From c9e3e430ea5fff06584554ed15750b448b7c6d87 Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 15 Mar 2017 16:10:05 +0100 Subject: [PATCH 01/23] [visualize.traj] new paramter projection for argmax correlations --- molpx/visualize.py | 60 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/molpx/visualize.py b/molpx/visualize.py index 69dd2d6..7f03f54 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -7,7 +7,10 @@ import numpy as _np from .bmutils import link_ax_w_pos_2_nglwidget as _link_ax_w_pos_2_nglwidget, \ data_from_input as _data_from_input, \ - smooth_geom as _smooth_geom + smooth_geom as _smooth_geom,\ + most_corr_info as _try_to_get_most_corr_feat, \ + re_warp as _re_warp + from . import generate from matplotlib import pylab as _plt @@ -98,6 +101,7 @@ def traj(MD_trajectories, dt = 1.0, tunits = 'ns', traj_selection = None, + projection = None, ): r"""Link one or many :obj:`projected trajectories`, [Y_0(t), Y_1(t)...], with the :obj:`MD_trajectories` that originated them. @@ -157,6 +161,17 @@ def traj(MD_trajectories, Don't plot all trajectories but only few of them. The default None implies that all trajs will be plotted. Note: the data used for the FES will always include all trajectories, regardless of this value + projection : object that generated the projection, default is None + The projected coordinates may come from a variety of sources. When working with :ref:`pyemma` a number of objects + might have generated this projection, like a + * :obj:`pyemma.coordinates.transform.TICA` or a + * :obj:`pyemma.coordinates.transform.PCA` or a + + Pass this object along and observe and the features that are most correlated with the projections + will be plotted for the active trajectory, allowing the user to establish a visual connection between the + projected coordinate and the original features (distances, angles, contacts etc) + + Returns --------- @@ -223,10 +238,22 @@ def traj(MD_trajectories, ylims[1, ii] = _np.max([idata[:,ii].max() for idata in data]) ylabels = ['$\mathregular{proj_%u}$'%ii for ii in proj_idxs] + # Do we have usable projection information? + __, most_corr_vals, most_corr_labels, out_feats = _try_to_get_most_corr_feat(projection, geoms=geoms, proj_idxs=proj_idxs) + if out_feats != []: + # Then extend the trajectory selection to include the active trajectory twice + traj_selection = _np.insert(traj_selection, + _np.argwhere([active_traj==ii for ii in traj_selection]).squeeze(), + active_traj) + myfig, myax = _plt.subplots(len(traj_selection)*2,1, sharex=True, figsize=(7, len(data)*2*panel_height)) myax = myax.reshape(len(traj_selection), -1) + + # Initialize some things widget = None + projections_plotted = 0 + feature_axis = [] for jj, time, jdata, jax in zip(traj_selection, [times[jj] for jj in traj_selection], [data[jj] for jj in traj_selection], @@ -234,17 +261,36 @@ def traj(MD_trajectories, for ii, (idata, iax) in enumerate(zip(jdata.T, jax)): data_sample =_np.vstack((time, idata)).T - iax.plot(time, idata) - if jj == active_traj: - widget = sample(data_sample, geoms.superpose(geoms[0]), iax, clear_lines=False, widget=widget) - # Axis-Cosmetics + # Inactive trajectories, act normal + if jj != active_traj: + iax.plot(time, idata) + # Active trajectory, distinguish between projection and feature + else: + if projections_plotted in [0,1]: #projection + iax.plot(time, idata) + widget = sample(data_sample, geoms.superpose(geoms[0]), iax, clear_lines=False, widget=widget) + projections_plotted += 1 + else: #feature + feature_axis.append(jj) + iax.plot(time, out_feats[ii]) + # matplotlib mysteries + #iax.legend('%4.2f'%most_corr_vals[ii]) # doesn't work + #iax.legend('a') # works + + # Axis-specific Cosmetics if ii == 0: iax.set_title('traj %u'%jj) - iax.set_ylabel(ylabels[ii]) + if jj not in feature_axis: + iax.set_ylabel(ylabels[ii]) + else: + iax.set_ylabel('\n'.join(_re_warp(most_corr_labels[ii], 10))) iax.set_xlim([tmin, tmax]) if sharey_traj: - iax.set_ylim(ylims[:,ii]+[-1,1]*_np.diff(ylims[:,ii])*.1) + if jj not in feature_axis: + iax.set_ylim(ylims[:,ii]+[-1,1]*_np.diff(ylims[:,ii])*.1) + + # General cosmetics iax.set_xlabel(tunits) if plot_FES: From c0842ce2272278e400556f822cfe667eafa8cdf4 Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 15 Mar 2017 17:44:08 +0100 Subject: [PATCH 02/23] [visualize.traj] default units is frames. correlated traj gets dot-marker, minor bugifxes --- molpx/visualize.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/molpx/visualize.py b/molpx/visualize.py index 7f03f54..a84a5ab 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -13,7 +13,7 @@ from . import generate -from matplotlib import pylab as _plt +from matplotlib import pylab as _plt, rcParams as _rcParams import nglview as _nglview import mdtraj as _md @@ -99,7 +99,7 @@ def traj(MD_trajectories, panel_height = 1, sharey_traj=True, dt = 1.0, - tunits = 'ns', + tunits = 'frames', traj_selection = None, projection = None, ): @@ -154,7 +154,7 @@ def traj(MD_trajectories, dt : float, default is 1.0 Physical time-unit equivalent to one frame of the :obj:`projected_trajectories` - tunits : str, default is 'ns' + tunits : str, default is 'frames' Name of the physical time unit provided in :obj:`dt` traj_selection : None, int, iterable of ints, default is None @@ -189,8 +189,8 @@ def traj(MD_trajectories, """ - assert len(proj_idxs) == 2 - + if isinstance(proj_idxs, int): + proj_idxs = [proj_idxs] # Parse input data = [iY[:,proj_idxs] for iY in _data_from_input(projected_trajectories)] @@ -233,7 +233,7 @@ def traj(MD_trajectories, # For later axes-cosmetics tmax, tmin = _np.max([time[-1] for time in times]), _np.min([time[0] for time in times]) ylims = _np.zeros((2,2)) - for ii in range(2): + for ii in proj_idxs: ylims[0, ii] = _np.min([idata[:,ii].min() for idata in data]) ylims[1, ii] = _np.max([idata[:,ii].max() for idata in data]) ylabels = ['$\mathregular{proj_%u}$'%ii for ii in proj_idxs] @@ -247,7 +247,7 @@ def traj(MD_trajectories, active_traj) - myfig, myax = _plt.subplots(len(traj_selection)*2,1, sharex=True, figsize=(7, len(data)*2*panel_height)) + myfig, myax = _plt.subplots(len(traj_selection)*len(proj_idxs),1, sharex=True, figsize=(7, len(data)*len(proj_idxs)*panel_height), squeeze=False) myax = myax.reshape(len(traj_selection), -1) # Initialize some things @@ -267,13 +267,19 @@ def traj(MD_trajectories, iax.plot(time, idata) # Active trajectory, distinguish between projection and feature else: - if projections_plotted in [0,1]: #projection + if projections_plotted < len(proj_idxs): #projection iax.plot(time, idata) - widget = sample(data_sample, geoms.superpose(geoms[0]), iax, clear_lines=False, widget=widget) + widget = sample(data_sample, geoms.superpose(geoms[0]), iax, + clear_lines=False, widget=widget, + link_with_lines='v') projections_plotted += 1 else: #feature feature_axis.append(jj) - iax.plot(time, out_feats[ii]) + fdata_sample = _np.vstack((time, out_feats[ii])).T + widget = sample(fdata_sample, geoms.superpose(geoms[0]), iax, + clear_lines=False, widget=widget, + link_with_lines=False) + iax.plot(time,out_feats[ii], zorder=0) # matplotlib mysteries #iax.legend('%4.2f'%most_corr_vals[ii]) # doesn't work #iax.legend('a') # works @@ -284,7 +290,7 @@ def traj(MD_trajectories, if jj not in feature_axis: iax.set_ylabel(ylabels[ii]) else: - iax.set_ylabel('\n'.join(_re_warp(most_corr_labels[ii], 10))) + iax.set_ylabel('\n'.join(_re_warp(most_corr_labels[ii], 16)), fontsize=int(_rcParams['font.size']/2)) iax.set_xlim([tmin, tmax]) if sharey_traj: if jj not in feature_axis: @@ -294,6 +300,10 @@ def traj(MD_trajectories, iax.set_xlabel(tunits) if plot_FES: + if len(proj_idxs)<2: + raise NotImplementedError('Can only plot 2D FES if more than one projection idxs has been ' + 'specificed, but only got %s. \n In the future a 1D histogramm will ' + 'be shown.'%proj_idxs) h, (x, y) = _np.histogramdd(_np.vstack(data), bins=50) irange = _np.hstack((x[[0,-1]], y[[0,-1]])) _plt.figure() From 9b86b4fce74db6f2b4690cfd5517a51fba91ff08 Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 15 Mar 2017 18:15:21 +0100 Subject: [PATCH 03/23] [notebook] added traj(projection=tica) section --- molpx/notebooks/Projection_Explorer.ipynb | 2196 +++++++++++++++++++-- 1 file changed, 2000 insertions(+), 196 deletions(-) diff --git a/molpx/notebooks/Projection_Explorer.ipynb b/molpx/notebooks/Projection_Explorer.ipynb index eb65557..f5bd144 100644 --- a/molpx/notebooks/Projection_Explorer.ipynb +++ b/molpx/notebooks/Projection_Explorer.ipynb @@ -2,7 +2,10 @@ "cells": [ { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "deletable": true, + "editable": true + }, "source": [ "# molPX intro\n", "
 \n",
@@ -22,7 +25,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Input types and typical usecase\n",
     "The typical usecase is having molecular dynamics (MD) simulation data in form of trajectory files with extensions like `.xtc, .dcd` etc and the associated molecular topology as a `.pdb` or `.gro` file. \n",
@@ -32,15 +38,17 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": 2,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
     "top = 'notebooks/data/bpti-c-alpha_centered.pdb'\n",
     "MD_trajfiles = ['notebooks/data/c-alpha_centered.stride.1000.xtc',\n",
-    "                'notebooks/data/c-alpha_centered.stride.1000.reversed.xtc',\n",
+    "               'notebooks/data/c-alpha_centered.stride.1000.reversed.xtc',\n",
     "                'notebooks/data/c-alpha_centered.stride.1000.halved.xtc'\n",
     "               ]\n",
     "\n",
@@ -59,16 +67,21 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "**However**, `molpx` relies heavily on the awesome [`mdtraj`](http://www.mdtraj.org) module for dealing with molecular structures, and so most of `molpx`'s functions accept also `Trajectory`-type objects (native to `mdtraj`) as alternative inputs. "
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 2,
+   "execution_count": 3,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -78,29 +91,33 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "The same idea applies to the input of projected trajectories: `molpx` can take the filenames as inputs (`.npy`, `.dat`, `.txt` etc) or deal directly with `numpy.ndarray` objects. \n",
     "\n",
-    "** These alternative, \"from-memory\" input modes (`md.Trajectory` and `np.ndarray` objects) avoid forcing the user to read from file everytime an API function is called, saving `I/O` overhead**\n",
+    "** These alternative, \"from-memory\" input modes (`md.Trajectory` and `np.ndarray` objects) avoid forcing the user to read from file everytime an API function is called, saving I/O overhead**\n",
     "\n",
     "The following cell either reads or generates projected trajectory files for this demonstration. In a real usecase this step (done here using TICA) might not be needed, given that the user might have generated the projected trajectory elsewhere:"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": 4,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
-    "# Perform TICA or read from file directly if already .npy-files already exist\n",
+    "# Perform TICA or read from file directly if already .npy-files exist\n",
     "Y_filenames = [ff.replace('.xtc','.Y.npy') for ff in MD_trajfiles]\n",
     "try:        \n",
     "    Y = [np.load(ff) for ff in Y_filenames]\n",
     "except:\n",
-    "    import pyemma\n",
     "    feat = pyemma.coordinates.featurizer(top)\n",
     "    pairs = feat.pairs(range(feat.topology.n_atoms)[::2])\n",
     "    feat.add_distances(pairs)\n",
@@ -112,7 +129,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Visualize a FES and the molecular structures behind it\n",
     "Execute the following cell and click either on the FES or on the slidebar. Some input parameters have been comented out for you to try out different modes of input (disk vs memory) as well as different projection indices:"
@@ -120,11 +140,20 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": 5,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "The installed widget Javascript is the wrong version.\n"
+     ]
+    },
     {
      "data": {
       "application/javascript": [
@@ -919,7 +948,8 @@
      "output_type": "stream",
      "text": [
       "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/matplotlib/cbook.py:136: MatplotlibDeprecationWarning: The spectral and spectral_r colormap was deprecated in version 2.0. Use nipy_spectral and nipy_spectral_r instead.\n",
-      "  warnings.warn(message, mplDeprecation, stacklevel=1)\n"
+      "  warnings.warn(message, mplDeprecation, stacklevel=1)\n",
+      "The installed widget Javascript is the wrong version.\n"
      ]
     }
    ],
@@ -939,23 +969,29 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Visualize trajectories, FES and molecular structures\n",
     "The user can sample structures as they occurr in sequence in the actual trajectory. Depending on the size of the dataset, this can be very time consuming, particularly if data is being read from disk. \n",
     "\n",
     "In this example, try changing `MD_trajfiles` to `MD_list` and/or changing `Y_filenames` to simply `Y` and see if it helps.\n",
     "\n",
-    "Furthermore, the objects in memory can be strided down to fewer frames **before** being parsed to the method. To stride objects being read from the dist, use the `stride` parameter. \n",
+    "Furthermore, the objects in memory can be strided down to fewer frames **before** being parsed to the method. To stride objects being read from the disk, use the `stride` parameter. \n",
     "\n",
     "Other commented parameters provide more control on the output of `visualize.traj`. Uncomment them and see what happens"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": 6,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true,
+    "scrolled": false
    },
    "outputs": [
     {
@@ -1738,7 +1774,7 @@
     {
      "data": {
       "text/html": [
-       ""
+       ""
       ],
       "text/plain": [
        ""
@@ -2527,7 +2563,7 @@
     {
      "data": {
       "text/html": [
-       ""
+       ""
       ],
       "text/plain": [
        ""
@@ -2540,22 +2576,25 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "/home/mi/gph82/SOURCE_gph82/python/molPX/molpx/visualize.py:255: RuntimeWarning: divide by zero encountered in log\n",
-      "  _plt.contourf(-_np.log(h).T, extent=irange)\n"
+      "/home/mi/gph82/SOURCE_gph82/python/molPX/molpx/visualize.py:311: RuntimeWarning: divide by zero encountered in log\n",
+      "  _plt.contourf(-_np.log(h).T, extent=irange)\n",
+      "The installed widget Javascript is the wrong version.\n"
      ]
     }
    ],
    "source": [
-    "proj_stride=5\n",
     "__, myfig, iwd, __ = molpx.visualize.traj(MD_trajfiles,     \n",
     "                                          top,                                                                                                                              \n",
-    "                                          Y_filenames,                                          \n",
+    "                                          Y,\n",
+    "                                          #Y_filenames,                                          \n",
     "                                          plot_FES = True,                                        \n",
-    "                                          dt = dt*1e-6, tunits='ms',                                           \n",
-    "                                          #active_traj=2,\n",
-    "                                          #traj_selection = [0, 2],\n",
+    "                                          dt = dt*1e-6, tunits='ms',    \n",
+    "                                          active_traj=1,\n",
+    "                                          #traj_selection = 0,\n",
+    "                                          #sharey_traj=False,\n",
     "                                          #max_frames=100,\n",
-    "                                          #proj_idxs=[0,2],  \n",
+    "                                          proj_idxs=[0,1],                                           \n",
+    "                                          panel_height=2,\n",
     "                          )\n",
     "myfig.tight_layout()\n",
     "iwd"
@@ -2563,7 +2602,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Intermediate steps: using molpx to generate a regspace sample of the data\n",
     "See the documentation of `molpx.generate.sample` to find out about all possible options:\n",
@@ -2574,19 +2616,28 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 7,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "The installed widget Javascript is the wrong version.\n"
+     ]
+    },
     {
      "data": {
       "text/plain": [
        "((192, 2),\n",
-       " )"
+       " )"
       ]
      },
-     "execution_count": 6,
+     "execution_count": 7,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -2604,7 +2655,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Link the PDF plot with the sampled structures and visually explore the FES \n",
     "Click either on the plot or on the widget slidebar: they're connected! "
@@ -2612,9 +2666,11 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 8,
    "metadata": {
     "collapsed": false,
+    "deletable": true,
+    "editable": true,
     "scrolled": true
    },
    "outputs": [
@@ -3398,7 +3454,7 @@
     {
      "data": {
       "text/html": [
-       ""
+       ""
       ],
       "text/plain": [
        ""
@@ -3411,7 +3467,8 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/ipykernel/__main__.py:4: RuntimeWarning: divide by zero encountered in log\n"
+      "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/ipykernel/__main__.py:4: RuntimeWarning: divide by zero encountered in log\n",
+      "The installed widget Javascript is the wrong version.\n"
      ]
     }
    ],
@@ -3434,18 +3491,32 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Paths samples along the different projections (=axis)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 9,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
-   "outputs": [],
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "The installed widget Javascript is the wrong version.\n",
+      "The installed widget Javascript is the wrong version.\n"
+     ]
+    }
+   ],
    "source": [
     "paths_dict, idata = molpx.generate.projection_paths(#MD_list, \n",
     "                                                    MD_trajfiles, \n",
@@ -3462,7 +3533,10 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "## Link the PDF plot with the sampled paths/structures and visually explore the coordinates (separately). \n",
     "Click either on the plot or on the widget slidebar: they're connected! You can change the type of path between min_rmsd or min_disp and you can also change the coordinate sampled (0 or 1)\n"
@@ -3470,9 +3544,11 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 10,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [],
    "source": [
@@ -3490,9 +3566,11 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 11,
    "metadata": {
     "collapsed": false,
+    "deletable": true,
+    "editable": true,
     "scrolled": false
    },
    "outputs": [
@@ -4276,7 +4354,7 @@
     {
      "data": {
       "text/html": [
-       ""
+       ""
       ],
       "text/plain": [
        ""
@@ -4290,7 +4368,8 @@
      "output_type": "stream",
      "text": [
       "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/ipykernel/__main__.py:3: RuntimeWarning: divide by zero encountered in log\n",
-      "  app.launch_new_instance()\n"
+      "  app.launch_new_instance()\n",
+      "The installed widget Javascript is the wrong version.\n"
      ]
     }
    ],
@@ -4312,55 +4391,58 @@
   },
   {
    "cell_type": "markdown",
-   "metadata": {},
+   "metadata": {
+    "deletable": true,
+    "editable": true
+   },
    "source": [
     "# Interaction with ```PyEMMA```\n",
-    "`molpx` is using many methods of the `coordinates` submodule of `PyEMMA`, and thus it also understands some of `PyEMMA`'s classes as input (for the moment, only clustering).\n",
-    "\n",
-    "## Use a clustering object as input \n",
-    "If the dataset has already been clustered, and it is **that** clustering that the user wants to explore, `molpx.generate.sample` can take this clustering object as an input instead of the \n",
-    "the projected trajectories:"
+    "`molpx` is using many methods of the `coordinates` submodule of `PyEMMA`, and thus it also understands some of `PyEMMA`'s classes as input (like clustering objects or streaming transformers).\n",
+    "## Using the TICA object to visualize the most correlated input features\n",
+    "If the projected coordinates come from a TICA (or PCA) transformation, and the TICA object is available in memory\n",
+    "`molpx.visualize.traj` can make use of correlation information to display not only the projected coordinates (i.e the TICs, in this case), but also the \"original\" input features behind it"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 24,
    "metadata": {
     "collapsed": false
    },
    "outputs": [
     {
-     "name": "stdout",
+     "name": "stderr",
      "output_type": "stream",
      "text": [
-      "08-03-17 17:03:25 pyemma.coordinates.clustering.kmeans.KmeansClustering[4] INFO     Cluster centers converged after 6 steps.\n"
+      "The installed widget Javascript is the wrong version.\n",
+      "The installed widget Javascript is the wrong version.\n"
      ]
     }
    ],
    "source": [
-    "# Do \"some\" clustering\n",
-    "clkmeans = pyemma.coordinates.cluster_kmeans([iY[:,:2] for iY in Y], 5)"
+    "# Force the TICA computation\n",
+    "feat = pyemma.coordinates.featurizer(top)\n",
+    "pairs = feat.pairs(range(feat.topology.n_atoms)[::2])\n",
+    "feat.add_distances(pairs)\n",
+    "src  = pyemma.coordinates.source(MD_trajfiles, features=feat)\n",
+    "tica = pyemma.coordinates.tica(src, lag=10, dim=3)\n",
+    "Y = tica.get_output()   "
    ]
   },
   {
-   "cell_type": "code",
-   "execution_count": 12,
-   "metadata": {
-    "collapsed": false
-   },
-   "outputs": [],
+   "cell_type": "markdown",
+   "metadata": {},
    "source": [
-    "data_sample, geoms = molpx.generate.sample(MD_trajfiles, top, clkmeans, \n",
-    "                                     n_geom_samples=50, \n",
-    "                                     #keep_all_samples=True # read the doc for this argument\n",
-    "                                    )"
+    "The cell below looks pretty similar to the first `molpx.visualize.traj` call, only now we're also parssing along\n",
+    "the tica object itself. Can you spot the differences?"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 26,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "scrolled": false
    },
    "outputs": [
     {
@@ -5143,7 +5225,7 @@
     {
      "data": {
       "text/html": [
-       ""
+       ""
       ],
       "text/plain": [
        ""
@@ -5152,58 +5234,6 @@
      "metadata": {},
      "output_type": "display_data"
     },
-    {
-     "name": "stderr",
-     "output_type": "stream",
-     "text": [
-      "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/ipykernel/__main__.py:6: RuntimeWarning: divide by zero encountered in log\n"
-     ]
-    }
-   ],
-   "source": [
-    "# Plot clusters\n",
-    "plt.figure(figsize=(7,7))\n",
-    "plt.plot(clkmeans.clustercenters[:,0], clkmeans.clustercenters[:,1],' ok')\n",
-    "# FES as background is optional (change the bool to False)\n",
-    "if True:\n",
-    "    plt.contourf(x[:-1], y[:-1], -np.log(h.T), alpha=.50)\n",
-    "\n",
-    "# Link the clusters positions with the molecular structures\n",
-    "iwdg = molpx.visualize.sample(data_sample, \n",
-    "                              geoms.superpose(geoms[0]),                             \n",
-    "                              plt.gca(), \n",
-    "                              clear_lines=False,\n",
-    "                              #plot_path=True\n",
-    "                            )\n",
-    "iwdg"
-   ]
-  },
-  {
-   "cell_type": "markdown",
-   "metadata": {},
-   "source": [
-    "## Visual representations for MSMs\n",
-    "Visually inspect the network behind an MSM"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 14,
-   "metadata": {
-    "collapsed": false
-   },
-   "outputs": [],
-   "source": [
-    "MSM = pyemma.msm.estimate_markov_model(clkmeans.dtrajs, 20)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 15,
-   "metadata": {
-    "collapsed": false
-   },
-   "outputs": [
     {
      "data": {
       "application/javascript": [
@@ -5984,7 +6014,7 @@
     {
      "data": {
       "text/html": [
-       ""
+       ""
       ],
       "text/plain": [
        ""
@@ -5997,29 +6027,29 @@
      "name": "stderr",
      "output_type": "stream",
      "text": [
-      "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/ipykernel/__main__.py:11: RuntimeWarning: divide by zero encountered in log\n"
+      "/home/mi/gph82/SOURCE_gph82/python/molPX/molpx/visualize.py:311: RuntimeWarning: divide by zero encountered in log\n",
+      "  _plt.contourf(-_np.log(h).T, extent=irange)\n",
+      "The installed widget Javascript is the wrong version.\n"
      ]
     }
    ],
    "source": [
-    "plt.figure(figsize=(7,7))\n",
-    "\n",
-    "ax, pos  = pyemma.plots.plot_markov_model(MSM.P, \n",
-    "                                          minflux=5e-4, \n",
-    "                                          arrow_labels=None,\n",
-    "                                          ax=plt.gca(), \n",
-    "                                          arrow_curvature = 2, show_frame=True,\n",
-    "                                          pos=clkmeans.clustercenters)\n",
-    "# Add a background if wanted\n",
-    "h, (x, y) = np.histogramdd(np.vstack(Y)[:,:2], weights=np.hstack(MSM.trajectory_weights()),  bins=50)\n",
-    "plt.contourf(x[:-1], y[:-1], -np.log(h.T), cmap=\"jet\", alpha=.5, zorder=0)\n",
-    "plt.xlim(x[[0,-1]])\n",
-    "plt.xticks(np.unique(x.round()))\n",
-    "plt.yticks(np.unique(y.round()))\n",
-    "\n",
-    "plt.ylim(y[[0,-1]])\n",
-    "\n",
-    "iwd = molpx.visualize.sample(pos, geoms, plt.gca())\n",
+    "# Reuse the visualize.traj method with the tica object as input\n",
+    "__, myfig, iwd, __ = molpx.visualize.traj(MD_trajfiles,     \n",
+    "                                          top,                                                                                                                              \n",
+    "                                          Y,\n",
+    "                                          #Y_filenames,                                          \n",
+    "                                          plot_FES = True,                                        \n",
+    "                                          dt = dt*1e-6, tunits='ms',    \n",
+    "                                          active_traj=1,\n",
+    "                                          #traj_selection = 0,\n",
+    "                                          #sharey_traj=False,\n",
+    "                                          #max_frames=100,\n",
+    "                                          proj_idxs=[0,1],                                           \n",
+    "                                          panel_height=2,\n",
+    "                                          projection=tica,\n",
+    "                          )\n",
+    "myfig.tight_layout()\n",
     "iwd"
    ]
   },
@@ -6027,77 +6057,1836 @@
    "cell_type": "markdown",
    "metadata": {},
    "source": [
-    "## TPT Reactive Pathway Representation"
+    "## Use a clustering object as input \n",
+    "If the dataset has already been clustered, and it is **that** clustering that the user wants to explore, `molpx.generate.sample` can take this clustering object as an input instead of the \n",
+    "the projected trajectories:"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 16,
+   "execution_count": 12,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
-     "data": {
-      "text/plain": [
-       "123"
-      ]
-     },
-     "execution_count": 16,
-     "metadata": {},
-     "output_type": "execute_result"
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "15-03-17 18:09:27 pyemma.coordinates.clustering.kmeans.KmeansClustering[4] INFO     Cluster centers converged after 9 steps.\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "The installed widget Javascript is the wrong version.\n",
+      "The installed widget Javascript is the wrong version.\n"
+     ]
     }
    ],
    "source": [
-    "# Do an MSM with a realistic number of clustercenters\n",
-    "cl_many = pyemma.coordinates.cluster_regspace([iY[:,:2] for iY in Y], dmin=.25)\n",
-    "M = pyemma.msm.estimate_markov_model(cl_many.dtrajs, 20)\n",
-    "cl_many.n_clusters"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 17,
-   "metadata": {
-    "collapsed": false
-   },
-   "outputs": [],
-   "source": [
-    "# Use this object to sample geometries\n",
-    "pos, geom = molpx.generate.sample(MD_trajfiles, top, cl_many)"
+    "# Do \"some\" clustering\n",
+    "clkmeans = pyemma.coordinates.cluster_kmeans([iY[:,:2] for iY in Y], 5)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 18,
+   "execution_count": 13,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
    },
    "outputs": [
     {
-     "name": "stdout",
+     "name": "stderr",
      "output_type": "stream",
      "text": [
-      "[-0.18704125 -0.77366424] [ 6.71851349  0.03159955]\n"
+      "The installed widget Javascript is the wrong version.\n"
      ]
     }
    ],
    "source": [
-    "# Find the most representative microstate of each \n",
-    "# and least populated macrostate\n",
-    "M.pcca(3)\n",
-    "dens_max_i = [distro.argmax() for distro in M.metastable_distributions]\n",
-    "A = np.argmax([M.stationary_distribution[iset].sum() for iset in M.metastable_sets])\n",
-    "B = np.argmin([M.stationary_distribution[iset].sum() for iset in M.metastable_sets])\n",
-    "print(cl_many.clustercenters[dens_max_i[A]],\n",
-    "      cl_many.clustercenters[dens_max_i[B]])"
+    "data_sample, geoms = molpx.generate.sample(MD_trajfiles, top, clkmeans, \n",
+    "                                     n_geom_samples=50, \n",
+    "                                     #keep_all_samples=True # read the doc for this argument\n",
+    "                                    )"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 19,
+   "execution_count": 14,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "deletable": true,
+    "editable": true
+   },
+   "outputs": [
+    {
+     "data": {
+      "application/javascript": [
+       "/* Put everything inside the global mpl namespace */\n",
+       "window.mpl = {};\n",
+       "\n",
+       "\n",
+       "mpl.get_websocket_type = function() {\n",
+       "    if (typeof(WebSocket) !== 'undefined') {\n",
+       "        return WebSocket;\n",
+       "    } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+       "        return MozWebSocket;\n",
+       "    } else {\n",
+       "        alert('Your browser does not have WebSocket support.' +\n",
+       "              'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+       "              'Firefox 4 and 5 are also supported but you ' +\n",
+       "              'have to enable WebSockets in about:config.');\n",
+       "    };\n",
+       "}\n",
+       "\n",
+       "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+       "    this.id = figure_id;\n",
+       "\n",
+       "    this.ws = websocket;\n",
+       "\n",
+       "    this.supports_binary = (this.ws.binaryType != undefined);\n",
+       "\n",
+       "    if (!this.supports_binary) {\n",
+       "        var warnings = document.getElementById(\"mpl-warnings\");\n",
+       "        if (warnings) {\n",
+       "            warnings.style.display = 'block';\n",
+       "            warnings.textContent = (\n",
+       "                \"This browser does not support binary websocket messages. \" +\n",
+       "                    \"Performance may be slow.\");\n",
+       "        }\n",
+       "    }\n",
+       "\n",
+       "    this.imageObj = new Image();\n",
+       "\n",
+       "    this.context = undefined;\n",
+       "    this.message = undefined;\n",
+       "    this.canvas = undefined;\n",
+       "    this.rubberband_canvas = undefined;\n",
+       "    this.rubberband_context = undefined;\n",
+       "    this.format_dropdown = undefined;\n",
+       "\n",
+       "    this.image_mode = 'full';\n",
+       "\n",
+       "    this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/ipykernel/__main__.py:11: RuntimeWarning: divide by zero encountered in log\n", + "The installed widget Javascript is the wrong version.\n" + ] + } + ], + "source": [ + "plt.figure(figsize=(7,7))\n", + "\n", + "ax, pos = pyemma.plots.plot_markov_model(MSM.P, \n", + " minflux=5e-4, \n", + " arrow_labels=None,\n", + " ax=plt.gca(), \n", + " arrow_curvature = 2, show_frame=True,\n", + " pos=clkmeans.clustercenters)\n", + "# Add a background if wanted\n", + "h, (x, y) = np.histogramdd(np.vstack(Y)[:,:2], weights=np.hstack(MSM.trajectory_weights()), bins=50)\n", + "plt.contourf(x[:-1], y[:-1], -np.log(h.T), cmap=\"jet\", alpha=.5, zorder=0)\n", + "plt.xlim(x[[0,-1]])\n", + "plt.xticks(np.unique(x.round()))\n", + "plt.yticks(np.unique(y.round()))\n", + "\n", + "plt.ylim(y[[0,-1]])\n", + "\n", + "iwd = molpx.visualize.sample(pos, geoms, plt.gca())\n", + "iwd" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "## TPT Reactive Pathway Representation" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "The installed widget Javascript is the wrong version.\n" + ] + }, + { + "data": { + "text/plain": [ + "123" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Do an MSM with a realistic number of clustercenters\n", + "cl_many = pyemma.coordinates.cluster_regspace([iY[:,:2] for iY in Y], dmin=.25)\n", + "M = pyemma.msm.estimate_markov_model(cl_many.dtrajs, 20)\n", + "cl_many.n_clusters" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "# Use this object to sample geometries\n", + "pos, geom = molpx.generate.sample(MD_trajfiles, top, cl_many)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-0.18704125 -0.77366424] [ 6.71851349 0.03159955]\n" + ] + } + ], + "source": [ + "# Find the most representative microstate of each \n", + "# and least populated macrostate\n", + "M.pcca(3)\n", + "dens_max_i = [distro.argmax() for distro in M.metastable_distributions]\n", + "A = np.argmax([M.stationary_distribution[iset].sum() for iset in M.metastable_sets])\n", + "B = np.argmin([M.stationary_distribution[iset].sum() for iset in M.metastable_sets])\n", + "print(cl_many.clustercenters[dens_max_i[A]],\n", + " cl_many.clustercenters[dens_max_i[B]])" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -6108,9 +7897,11 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "metadata": { "collapsed": false, + "deletable": true, + "editable": true, "scrolled": true }, "outputs": [], @@ -6121,9 +7912,11 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 23, "metadata": { - "collapsed": false + "collapsed": false, + "deletable": true, + "editable": true }, "outputs": [ { @@ -6906,7 +8699,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -6922,6 +8715,16 @@ "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/ipykernel/__main__.py:2: RuntimeWarning: divide by zero encountered in log\n", " from ipykernel import kernelapp as app\n" ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ @@ -6931,15 +8734,16 @@ " geom[sample_path].superpose(geom[sample_path[0]]), plt.gca(), \n", " plot_path=True,\n", " )\n", - "plt.scatter(*cl_many.clustercenters.T, alpha=.25)\n", - "iwd" + "plt.scatter(*cl_many.clustercenters.T, alpha=.25)\n" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { - "collapsed": true + "collapsed": true, + "deletable": true, + "editable": true }, "outputs": [], "source": [ @@ -6952,7 +8756,7 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python [default]", + "display_name": "Python 3", "language": "python", "name": "python3" }, From 1895bf6b70b0bca61202f9f6abce2fc76bc3ebe5 Mon Sep 17 00:00:00 2001 From: gph82 Date: Thu, 16 Mar 2017 15:58:41 +0100 Subject: [PATCH 04/23] [visualize & bmutils] allow for more than one feature to be analysed and visualized. Also better visuals --- molpx/bmutils.py | 117 +- molpx/notebooks/Projection_Explorer.ipynb | 8399 ++------------------- molpx/visualize.py | 105 +- 3 files changed, 807 insertions(+), 7814 deletions(-) diff --git a/molpx/bmutils.py b/molpx/bmutils.py index 182f751..0c36f76 100644 --- a/molpx/bmutils.py +++ b/molpx/bmutils.py @@ -17,6 +17,20 @@ from pyemma.util.discrete_trajectories import index_states as _index_states from scipy.spatial import cKDTree as _cKDTree +def matplotlib_colors_no_blue(): + # Until we get the colorcyle thing working, this is a workaround: + # http://stackoverflow.com/questions/13831549/get-matplotlib-color-cycle-state + cc = ['green', + 'red', + 'cyan', + 'magenta', + 'yellow', + 'black', + 'white'] + for ii in range(3): + cc += cc # this grows quickly + return cc + def re_warp(array_in, lengths): """Return iterable ::py:obj:array_in as a list of arrays, each one with the length specified in lengths @@ -817,7 +831,7 @@ def smooth_geom(geom, n, geom_data=None, superpose=True, symmetric=True): else: return geom_out, data_out -def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None): +def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None, n_args=1): r""" return information about the most correlated features from a `:obj:pyemma.coodrinates.transformer` object @@ -840,17 +854,19 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None The prefix with which to prepend the labels of the most correlated features. If left to None, the feature description found in :obj:`correlation_input` will be used (if available) + n_args : int, default is 1 + Number of argmax correlation to return for each feature. Returns ------- - most_corr_idxs : list of ints - List of with the index of the feature that most correlates with the projected coordinates, for each + most_corr_idxs : list of lists of integers + List of lists with the first :obj:`n_args` indices of the features that most correlate with the projected coordinates, for each coordinate specified in :obj:`proj_idxs` - most_corr_vals : list of floats - List with the correlation values [-1,1] belonging to the feature indices in :obj:`most_corr_idxs' + most_corr_vals : list of lists of floats + List with lists of correlation values (e [-1,1]) belonging to the feature indices in :obj:`most_corr_idxs' - most_corr_labels : list of strings + most_corr_labels : list lists of strings The labels of the most correlated features. If a string was parsed as prefix in :obj:`feat_name`, these labels will be ['feat_name_%u'%i for i in most_corr_idxs']. Otherwise it will be the full feature description found in :obj:`pyemma.coordinates. @@ -859,16 +875,23 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None If :obj:`geom` was given, this will contain the most correlated feature evaluated for every frame for every projection in :obj:`proj_idxs`. Otherwise this will just be an empty list + most_corr_atom_idxs : list of lists of integers + In many cases, the most correlated feature can be represented visually by the atoms involved in defining it, e.g + * two atoms for a distance + * three for an angle + * four for a dihedral + * etc. + If possible, most_corr_info will try to return these indices to be used later for visualization + - tested: false """ - #TODO: TEST #TODO: extend to other inputs most_corr_idxs = [] most_corr_vals = [] most_corr_feats = [] most_corr_labels = [] + most_corr_atom_idxs = [] if isinstance(proj_idxs, int): proj_idxs = [proj_idxs] @@ -884,15 +907,85 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None for ii in proj_idxs: icorr = correlation_input.feature_TIC_correlation[:, ii] - most_corr_idxs.append(_np.abs(icorr).argmax()) - most_corr_vals.append(icorr[most_corr_idxs[-1]]) + most_corr_idxs.append(_np.abs(icorr).argsort()[::-1][:n_args]) + most_corr_vals.append([icorr[jj] for jj in most_corr_idxs[-1]]) if geoms is not None: most_corr_feats.append(correlation_input.data_producer.featurizer.transform(geoms)[:, most_corr_idxs[-1]]) if isinstance(feat_name, str): istr = '$\mathregular{%s_{%%u}}$'%(feat_name, most_corr_idxs[-1]) elif feat_name is None: - istr = correlation_input.data_producer.featurizer.describe()[most_corr_idxs[-1]] + istr = [correlation_input.data_producer.featurizer.describe()[jj] for jj in most_corr_idxs[-1]] most_corr_labels.append(istr) - return most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats + if len(correlation_input.data_producer.featurizer.active_features) > 1: + pass + # TODO write a warning + else: + ifeat = correlation_input.data_producer.featurizer.active_features[0] + most_corr_atom_idxs.append(atom_idxs_from_feature(ifeat)[most_corr_idxs[-1]]) + + return most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs + +def atom_idxs_from_feature(ifeat): + r""" + Return the atom_indices that best represent this input feature + + Parameters + ---------- + + ifeat : input feature, :any:`pyemma.coordinates.featurizer` object + + Returns + ------- + + atom_indices : list with the atoms indices representative of this feature, whatever the feature + """ + from pyemma.coordinates.data.featurization.distances import DistanceFeature as _DF + if isinstance(ifeat, _DF): + return ifeat.distance_indexes + else: + # TODO write a warning? + return ifeat.distance_indexes + +def add_atom_idxs_widget(atom_idxs, widget, color_list=None): + r""" + provided a list of atom_idxs and a widget, try to represent them as well as possible in the widget + The user should not need to provide anything other than the atom indxs and the method decides how + best to represent them. Currently, that means: + * pairs of atoms are represented as distances + * everything else is ignored + + Parameters + ---------- + + atom_idxs : list of iterables of integers. If [], the method won't do anything + + widget : nglview widget on which to represent stuff + + color_list: list, default is None + list of colors to provide the representations with. The default None yields blue. + In principle, len(atom_idxs) should be == len(color_list), + but if your list is short it will just default to the last color. This way, color_list=['black'] will paint + all black regardless len(atom_idxs) + + Returns + ------- + widget : Input widget with the representations add + + """ + + if color_list is None: + color_list = ['blue']*len(atom_idxs) + elif isinstance(color_list, list) and len(color_list)" + "
" ], "text/plain": [ "" @@ -944,29 +1025,73 @@ "output_type": "display_data" }, { - "name": "stderr", + "name": "stdout", "output_type": "stream", "text": [ - "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/matplotlib/cbook.py:136: MatplotlibDeprecationWarning: The spectral and spectral_r colormap was deprecated in version 2.0. Use nipy_spectral and nipy_spectral_r instead.\n", - " warnings.warn(message, mplDeprecation, stacklevel=1)\n", - "The installed widget Javascript is the wrong version.\n" + "first_empty_axis [3]\n", + "last_empty_axis [9]\n", + "0 1 0\n", + "1 1 1\n", + "2 1 2\n" + ] + }, + { + "ename": "IndexError", + "evalue": "index 2 is out of bounds for axis 1 with size 2", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mpanel_height\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0mn_args\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0msharey_traj\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m )\n\u001b[1;32m 17\u001b[0m \u001b[0;31m#myfig.tight_layout()\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/mi/gph82/SOURCE_gph82/python/molPX/molpx/visualize.py\u001b[0m in \u001b[0;36mtraj\u001b[0;34m(MD_trajectories, MD_top, projected_trajectories, active_traj, max_frames, stride, proj_stride, proj_idxs, plot_FES, panel_height, sharey_traj, dt, tunits, traj_selection, projection, n_args)\u001b[0m\n\u001b[1;32m 307\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mir\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mic\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 308\u001b[0m \u001b[0;32mpass\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 309\u001b[0;31m \u001b[0mmyax\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mir\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mic\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtime\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mout_feats\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mic\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mkk\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'g'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 310\u001b[0m \u001b[0;31m#else: #feature\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 311\u001b[0m \u001b[0;31m#fdata_sample = _np.vstack((time, out_feats[ii])).T\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mIndexError\u001b[0m: index 2 is out of bounds for axis 1 with size 2" ] } ], "source": [ - "ax, fig, iwd, data_sample, geom = molpx.visualize.FES(\n", - " MD_list, \n", - " #MD_trajfiles, \n", - " top, \n", - " Y_filenames, \n", - " #Y, \n", - " nbins=50, \n", - " #proj_idxs=[1,2],\n", - " axlabel='TIC',\n", - " )\n", + "__, myfig, iwd, __ = molpx.visualize.traj(MD_trajfiles, \n", + " top, \n", + " Y,\n", + " #Y_filenames, \n", + " #plot_FES = True, \n", + " dt = dt*1e-6, tunits='ms', \n", + " active_traj=1,\n", + " traj_selection = 1,\n", + " #sharey_traj=False,\n", + " #max_frames=100,\n", + " projection = tica,\n", + " proj_idxs=[0, 1, 2],# 1, 2],#, 1, 2], \n", + " panel_height=1,\n", + " n_args=2,\n", + " sharey_traj=False,\n", + " )\n", + "#myfig.tight_layout()\n", "iwd" ] }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'adsfasdf' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0madsfasdf\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'adsfasdf' is not defined" + ] + } + ], + "source": [ + "adsfasdf" + ] + }, { "cell_type": "markdown", "metadata": { @@ -974,7759 +1099,469 @@ "editable": true }, "source": [ - "## Visualize trajectories, FES and molecular structures\n", - "The user can sample structures as they occurr in sequence in the actual trajectory. Depending on the size of the dataset, this can be very time consuming, particularly if data is being read from disk. \n", - "\n", - "In this example, try changing `MD_trajfiles` to `MD_list` and/or changing `Y_filenames` to simply `Y` and see if it helps.\n", - "\n", - "Furthermore, the objects in memory can be strided down to fewer frames **before** being parsed to the method. To stride objects being read from the disk, use the `stride` parameter. \n", + "# Intermediate steps: using molpx to generate a regspace sample of the data\n", + "See the documentation of `molpx.generate.sample` to find out about all possible options:\n", + "```\n", + "molpx.generate.sample(MD_trajectories, MD_top, projected_trajectories, proj_idxs=[0, 1], n_points=100, n_geom_samples=1, keep_all_samples=False, proj_stride=1, verbose=False, return_data=False)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "data_sample, geoms = molpx.generate.sample(#MD_list, \n", + " MD_trajfiles, \n", + " top, \n", + " #Y, \n", + " Y_filenames,\n", + " n_points=200 \n", + " )\n", + "data_sample.shape, geoms\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "## Link the PDF plot with the sampled structures and visually explore the FES \n", + "Click either on the plot or on the widget slidebar: they're connected! " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true, + "scrolled": true + }, + "outputs": [], + "source": [ + "# Replot the FES\n", + "plt.figure(figsize=(7,7))\n", + "h, (x,y) = np.histogramdd(np.vstack(Y)[:,:2], bins=50)\n", + "plt.contourf(x[:-1], y[:-1], -np.log(h.T), alpha=.50)\n", + "# Create the linked widget\n", + "linked_wdg = molpx.visualize.sample(data_sample, \n", + " geoms.superpose(geoms[0]), \n", + " plt.gca(), \n", + " clear_lines=True,\n", + " #plot_path=True\n", + " )\n", + "plt.plot(data_sample[:,0], data_sample[:,1],' ok', zorder=0)\n", + "# Show it\n", + "linked_wdg\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "# Paths samples along the different projections (=axis)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "paths_dict, idata = molpx.generate.projection_paths(#MD_list, \n", + " MD_trajfiles, \n", + " top, \n", + " Y_filenames,\n", + " #Y, # You can also directly give the data here\n", + " n_points=50,\n", + " proj_idxs=[0,1],\n", + " n_projs=3,\n", + " proj_dim = 3, \n", + " verbose=False, \n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "## Link the PDF plot with the sampled paths/structures and visually explore the coordinates (separately). \n", + "Click either on the plot or on the widget slidebar: they're connected! You can change the type of path between min_rmsd or min_disp and you can also change the coordinate sampled (0 or 1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "# Choose the coordinate and the tyep of path\n", + "coord = 1\n", + "#path_type = 'min_rmsd'\n", + "path_type = 'min_disp'\n", + "igeom = paths_dict[coord][path_type][\"geom\"]\n", + "ipath = paths_dict[coord][path_type][\"proj\"]\n", "\n", - "Other commented parameters provide more control on the output of `visualize.traj`. Uncomment them and see what happens" + "# Choose the proj_idxs for the path and the FES \n", + "# to be shown\n", + "proj_idxs = [0,1]" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "collapsed": false, "deletable": true, "editable": true, "scrolled": false }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/mi/gph82/SOURCE_gph82/python/molPX/molpx/visualize.py:311: RuntimeWarning: divide by zero encountered in log\n", - " _plt.contourf(-_np.log(h).T, extent=irange)\n", - "The installed widget Javascript is the wrong version.\n" - ] - } - ], - "source": [ - "__, myfig, iwd, __ = molpx.visualize.traj(MD_trajfiles, \n", - " top, \n", - " Y,\n", - " #Y_filenames, \n", - " plot_FES = True, \n", - " dt = dt*1e-6, tunits='ms', \n", - " active_traj=1,\n", - " #traj_selection = 0,\n", - " #sharey_traj=False,\n", - " #max_frames=100,\n", - " proj_idxs=[0,1], \n", - " panel_height=2,\n", - " )\n", - "myfig.tight_layout()\n", - "iwd" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "# Intermediate steps: using molpx to generate a regspace sample of the data\n", - "See the documentation of `molpx.generate.sample` to find out about all possible options:\n", - "```\n", - "molpx.generate.sample(MD_trajectories, MD_top, projected_trajectories, proj_idxs=[0, 1], n_points=100, n_geom_samples=1, keep_all_samples=False, proj_stride=1, verbose=False, return_data=False)\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "The installed widget Javascript is the wrong version.\n" - ] - }, - { - "data": { - "text/plain": [ - "((192, 2),\n", - " )" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "data_sample, geoms = molpx.generate.sample(#MD_list, \n", - " MD_trajfiles, \n", - " top, \n", - " #Y, \n", - " Y_filenames,\n", - " n_points=200 \n", - " )\n", - "data_sample.shape, geoms\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "## Link the PDF plot with the sampled structures and visually explore the FES \n", - "Click either on the plot or on the widget slidebar: they're connected! " - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true, - "scrolled": true - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/ipykernel/__main__.py:3: RuntimeWarning: divide by zero encountered in log\n", - " app.launch_new_instance()\n", - "The installed widget Javascript is the wrong version.\n" - ] - } - ], - "source": [ - "plt.figure(figsize=(7,7))\n", - "h, (x,y) = np.histogramdd(np.vstack(Y)[:,proj_idxs], bins=50)\n", - "plt.contourf(x[:-1], y[:-1], -np.log(h.T), alpha=.50)\n", - "\n", - "linked_wdg = molpx.visualize.sample(ipath[:,proj_idxs], \n", - " igeom.superpose(igeom[0]), \n", - " plt.gca(), \n", - " clear_lines=True,\n", - " n_smooth = 5, \n", - " plot_path=True, \n", - " #radius=True,\n", - " )\n", - "linked_wdg" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "# Interaction with ```PyEMMA```\n", - "`molpx` is using many methods of the `coordinates` submodule of `PyEMMA`, and thus it also understands some of `PyEMMA`'s classes as input (like clustering objects or streaming transformers).\n", - "## Using the TICA object to visualize the most correlated input features\n", - "If the projected coordinates come from a TICA (or PCA) transformation, and the TICA object is available in memory\n", - "`molpx.visualize.traj` can make use of correlation information to display not only the projected coordinates (i.e the TICs, in this case), but also the \"original\" input features behind it" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "The installed widget Javascript is the wrong version.\n", - "The installed widget Javascript is the wrong version.\n" - ] - } - ], - "source": [ - "# Force the TICA computation\n", - "feat = pyemma.coordinates.featurizer(top)\n", - "pairs = feat.pairs(range(feat.topology.n_atoms)[::2])\n", - "feat.add_distances(pairs)\n", - "src = pyemma.coordinates.source(MD_trajfiles, features=feat)\n", - "tica = pyemma.coordinates.tica(src, lag=10, dim=3)\n", - "Y = tica.get_output() " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The cell below looks pretty similar to the first `molpx.visualize.traj` call, only now we're also parssing along\n", - "the tica object itself. Can you spot the differences?" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "collapsed": false, - "scrolled": false - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/mi/gph82/SOURCE_gph82/python/molPX/molpx/visualize.py:311: RuntimeWarning: divide by zero encountered in log\n", - " _plt.contourf(-_np.log(h).T, extent=irange)\n", - "The installed widget Javascript is the wrong version.\n" - ] - } - ], - "source": [ - "# Reuse the visualize.traj method with the tica object as input\n", - "__, myfig, iwd, __ = molpx.visualize.traj(MD_trajfiles, \n", - " top, \n", - " Y,\n", - " #Y_filenames, \n", - " plot_FES = True, \n", - " dt = dt*1e-6, tunits='ms', \n", - " active_traj=1,\n", - " #traj_selection = 0,\n", - " #sharey_traj=False,\n", - " #max_frames=100,\n", - " proj_idxs=[0,1], \n", - " panel_height=2,\n", - " projection=tica,\n", - " )\n", - "myfig.tight_layout()\n", - "iwd" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Use a clustering object as input \n", - "If the dataset has already been clustered, and it is **that** clustering that the user wants to explore, `molpx.generate.sample` can take this clustering object as an input instead of the \n", - "the projected trajectories:" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "15-03-17 18:09:27 pyemma.coordinates.clustering.kmeans.KmeansClustering[4] INFO Cluster centers converged after 9 steps.\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "The installed widget Javascript is the wrong version.\n", - "The installed widget Javascript is the wrong version.\n" - ] - } - ], - "source": [ - "# Do \"some\" clustering\n", - "clkmeans = pyemma.coordinates.cluster_kmeans([iY[:,:2] for iY in Y], 5)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "The installed widget Javascript is the wrong version.\n" - ] - } - ], - "source": [ - "data_sample, geoms = molpx.generate.sample(MD_trajfiles, top, clkmeans, \n", - " n_geom_samples=50, \n", - " #keep_all_samples=True # read the doc for this argument\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", - " button.click(method_name, toolbar_event);\n", - " button.mouseover(tooltip, toolbar_mouse_event);\n", - " nav_element.append(button);\n", - " }\n", - "\n", - " // Add the status bar.\n", - " var status_bar = $('');\n", - " nav_element.append(status_bar);\n", - " this.message = status_bar[0];\n", - "\n", - " // Add the close button to the window.\n", - " var buttongrp = $('
');\n", - " var button = $('');\n", - " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", - " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", - " buttongrp.append(button);\n", - " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", - " titlebar.prepend(buttongrp);\n", - "}\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(el){\n", - " var fig = this\n", - " el.on(\"remove\", function(){\n", - "\tfig.close_ws(fig, {});\n", - " });\n", - "}\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(el){\n", - " // this is important to make the div 'focusable\n", - " el.attr('tabindex', 0)\n", - " // reach out to IPython and tell the keyboard manager to turn it's self\n", - " // off when our div gets focus\n", - "\n", - " // location in version 3\n", - " if (IPython.notebook.keyboard_manager) {\n", - " IPython.notebook.keyboard_manager.register_events(el);\n", - " }\n", - " else {\n", - " // location in version 2\n", - " IPython.keyboard_manager.register_events(el);\n", - " }\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._key_event_extra = function(event, name) {\n", - " var manager = IPython.notebook.keyboard_manager;\n", - " if (!manager)\n", - " manager = IPython.keyboard_manager;\n", - "\n", - " // Check for shift+enter\n", - " if (event.shiftKey && event.which == 13) {\n", - " this.canvas_div.blur();\n", - " // select the cell after this one\n", - " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", - " IPython.notebook.select(index + 1);\n", - " }\n", - "}\n", - "\n", - "mpl.figure.prototype.handle_save = function(fig, msg) {\n", - " fig.ondownload(fig, null);\n", - "}\n", - "\n", - "\n", - "mpl.find_output_cell = function(html_output) {\n", - " // Return the cell and output element which can be found *uniquely* in the notebook.\n", - " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", - " // IPython event is triggered only after the cells have been serialised, which for\n", - " // our purposes (turning an active figure into a static one), is too late.\n", - " var cells = IPython.notebook.get_cells();\n", - " var ncells = cells.length;\n", - " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", - " data = data.data;\n", - " }\n", - " if (data['text/html'] == html_output) {\n", - " return [cell, data, j];\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "// Register the function which deals with the matplotlib target/channel.\n", - "// The kernel may be null if the page has been refreshed.\n", - "if (IPython.notebook.kernel != null) {\n", - " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", - "}\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/mi/gph82/miniconda3/lib/python3.4/site-packages/ipykernel/__main__.py:11: RuntimeWarning: divide by zero encountered in log\n", - "The installed widget Javascript is the wrong version.\n" - ] - } - ], - "source": [ - "plt.figure(figsize=(7,7))\n", - "\n", - "ax, pos = pyemma.plots.plot_markov_model(MSM.P, \n", - " minflux=5e-4, \n", - " arrow_labels=None,\n", - " ax=plt.gca(), \n", - " arrow_curvature = 2, show_frame=True,\n", - " pos=clkmeans.clustercenters)\n", - "# Add a background if wanted\n", - "h, (x, y) = np.histogramdd(np.vstack(Y)[:,:2], weights=np.hstack(MSM.trajectory_weights()), bins=50)\n", - "plt.contourf(x[:-1], y[:-1], -np.log(h.T), cmap=\"jet\", alpha=.5, zorder=0)\n", - "plt.xlim(x[[0,-1]])\n", - "plt.xticks(np.unique(x.round()))\n", - "plt.yticks(np.unique(y.round()))\n", - "\n", - "plt.ylim(y[[0,-1]])\n", - "\n", - "iwd = molpx.visualize.sample(pos, geoms, plt.gca())\n", - "iwd" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "deletable": true, - "editable": true - }, - "source": [ - "## TPT Reactive Pathway Representation" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "The installed widget Javascript is the wrong version.\n" - ] - }, - { - "data": { - "text/plain": [ - "123" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Do an MSM with a realistic number of clustercenters\n", - "cl_many = pyemma.coordinates.cluster_regspace([iY[:,:2] for iY in Y], dmin=.25)\n", - "M = pyemma.msm.estimate_markov_model(cl_many.dtrajs, 20)\n", - "cl_many.n_clusters" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [], - "source": [ - "# Use this object to sample geometries\n", - "pos, geom = molpx.generate.sample(MD_trajfiles, top, cl_many)" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[-0.18704125 -0.77366424] [ 6.71851349 0.03159955]\n" - ] - } - ], - "source": [ - "# Find the most representative microstate of each \n", - "# and least populated macrostate\n", - "M.pcca(3)\n", - "dens_max_i = [distro.argmax() for distro in M.metastable_distributions]\n", - "A = np.argmax([M.stationary_distribution[iset].sum() for iset in M.metastable_sets])\n", - "B = np.argmin([M.stationary_distribution[iset].sum() for iset in M.metastable_sets])\n", - "print(cl_many.clustercenters[dens_max_i[A]],\n", - " cl_many.clustercenters[dens_max_i[B]])" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [], - "source": [ - "# Create a TPT object with most_pop, least_pop as source, sink respectively\n", - "tpt = pyemma.msm.tpt(M, [dens_max_i[A]], [dens_max_i[B]])\n", - "paths, flux = tpt.pathways(fraction=.5)" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true, - "scrolled": true - }, - "outputs": [], - "source": [ - "# Get a path with a decent number of intermediates\n", - "sample_path = paths[np.argmax([len(ipath) for ipath in paths])]" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": { - "collapsed": false, - "deletable": true, - "editable": true - }, - "outputs": [ - { - "data": { - "application/javascript": [ - "/* Put everything inside the global mpl namespace */\n", - "window.mpl = {};\n", - "\n", - "\n", - "mpl.get_websocket_type = function() {\n", - " if (typeof(WebSocket) !== 'undefined') {\n", - " return WebSocket;\n", - " } else if (typeof(MozWebSocket) !== 'undefined') {\n", - " return MozWebSocket;\n", - " } else {\n", - " alert('Your browser does not have WebSocket support.' +\n", - " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", - " 'Firefox 4 and 5 are also supported but you ' +\n", - " 'have to enable WebSockets in about:config.');\n", - " };\n", - "}\n", - "\n", - "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", - " this.id = figure_id;\n", - "\n", - " this.ws = websocket;\n", - "\n", - " this.supports_binary = (this.ws.binaryType != undefined);\n", - "\n", - " if (!this.supports_binary) {\n", - " var warnings = document.getElementById(\"mpl-warnings\");\n", - " if (warnings) {\n", - " warnings.style.display = 'block';\n", - " warnings.textContent = (\n", - " \"This browser does not support binary websocket messages. \" +\n", - " \"Performance may be slow.\");\n", - " }\n", - " }\n", - "\n", - " this.imageObj = new Image();\n", - "\n", - " this.context = undefined;\n", - " this.message = undefined;\n", - " this.canvas = undefined;\n", - " this.rubberband_canvas = undefined;\n", - " this.rubberband_context = undefined;\n", - " this.format_dropdown = undefined;\n", - "\n", - " this.image_mode = 'full';\n", - "\n", - " this.root = $('
');\n", - " this._root_extra_style(this.root)\n", - " this.root.attr('style', 'display: inline-block');\n", - "\n", - " $(parent_element).append(this.root);\n", - "\n", - " this._init_header(this);\n", - " this._init_canvas(this);\n", - " this._init_toolbar(this);\n", - "\n", - " var fig = this;\n", - "\n", - " this.waiting = false;\n", - "\n", - " this.ws.onopen = function () {\n", - " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", - " fig.send_message(\"send_image_mode\", {});\n", - " if (mpl.ratio != 1) {\n", - " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", - " }\n", - " fig.send_message(\"refresh\", {});\n", - " }\n", - "\n", - " this.imageObj.onload = function() {\n", - " if (fig.image_mode == 'full') {\n", - " // Full images could contain transparency (where diff images\n", - " // almost always do), so we need to clear the canvas so that\n", - " // there is no ghosting.\n", - " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", - " }\n", - " fig.context.drawImage(fig.imageObj, 0, 0);\n", - " };\n", - "\n", - " this.imageObj.onunload = function() {\n", - " this.ws.close();\n", - " }\n", - "\n", - " this.ws.onmessage = this._make_on_message_function(this);\n", - "\n", - " this.ondownload = ondownload;\n", - "}\n", - "\n", - "mpl.figure.prototype._init_header = function() {\n", - " var titlebar = $(\n", - " '
');\n", - " var titletext = $(\n", - " '
');\n", - " titlebar.append(titletext)\n", - " this.root.append(titlebar);\n", - " this.header = titletext[0];\n", - "}\n", - "\n", - "\n", - "\n", - "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "\n", - "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", - "\n", - "}\n", - "\n", - "mpl.figure.prototype._init_canvas = function() {\n", - " var fig = this;\n", - "\n", - " var canvas_div = $('
');\n", - "\n", - " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", - "\n", - " function canvas_keyboard_event(event) {\n", - " return fig.key_event(event, event['data']);\n", - " }\n", - "\n", - " canvas_div.keydown('key_press', canvas_keyboard_event);\n", - " canvas_div.keyup('key_release', canvas_keyboard_event);\n", - " this.canvas_div = canvas_div\n", - " this._canvas_extra_style(canvas_div)\n", - " this.root.append(canvas_div);\n", - "\n", - " var canvas = $('');\n", - " canvas.addClass('mpl-canvas');\n", - " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", - "\n", - " this.canvas = canvas[0];\n", - " this.context = canvas[0].getContext(\"2d\");\n", - "\n", - " var backingStore = this.context.backingStorePixelRatio ||\n", - "\tthis.context.webkitBackingStorePixelRatio ||\n", - "\tthis.context.mozBackingStorePixelRatio ||\n", - "\tthis.context.msBackingStorePixelRatio ||\n", - "\tthis.context.oBackingStorePixelRatio ||\n", - "\tthis.context.backingStorePixelRatio || 1;\n", - "\n", - " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", - "\n", - " var rubberband = $('');\n", - " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", - "\n", - " var pass_mouse_events = true;\n", - "\n", - " canvas_div.resizable({\n", - " start: function(event, ui) {\n", - " pass_mouse_events = false;\n", - " },\n", - " resize: function(event, ui) {\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " stop: function(event, ui) {\n", - " pass_mouse_events = true;\n", - " fig.request_resize(ui.size.width, ui.size.height);\n", - " },\n", - " });\n", - "\n", - " function mouse_event_fn(event) {\n", - " if (pass_mouse_events)\n", - " return fig.mouse_event(event, event['data']);\n", - " }\n", - "\n", - " rubberband.mousedown('button_press', mouse_event_fn);\n", - " rubberband.mouseup('button_release', mouse_event_fn);\n", - " // Throttle sequential mouse events to 1 every 20ms.\n", - " rubberband.mousemove('motion_notify', mouse_event_fn);\n", - "\n", - " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", - " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", - "\n", - " canvas_div.on(\"wheel\", function (event) {\n", - " event = event.originalEvent;\n", - " event['data'] = 'scroll'\n", - " if (event.deltaY < 0) {\n", - " event.step = 1;\n", - " } else {\n", - " event.step = -1;\n", - " }\n", - " mouse_event_fn(event);\n", - " });\n", - "\n", - " canvas_div.append(canvas);\n", - " canvas_div.append(rubberband);\n", - "\n", - " this.rubberband = rubberband;\n", - " this.rubberband_canvas = rubberband[0];\n", - " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", - " this.rubberband_context.strokeStyle = \"#000000\";\n", - "\n", - " this._resize_canvas = function(width, height) {\n", - " // Keep the size of the canvas, canvas container, and rubber band\n", - " // canvas in synch.\n", - " canvas_div.css('width', width)\n", - " canvas_div.css('height', height)\n", - "\n", - " canvas.attr('width', width * mpl.ratio);\n", - " canvas.attr('height', height * mpl.ratio);\n", - " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", - "\n", - " rubberband.attr('width', width);\n", - " rubberband.attr('height', height);\n", - " }\n", - "\n", - " // Set the figure to an initial 600x600px, this will subsequently be updated\n", - " // upon first draw.\n", - " this._resize_canvas(600, 600);\n", - "\n", - " // Disable right mouse context menu.\n", - " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", - " return false;\n", - " });\n", - "\n", - " function set_focus () {\n", - " canvas.focus();\n", - " canvas_div.focus();\n", - " }\n", - "\n", - " window.setTimeout(set_focus, 100);\n", - "}\n", - "\n", - "mpl.figure.prototype._init_toolbar = function() {\n", - " var fig = this;\n", - "\n", - " var nav_element = $('
')\n", - " nav_element.attr('style', 'width: 100%');\n", - " this.root.append(nav_element);\n", - "\n", - " // Define a callback function for later on.\n", - " function toolbar_event(event) {\n", - " return fig.toolbar_button_onclick(event['data']);\n", - " }\n", - " function toolbar_mouse_event(event) {\n", - " return fig.toolbar_button_onmouseover(event['data']);\n", - " }\n", - "\n", - " for(var toolbar_ind in mpl.toolbar_items) {\n", - " var name = mpl.toolbar_items[toolbar_ind][0];\n", - " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", - " var image = mpl.toolbar_items[toolbar_ind][2];\n", - " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", - "\n", - " if (!name) {\n", - " // put a spacer in here.\n", - " continue;\n", - " }\n", - " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/guille/miniconda3/lib/python3.5/site-packages/ipykernel/__main__.py:4: RuntimeWarning: divide by zero encountered in log\n" + ] + } + ], + "source": [ + "# Replot the FES\n", + "plt.figure(figsize=(7,7))\n", + "h, (x,y) = np.histogramdd(np.vstack(Y)[:,:2], bins=50)\n", + "plt.contourf(x[:-1], y[:-1], -np.log(h.T), alpha=.50)\n", + "# Create the linked widget\n", + "linked_wdg = molpx.visualize.sample(data_sample, \n", + " geoms.superpose(geoms[0]), \n", + " plt.gca(), \n", + " clear_lines=True,\n", + " #plot_path=True\n", + " )\n", + "plt.plot(data_sample[:,0], data_sample[:,1],' ok', zorder=0)\n", + "# Show it\n", + "linked_wdg\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "# Paths samples along the different projections (=axis)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "paths_dict, idata = molpx.generate.projection_paths(#MD_list, \n", + " MD_trajfiles, \n", + " top, \n", + " Y_filenames,\n", + " #Y, # You can also directly give the data here\n", + " n_points=50,\n", + " proj_idxs=[0,1],\n", + " n_projs=3,\n", + " proj_dim = 3, \n", + " verbose=False, \n", + " )" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "## Link the PDF plot with the sampled paths/structures and visually explore the coordinates (separately). \n", + "Click either on the plot or on the widget slidebar: they're connected! You can change the type of path between min_rmsd or min_disp and you can also change the coordinate sampled (0 or 1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "# Choose the coordinate and the tyep of path\n", + "coord = 1\n", + "#path_type = 'min_rmsd'\n", + "path_type = 'min_disp'\n", + "igeom = paths_dict[coord][path_type][\"geom\"]\n", + "ipath = paths_dict[coord][path_type][\"proj\"]\n", + "\n", + "# Choose the proj_idxs for the path and the FES \n", + "# to be shown\n", + "proj_idxs = [0,1]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true, + "scrolled": false + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/guille/miniconda3/lib/python3.5/site-packages/ipykernel/__main__.py:6: RuntimeWarning: divide by zero encountered in log\n" + ] + } + ], "source": [ "# Plot clusters\n", "plt.figure(figsize=(7,7))\n", @@ -1412,7 +6779,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "collapsed": false, "deletable": true, @@ -1425,13 +6792,794 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": { "collapsed": false, "deletable": true, "editable": true }, - "outputs": [], + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/guille/miniconda3/lib/python3.5/site-packages/ipykernel/__main__.py:2: RuntimeWarning: divide by zero encountered in log\n", + " from ipykernel import kernelapp as app\n" + ] + } + ], "source": [ "plt.figure()\n", "plt.contourf(x[:-1], y[:-1], -np.log(h.T), cmap=\"jet\", alpha=.5, zorder=0)\n", @@ -1570,16 +8510,12 @@ " plot_path=True,\n", " )\n", "plt.scatter(*cl_many.clustercenters.T, alpha=.25)\n", - "iwd.add_distance(atom_pair=[[10,20]], \n", - " color='red', \n", - " #label_color='black', \n", - " label_size=0)\n", "iwd" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "collapsed": true, "deletable": true, @@ -1591,39 +8527,12 @@ "# https://github.com/arose/nglview/issues/518\n", "# https://github.com/arose/nglview/issues/517" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python 3", + "display_name": "Python [default]", "language": "python", "name": "python3" }, @@ -1637,303 +8546,1080 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.5" + "version": "3.5.2" }, "widgets": { "state": { - "05fd51b6199a411295236d6bfd3932f3": { + "018fc0aa41c047aca2eb61f0fa986783": { + "views": [ + { + "cell_index": 14 + } + ] + }, + "047c029783f44befa428bc71101c1537": { + "views": [ + { + "cell_index": 19 + } + ] + }, + "0749093cd02443c29b37de56625bcd37": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "0a1d7a21c74444fbad3ccbc37919e30c": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "0dbe43592927492686d79df4092eee49": { + "views": [ + { + "cell_index": 27 + } + ] + }, + "0f4517cd73af4937a3f25cd94db7fcf3": { + "views": [ + { + "cell_index": 23 + } + ] + }, + "0fa859cb6dfa40b6b5c4ed50ff205cf3": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "0fed1a331da34da3bc4b5f5962e6b6ed": { + "views": [ + { + "cell_index": 23 + } + ] + }, + "110c579c3fee473fa2dade260a62a60e": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "11d2aacbf2bc4d94afbbd55d9a11168e": { + "views": [ + { + "cell_index": 23 + } + ] + }, + "16ffeeeff2a5472b8af3e17738a5a666": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "178e0fae0df640b186591f58c4749f3c": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "17dbdf8e22f84b9d947efeb73c75bcdf": { + "views": [ + { + "cell_index": 19 + } + ] + }, + "1980932c568d430d833679aeb77e982a": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "1b0c3bb4ab6946ed99500c6a082070ab": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "1eab560d93744f51a26ee54fde14c931": { + "views": [ + { + "cell_index": 19 + } + ] + }, + "20268dfa4e5b4358bf932f8b496643e8": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "210f3bda53db440ebcb891aa9668dc6f": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "21e0fef6d2dc4f6ebec541c74b4cdcfe": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "22ae1e136b2041f5b0d405faf11da717": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "22fe64f7eb70459b947e22e5faaccbb3": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "29e6fb193944432ca0f3e3ce0e85fdba": { + "views": [ + { + "cell_index": 8 + } + ] + }, + "2a53826052a6497a90c64c9c941bd0bc": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "2af726a38e2340108f9a86512bf19a87": { + "views": [ + { + "cell_index": 30 + } + ] + }, + "2af74c87b99a464ab7503e29276e52ee": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "2b2546a3c9784bec898116aa9245d230": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "2bd0823cf1b543f8b52adf85c01faba9": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "2c463732cff34e298b17835659903d8a": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "2c4dc7944f5f4e228100dbc3656bf0c9": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "2ca19fd246934b5bbabd2e2e1c7b867c": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "2e31ed28a18142e090578fb857950145": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "30fc779d2f8f4c3295c96495729a34bd": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "3186d6454371425db4fccdfdd9979232": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "32afe69b1f9145919c20c97f2eded8b1": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "37892a7ecb0a4138a200e77e24497b06": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "3a7029e6cc7445389ca3e1de45ca19a3": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "3b81511382b34668aae6473f1d19240d": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "3ba63f31778f4faba69675698adcbc98": { + "views": [ + { + "cell_index": 27 + } + ] + }, + "3f3d4f984a2d43c0b538243ca86a1968": { + "views": [ + { + "cell_index": 11 + } + ] + }, + "42cc4be7ad904aaa8819111a7004fc18": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "44bd423630a14f008869d062308110ca": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "46825e89c4fa45da80f3a45f02205eed": { + "views": [ + { + "cell_index": 30 + } + ] + }, + "4693842948ac496395f23d46ece779b8": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "476ac8256d7f418880e7b2ad9f0607ac": { + "views": [ + { + "cell_index": 19 + } + ] + }, + "4911c01ac6534a11950bf2417a8d7624": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "49fa607769f94bada815ec6638aae0dd": { + "views": [ + { + "cell_index": 19 + } + ] + }, + "4b4c35f728574591a033f3fc9917b105": { + "views": [ + { + "cell_index": 37 + } + ] + }, + "4be58c34e4fb46aa9160f5ee1281ef51": { + "views": [ + { + "cell_index": 37 + } + ] + }, + "4f4971f6e8e443afa668c5a06d2afd14": { + "views": [ + { + "cell_index": 38 + } + ] + }, + "4fbd9f5d57234801a03ba1b9973ee49c": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "51104bc101f044fb9fd07c66d2338db1": { + "views": [ + { + "cell_index": 30 + } + ] + }, + "53b60f990ea84522905636a4d98ed33b": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "53fefd3603304a81b5f34ac101d0b765": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "542b21bc1e724f969e988ff71484d9da": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "5473c708f330442bb125fed6d82fd115": { + "views": [ + { + "cell_index": 11 + } + ] + }, + "565610aef3864a5abf6f0b2f28186a72": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "578b809d38dc44c1874f6892a555fac2": { + "views": [ + { + "cell_index": 27 + } + ] + }, + "57d2e542d0404390922418b15cf12863": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "594d4e0d896d4319a92f831be697e0bd": { + "views": [ + { + "cell_index": 30 + } + ] + }, + "5d10a5e6685f4231aede0c16e1c4334d": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "5ebc585f29ef4634a8a57841279c45cc": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "5f572a3cf4da468bab4f6d6c516bfdd2": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "624dad1c792245aaab80bd4b926a2368": { + "views": [ + { + "cell_index": 11 + } + ] + }, + "626067daeda947f391fed246bd132f58": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "62d8d016a1394d5f9e4850e323921b1c": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "63759e3d7c1841bb89872d5a8a934de4": { + "views": [ + { + "cell_index": 30 + } + ] + }, + "658d4059a1af4639875bce5e5b48b712": { + "views": [ + { + "cell_index": 23 + } + ] + }, + "674943d4205f46c180e89c3467b2dd4c": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "6ae7dc40ca2341beb8e4eebb8d7541ac": { "views": [ { - "cell_index": 19 + "cell_index": 14 } ] }, - "074c3dca074849c988592e65297e978d": { + "6b0cb0fea5e642c4a0b6390d91b9926c": { "views": [ { - "cell_index": 20 + "cell_index": 12 } ] }, - "08ccb13e01324ee5babd047e5e80389b": { + "6d10d37798d5487e89b11b23d932ef96": { "views": [ { - "cell_index": 14 + "cell_index": 12 } ] }, - "11c6e4b180f147cc8c20fd648bcd7e62": { + "6d2d7a5b89b24dc1af4bab4bc3b92a80": { "views": [ { - "cell_index": 19 + "cell_index": 12 } ] }, - "142e08b8b6ea48b198545fba615fa4b8": { + "6f3ab259284d47598a32e27514d957bb": { + "views": [ + { + "cell_index": 30 + } + ] + }, + "70656ce17acb4aca81c2d340957d65e9": { "views": [ { "cell_index": 19 } ] }, - "1f9aef433b91482d815f25acce409f47": { + "70f4f25c955e4f69ba465137ba46f401": { "views": [ { - "cell_index": 20 + "cell_index": 14 } ] }, - "203b0244c43345358e41aad1dc14b950": { + "75867e15272a45069b14c1bde51e9ce0": { "views": [ { - "cell_index": 19 + "cell_index": 10 } ] }, - "2476b110e8084a31b36ee8240cc32e67": { + "7846c65b1e8f4076a36673767b8fc4e6": { "views": [ { - "cell_index": 33 + "cell_index": 12 } ] }, - "292be1d5b0e7435cbf0bff3136d704ce": { + "793ab05781444084a58b05d15835b8ed": { "views": [ { - "cell_index": 20 + "cell_index": 12 } ] }, - "32bf0a31432f4b908d842bd580eef695": { + "7ad9ae43fb3444739faa1b2613971110": { "views": [ { - "cell_index": 8 + "cell_index": 12 } ] }, - "32d6c35863394d7ea099cd19be6c787f": { + "7cb401236f6a43a5a307496385e2b1e3": { "views": [ { - "cell_index": 20 + "cell_index": 12 } ] }, - "4309c2da46ca483bb70b16354d2446ac": { + "7efa07bc99b14ddaa488917a64f61f5c": { "views": [ { - "cell_index": 20 + "cell_index": 10 } ] }, - "43823fa5e51c4ea6875a09c893bdf984": { + "83ade96b936349a9992871e0f868751a": { "views": [ { - "cell_index": 19 + "cell_index": 10 + } + ] + }, + "84ba7d356306416fa17a6e83f34b1eb9": { + "views": [ + { + "cell_index": 11 + } + ] + }, + "891d1b10bccd41b596184e1234b78e8c": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "898b1f881787467b98230153cda96bd7": { + "views": [ + { + "cell_index": 27 + } + ] + }, + "8a70c900f8644b4c8d15cc4788b4dc2d": { + "views": [ + { + "cell_index": 23 + } + ] + }, + "8afe5a4b135940f1b1e6d1d32e149c59": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "8b54ab898c8440ef8b8c7bb3b865f0df": { + "views": [ + { + "cell_index": 27 + } + ] + }, + "8cfdea6168774a33bc68c4720711e4ac": { + "views": [ + { + "cell_index": 30 + } + ] + }, + "8e7a1f23075545598fe74b67a61ffc1f": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "933d642417cb464a900be96d63a751a9": { + "views": [ + { + "cell_index": 23 + } + ] + }, + "937cdd64343b4e63849dc9ad2d308a20": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "95105c41b274436186a8d7e0389ecf13": { + "views": [ + { + "cell_index": 27 + } + ] + }, + "98e40c08a32049a6bcabc8cee9dcac31": { + "views": [ + { + "cell_index": 23 + } + ] + }, + "9b2b8bc2b2624e9ab6c9e77517ce2a46": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "9b461597d0964ddb9d484f7c12fe8465": { + "views": [ + { + "cell_index": 14 } ] }, - "50b5fcdfda0e4795b1dfc97c981f0f35": { + "9cbaaa8f799646cebb36c2ecd0bd2c1c": { "views": [ { - "cell_index": 33 + "cell_index": 27 } ] }, - "57fe9b7535834d5ba34b86cd033b6062": { + "9f240527f058464783c83d66509c8cf1": { "views": [ { "cell_index": 8 } ] }, - "5ca634bd0a324858af6bf51430dc1fc6": { + "9f8b14b32a4a4b5b81786340cd73cd07": { "views": [ { - "cell_index": 19 + "cell_index": 11 } ] }, - "5d8661f49236417d92165de679d52d04": { + "a22672667f3e4b66993f3bc4213a445d": { "views": [ { - "cell_index": 19 + "cell_index": 14 } ] }, - "61953ff5f4604a5cb40ce6b527fe2b67": { + "a4c506c4dcdf4f56bc50e8be7745efe4": { "views": [ { - "cell_index": 22 + "cell_index": 12 } ] }, - "63ef7a2549f44d27ad9aab99f6f18b84": { + "a73e1626e3724e54876b9b47722c8163": { "views": [ { - "cell_index": 19 + "cell_index": 10 } ] }, - "6af12466edf145908369c274df562f3c": { + "a8882cf6f11c470cbc341c8012862d40": { "views": [ { - "cell_index": 20 + "cell_index": 12 } ] }, - "6e4fbcd025f6456896f4b0bbfc507e6c": { + "a93b1cb51ed942998265e3701ede62e7": { "views": [ { - "cell_index": 19 + "cell_index": 30 } ] }, - "7620b9be5c0c43b28edf3edc90868f48": { + "ab5a9e58db35491f873210bf0c56de36": { "views": [ { - "cell_index": 20 + "cell_index": 37 } ] }, - "79a044e9dfb14df1bd1bc50cb4dedbc2": { + "ab81995504ba46d8b9dcfdeebae3158a": { "views": [ { - "cell_index": 19 + "cell_index": 27 } ] }, - "833eb6cf19db4f82bffa29888b6449f5": { + "acbe2416a224402786002b3f483ffde9": { "views": [ { - "cell_index": 20 + "cell_index": 12 } ] }, - "8652ecaf48fe4cd6a042d53f1ea7054d": { + "b70d2038c2364e118fce54b9b3ac651c": { "views": [ { - "cell_index": 19 + "cell_index": 12 + } + ] + }, + "b8796d27cb1d45e590a58d0ebf84011b": { + "views": [ + { + "cell_index": 10 } ] }, - "867bfe338b4b4b2d875a6e1228a49808": { + "ba9d16be75e54f58a81363c9fb554fe5": { "views": [ { - "cell_index": 26 + "cell_index": 12 } ] }, - "995af6fd7f62412b8789c28e4d863e85": { + "babcfae794664fdd91999c4aafaaa9be": { "views": [ { - "cell_index": 23 + "cell_index": 37 + } + ] + }, + "be1fedb0eb97451dae6cf439d3549770": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "be357f875393495998b7b45ba2b36a41": { + "views": [ + { + "cell_index": 11 + } + ] + }, + "be64d759283c4e838579524b3d99fcec": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "bee3a820487643059034726061ea0a08": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "c0e7e9d248894446b1dd3e491bdeb837": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "c14c7a44f81a4a758fcc01c031f6628c": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "c37858c1e2bd44f98a9567003a267396": { + "views": [ + { + "cell_index": 38 + } + ] + }, + "c55b12a8781f416e843229b3576cf01b": { + "views": [ + { + "cell_index": 12 } ] }, - "a503d1d410754d02bdda3bc2053855dd": { + "c690e96ab943413982bd475b92317abc": { "views": [ { - "cell_index": 20 + "cell_index": 11 } ] }, - "b591546e821a488588cad14c2d00745d": { + "c6f37f0b452549a2a921855f04ecaf0a": { "views": [ { - "cell_index": 20 + "cell_index": 14 } ] }, - "b877d5e391604f448585a825bddba222": { + "c72a4bc107a64d41a402b007d6667afa": { "views": [ { - "cell_index": 22 + "cell_index": 12 } ] }, - "bbfd9197cb3546dbb7ce5fca9ad3fac8": { + "c7a0110d23304e589e50f8481603b1c0": { "views": [ { "cell_index": 10 } ] }, - "bd6b86bf1b7749ef9fb70d1645f9a4ca": { + "c880e0a6d86a448887a4443c6df0dfe2": { + "views": [ + { + "cell_index": 11 + } + ] + }, + "cbb8f7f821974e248e1ba9acbc836634": { + "views": [ + { + "cell_index": 27 + } + ] + }, + "cbf4980b45834bf4920fbf6849f73272": { + "views": [ + { + "cell_index": 37 + } + ] + }, + "d330ebdc74c04600836e78397c9a8689": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "d3aa99b910314362a08ba2e3c8915e5b": { "views": [ { "cell_index": 14 } ] }, - "c5a9ec822fc74321b2c64c49c364bdaf": { + "d43a56908a224407ad434a21138fd74b": { "views": [ { - "cell_index": 20 + "cell_index": 12 } ] }, - "c7cd188e40934ef3815578d61e77ceb6": { + "d5303b80f4534814ba39ee07a20e624d": { "views": [ { - "cell_index": 20 + "cell_index": 14 } ] }, - "cc9e74df4aac4d1bb934cc1fae94d33d": { + "d670822b81bb4f56a0989cd5eeeac0cb": { "views": [ { - "cell_index": 23 + "cell_index": 12 } ] }, - "cdb00ea7b13a489ebc46fa33191419fb": { + "d755e6ed8dea46679295cff6c780a6ea": { "views": [ { - "cell_index": 10 + "cell_index": 30 + } + ] + }, + "d9958626bfb54a5da5e844d3d8502a22": { + "views": [ + { + "cell_index": 12 } ] }, - "cece81c91a68427297e2a624eb57330c": { + "de0110da2428486d859e97876253d183": { "views": [ { "cell_index": 19 } ] }, - "cf370472fe4544e4976d53f7a141faf5": { + "e00108eeb9204d6ea2b835efaf1dff16": { + "views": [ + { + "cell_index": 37 + } + ] + }, + "e1553b0bd42e431897bf90954c6190d6": { "views": [ { "cell_index": 19 } ] }, - "ec665e6b831642faa7a83e53abd74790": { + "e432e7a220224e32bdfa5141698e0c78": { "views": [ { - "cell_index": 26 + "cell_index": 12 } ] }, - "f23352befa0a4dda8423d4b98c953c9a": { + "e569ec592aa34b89ad439df2fb74bfa7": { "views": [ { - "cell_index": 20 + "cell_index": 12 } ] }, - "f418d22d5fc649f988da42c7168bd7e4": { + "e6aa2a1dc8284e2b976e598283b72c88": { "views": [ { - "cell_index": 19 + "cell_index": 23 + } + ] + }, + "ea9b3098594949e8847da9e7eb298dc7": { + "views": [ + { + "cell_index": 37 } ] }, - "f781d6cd30904afab09ad7d14e682eb4": { + "ebdb95cd9bff42d6aa5a6827c38496c5": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "ed3d93e969b84469a36cc904cd259ee1": { + "views": [ + { + "cell_index": 23 + } + ] + }, + "eddb3f025e6d419dbea1dfce222a02a4": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "eee6e5f4802e4b0d9b08766263d0b6cf": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "f180d827ba0d4c9995d0b036e058e6b8": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "f2d15809e80145428505ec27f68f0229": { + "views": [ + { + "cell_index": 23 + } + ] + }, + "f322ef6b10214e43a30bce5d5dac98e6": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "f5f43f2f36cf4de682a21527012f5613": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "f66f59189ce0465b8cc4a26b680e9154": { + "views": [ + { + "cell_index": 10 + } + ] + }, + "f967f2d1fb314eba8c245b119b2a00b0": { + "views": [ + { + "cell_index": 37 + } + ] + }, + "fcc4c3c131d64c88976996c008b39cec": { "views": [ { "cell_index": 19 } ] + }, + "fd437315044f4400a0f3e931d3a1e1fc": { + "views": [ + { + "cell_index": 12 + } + ] + }, + "fd51d3d74b3c4093ab3cd73fc80a5511": { + "views": [ + { + "cell_index": 14 + } + ] } }, "version": "1.2.0" From c5f9897e8ec4893aaa0682a05e16becfe0c58f95 Mon Sep 17 00:00:00 2001 From: gph82 Date: Thu, 16 Mar 2017 23:04:05 +0100 Subject: [PATCH 06/23] [README] include docs badge and nicer formatting with links --- README.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 5b3505a..6f7ed97 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ ################################################### Welcome to molPX: The Molecular Projection Explorer ################################################### -|DOI| |travis-build| |appveyor-build| |coverage| |docs-build| +|DOI| |travis_build| |appveyor_build| |coverage| |docs_build| The Molecular Projection Explorer, molPX, is a python module that provides **interactive visualization of projected coordinates of molecular dynamics (MD) trajectories** inside a `Jupyter notebook `_. @@ -40,6 +40,7 @@ and jump to the Quick Start section of this document. Otherwise, check out our m * :doc:`Installation Guide ` + Quick Start ============= @@ -144,13 +145,13 @@ Known Issues :height: 20 :alt: DOI -.. |travis-build| image:: +.. |travis_build| image:: https://travis-ci.org/markovmodel/molPX.svg?branch=master :height: 10 :target: https://travis-ci.org/markovmodel/molPX :alt: Travis build status -.. |appveyor-build| image:: +.. |appveyor_build| image:: https://ci.appveyor.com/api/projects/status/396ej39s3fewhwy9/branch/master?svg=true :height: 10 :target: https://ci.appveyor.com/project/gph82/molpx @@ -162,7 +163,7 @@ Known Issues :target: https://codecov.io/gh/markovmodel/molPX :alt: Codecov -.. |docs-build| image:: +.. |docs_build| image:: https://readthedocs.org/projects/molpx/badge/?version=latest :alt: Documentation Status :height: 20 From d73e056af9462c33f53e3dd4cc31b947148d0e2e Mon Sep 17 00:00:00 2001 From: gph82 Date: Fri, 17 Mar 2017 09:22:30 +0100 Subject: [PATCH 07/23] [visualize.correlation] preparing refactoring for new method --- molpx/bmutils.py | 7 +++++-- molpx/visualize.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/molpx/bmutils.py b/molpx/bmutils.py index 4bfc861..970f3e5 100644 --- a/molpx/bmutils.py +++ b/molpx/bmutils.py @@ -835,7 +835,7 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None r""" return information about the most correlated features from a `:obj:pyemma.coodrinates.transformer` object - Paramters + Parameters --------- correlation_input : anything @@ -843,7 +843,7 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None like a TICA or PCA object (this method will be extended to interpret other inputs, so for now this parameter is pretty flexible) - geoms: None or obj:`md.Trajectory`, default is None + geoms : None or obj:`md.Trajectory`, default is None The values of the most correlated features will be returned for the geometires in this object proj_idxs: None, or int, or iterable of integers, default is None @@ -923,6 +923,9 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None # TODO write a warning else: ifeat = correlation_input.data_producer.featurizer.active_features[0] + print(ifeat) + print(atom_idxs_from_feature(ifeat)) + print(most_corr_idxs) most_corr_atom_idxs.append(atom_idxs_from_feature(ifeat)[most_corr_idxs[-1]]) return most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs diff --git a/molpx/visualize.py b/molpx/visualize.py index 8d8358c..5ad697f 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -348,6 +348,50 @@ def traj(MD_trajectories, return _plt.gca(), _plt.gcf(), widget, geoms +def correlations(correlation_input, geoms=None, proj_idxs=None, feat_name=None, n_args=1, proj_name='proj'): + r""" + Provide a visual and textual representation of the linear correlations between projected coordinates (PCA, TICA) + and original features. + + Parameters + --------- + + correlation_input : anything + Something that could, in principle, be a :obj:`pyemma.coordinates.transformer, + like a TICA or PCA object + (this method will be extended to interpret other inputs, so for now this parameter is pretty flexible) + + geoms : None or obj:`md.Trajectory`, default is None + The values of the most correlated features will be returned for the geometires in this object + + widget : None or nglview widget + + proj_idxs: None, or int, or iterable of integers, default is None + The indices of the projections for which the most correlated feture will be returned + If none it will default to the dimension of the correlation_input object + + feat_name : None or str, default is None + The prefix with which to prepend the labels of the most correlated features. If left to None, the feature + description found in :obj:`correlation_input` will be used (if available) + + n_args : int, default is 1 + Number of argmax correlation to return for each feature. + + :return: + """ + + most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs = \ + _most_corr_info(correlation_input, geoms=geoms, proj_idxs=proj_idxs, feat_name=feat_name, n_args=n_args) + + if isinstance(proj_idxs, int): + proj_idxs = [proj_idxs] + + if isinstance(proj_name, str): + proj_name = ['%s_%u'%(proj_name, ii) for ii in proj_idxs] + for ii, __ in enumerate(proj_idxs): + print(proj_name[ii]) + for jj, jidx in most_corr_idxs[ii]: + print() def sample(positions, geom, ax, plot_path=False, From b0aaab0a6fffcf862a018acc0f3cc566778300a7 Mon Sep 17 00:00:00 2001 From: gph82 Date: Fri, 17 Mar 2017 10:22:31 +0100 Subject: [PATCH 08/23] [bmutils.most_corr_info] returns also dictionary of strings with description for easy printing --- molpx/bmutils.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/molpx/bmutils.py b/molpx/bmutils.py index 970f3e5..4d39115 100644 --- a/molpx/bmutils.py +++ b/molpx/bmutils.py @@ -831,7 +831,7 @@ def smooth_geom(geom, n, geom_data=None, superpose=True, symmetric=True): else: return geom_out, data_out -def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None, n_args=1): +def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None, n_args=1, proj_names='proj'): r""" return information about the most correlated features from a `:obj:pyemma.coodrinates.transformer` object @@ -883,9 +883,12 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None * etc. If possible, most_corr_info will try to return these indices to be used later for visualization + info : a list of dictionaries containing information as strings (for stdout printing use) """ #TODO: extend to other inputs + #todo:document proj_names + # TODO: CONSIDER PURE STRING WITH \N INSTEAD for output "lines" most_corr_idxs = [] most_corr_vals = [] @@ -896,11 +899,15 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None if isinstance(proj_idxs, int): proj_idxs = [proj_idxs] + if isinstance(correlation_input, (_TICA, _PCA)): if proj_idxs is None: proj_idxs = _np.arange(correlation_input.dim) + if isinstance(proj_names, str): + proj_names = ['%s_%u' % (proj_names, ii) for ii in proj_idxs] + if _np.max(proj_idxs) > correlation_input.dim: raise ValueError("Cannot ask for projection index %u if the " "transformation only has %u projections"%(_np.max(proj_idxs), correlation_input.dim)) @@ -923,12 +930,21 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None # TODO write a warning else: ifeat = correlation_input.data_producer.featurizer.active_features[0] - print(ifeat) - print(atom_idxs_from_feature(ifeat)) - print(most_corr_idxs) + #print(ifeat) + #print(atom_idxs_from_feature(ifeat)) + #print(most_corr_idxs) most_corr_atom_idxs.append(atom_idxs_from_feature(ifeat)[most_corr_idxs[-1]]) - return most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs + info = [] + for ii, iproj in enumerate(proj_names): + info.append({"lines":[], "name":iproj}) + for jj, jidx in enumerate(most_corr_idxs[ii]): + istr = 'Corr[%s|feat] = %2.1f for %-50s (feat nr. %u, atom idxs %s' % \ + (iproj, most_corr_vals[ii][jj], most_corr_labels[ii][jj], jidx, most_corr_atom_idxs[ii][jj]) + info[-1]["lines"].append(istr) + info[-1]["lines"].append('') + + return most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs, info def atom_idxs_from_feature(ifeat): r""" From b108af69babff0da3e212b0704e6b0818aefca82 Mon Sep 17 00:00:00 2001 From: gph82 Date: Fri, 17 Mar 2017 10:23:12 +0100 Subject: [PATCH 09/23] [visualize.correlations] new method for indendent visualizations --- molpx/visualize.py | 76 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/molpx/visualize.py b/molpx/visualize.py index 5ad697f..64fc53a 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -348,7 +348,14 @@ def traj(MD_trajectories, return _plt.gca(), _plt.gcf(), widget, geoms -def correlations(correlation_input, geoms=None, proj_idxs=None, feat_name=None, n_args=1, proj_name='proj'): +def correlations(correlation_input, + geoms=None, + proj_idxs=None, + feat_name=None, + widget=None, + color_list=None, + n_feats=1, + verbose=True): r""" Provide a visual and textual representation of the linear correlations between projected coordinates (PCA, TICA) and original features. @@ -362,9 +369,30 @@ def correlations(correlation_input, geoms=None, proj_idxs=None, feat_name=None, (this method will be extended to interpret other inputs, so for now this parameter is pretty flexible) geoms : None or obj:`md.Trajectory`, default is None - The values of the most correlated features will be returned for the geometires in this object + The values of the most correlated features will be returned for the geometires in this object. If widget is + left to its default, None, :obj:`correlations` will create a new widget and try to show the most correlated + features on top of the widget widget : None or nglview widget + Provide an already existing widget to visualize the correlations on top of. This is only for expert use, + because no checks are done to see if :obj:`correlation_input` and the geometry contained in the + widget **actually match**. Use with caution. + + Note + ---- + When objects :obj:`geoms` and :obj:`widget` are provided simultaneously, three things happen: + * no new widget will be instantiated + * the display of features will be on top of whatever geometry :obj:`widget` contains + * the value of the features is computed for the geometry of :obj:`geom` + + Use with caution and clean bookkeeping! + + color_list: list, default is None + list of colors to provide the representations with. The default None yields blue. + In principle, the list can contain one color for each projection (= as many colors as len(proj_idxs) + but if your list is short it will just default to the last color. This way, color_list=['black'] will paint + all black regardless len(proj_idxs) + proj_idxs: None, or int, or iterable of integers, default is None The indices of the projections for which the most correlated feture will be returned @@ -374,24 +402,46 @@ def correlations(correlation_input, geoms=None, proj_idxs=None, feat_name=None, The prefix with which to prepend the labels of the most correlated features. If left to None, the feature description found in :obj:`correlation_input` will be used (if available) - n_args : int, default is 1 + n_feats : int, default is 1 Number of argmax correlation to return for each feature. + verbose : Bool, default is True + print to standard output + :return: + most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs, lines, widget, lines """ + # todo document + # todo test - most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs = \ - _most_corr_info(correlation_input, geoms=geoms, proj_idxs=proj_idxs, feat_name=feat_name, n_args=n_args) + most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs, lines = \ + _most_corr_info(correlation_input, geoms=geoms, proj_idxs=proj_idxs, feat_name=feat_name, n_args=n_feats) - if isinstance(proj_idxs, int): - proj_idxs = [proj_idxs] + if verbose: + for line in lines: + print(line["name"]) + for line in line["lines"]: + print(line) + + # Create ngl_viewer widget + if geoms is not None and widget is None: + widget = _nglview.show_mdtraj(geoms.superpose(geoms)) + #else: + # iwd = widget + + if color_list is None: + color_list = ['blue']*len(most_corr_idxs) + elif isinstance(color_list, list) and len(color_list) Date: Fri, 17 Mar 2017 11:53:18 +0100 Subject: [PATCH 10/23] [tests_bmutils] tests most_corr_info refactored to work with dict --- molpx/tests/test_bmutils.py | 49 +++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/molpx/tests/test_bmutils.py b/molpx/tests/test_bmutils.py index 5420537..c2c3b82 100644 --- a/molpx/tests/test_bmutils.py +++ b/molpx/tests/test_bmutils.py @@ -67,80 +67,75 @@ def _test_data_from_input_ndarray_ascii_npy(self): assert np.all([np.allclose(self.Y, iY) for iY in Ys]) def test_most_corr_info_works(self): - most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats = bmutils.most_corr_info(self.tica) + most_corr = bmutils.most_corr(self.tica) ref_idxs = [np.abs(self.tica.feature_TIC_correlation[:, ii]).argmax() for ii in range(self.tica.dim)] + # Since the results are always lists, that's how the comparsion will go # Idxs are okay - assert np.allclose(ref_idxs, most_corr_idxs) + assert np.all([ri == mci for ri, mci in zip(ref_idxs, most_corr['idxs'])]) ref_corrs = [self.tica.feature_TIC_correlation[jj, ii] for jj, ii in zip(ref_idxs,range(self.tica.dim) )] # Values are ok - assert np.allclose(ref_corrs, most_corr_vals) + assert np.all([rv == mcv for rv, mcv in zip(ref_corrs, most_corr['vals'])]) # Labels are strings and are the right number - assert len(most_corr_labels) == len(ref_idxs) - assert [isinstance(istr, str) for istr in most_corr_labels] + assert len(most_corr['labels']) == len(ref_idxs) + assert [isinstance(istr, str) for istr in most_corr['labels']] # No geom was parsed, show the last onew should be empty - assert most_corr_feats == [] + assert most_corr['feats'] == [] def test_most_corr_info_works_with_options(self): geoms = md.load(self.MD_trajectory, top=self.MD_topology) - - - most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats = \ - bmutils.most_corr_info(self.tica, geoms=geoms) - - ref_feats = self.feat.transform(geoms) + most_corr = bmutils.most_corr(self.tica, geoms=geoms) # Idxs are okay ref_idxs = [np.abs(self.tica.feature_TIC_correlation[:, ii]).argmax() for ii in range(self.tica.dim)] - assert np.allclose(ref_idxs, most_corr_idxs) + assert np.all([ri == mci for ri, mci in zip(ref_idxs, most_corr['idxs'])]) # Corr values ref_corrs = [self.tica.feature_TIC_correlation[jj, ii] for jj, ii in zip(ref_idxs, range(self.tica.dim))] - assert np.allclose(ref_corrs, most_corr_vals) - + assert np.all([rv == mcv for rv, mcv in zip(ref_corrs, most_corr['vals'])]) + # Check that we got the right most correlated feature trajectory + ref_feats = self.feat.transform(geoms) + ref_feats = [ref_feats[:, ii] for ii in ref_idxs] + assert np.all(np.allclose(rv, mcv) for rv, mcv in zip(ref_feats, np.squeeze(most_corr['feats']))) def test_most_corr_info_works_with_options_and_proj_idxs(self): geoms = md.load(self.MD_trajectory, top=self.MD_topology) proj_idxs = [1, 0] # the order shouldn't matter - most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats = \ - bmutils.most_corr_info(self.tica, geoms=geoms, proj_idxs=proj_idxs) - - ref_feats = self.feat.transform(geoms) + corr_dict = bmutils.most_corr(self.tica, geoms=geoms, proj_idxs=proj_idxs) # Idxs are okay ref_idxs = [np.abs(self.tica.feature_TIC_correlation[:, ii]).argmax() for ii in proj_idxs] - assert np.allclose(ref_idxs, most_corr_idxs), (ref_idxs, most_corr_idxs) + assert np.all([ri == mci for ri, mci in zip(ref_idxs, corr_dict['idxs'])]), (ref_idxs, corr_dict["idxs"]) # Corr values ref_corrs = [self.tica.feature_TIC_correlation[jj, ii] for jj, ii in zip(ref_idxs, proj_idxs)] - assert np.allclose(ref_corrs, most_corr_vals) + assert np.all([rv == mcv for rv, mcv in zip(ref_corrs, corr_dict['vals'])]) # Labels are strings and are the right number - assert len(most_corr_labels) == len(ref_idxs) - assert [isinstance(istr, str) for istr in most_corr_labels] + assert len(corr_dict["labels"]) == len(ref_idxs) + assert [isinstance(istr, str) for istr in corr_dict["labels"]] # Feature values are ok + ref_feats = self.feat.transform(geoms) ref_feats = [ref_feats[:, ii] for ii in ref_idxs] - assert [np.allclose(imcf, rf) for imcf, rf in zip(most_corr_feats, ref_feats)] + assert np.all(np.allclose(rv, mcv) for rv, mcv in zip(ref_feats, np.squeeze(corr_dict['feats']))) def test_most_corr_info_wrong_proj_idxs(self): proj_idxs = [1, 0, 10] # we don't have 10 TICs try: - bmutils.most_corr_info(self.tica, proj_idxs=proj_idxs) + bmutils.most_corr(self.tica, proj_idxs=proj_idxs) except(ValueError): pass #this should given this type of error - - class TestClusteringAndCatalogues(unittest.TestCase): def setUp(self): From 3d69d78b41cbca2d2f18ec012341cd1d715dc33e Mon Sep 17 00:00:00 2001 From: gph82 Date: Fri, 17 Mar 2017 11:54:16 +0100 Subject: [PATCH 11/23] [notebook] updated to display new method visualize.correlations --- molpx/notebooks/Projection_Explorer.ipynb | 874 ++++++---------------- 1 file changed, 212 insertions(+), 662 deletions(-) diff --git a/molpx/notebooks/Projection_Explorer.ipynb b/molpx/notebooks/Projection_Explorer.ipynb index eee982f..23fee87 100644 --- a/molpx/notebooks/Projection_Explorer.ipynb +++ b/molpx/notebooks/Projection_Explorer.ipynb @@ -117,7 +117,6 @@ "Y_filenames = [ff.replace('.xtc','.Y.npy') for ff in MD_trajfiles]\n", "try: \n", " Y = [np.load(ff) for ff in Y_filenames]\n", - " aa\n", "except:\n", " feat = pyemma.coordinates.featurizer(top)\n", " pairs = feat.pairs(range(feat.topology.n_atoms)[::2])\n", @@ -2563,7 +2562,7 @@ "data": { "text/plain": [ "((192, 2),\n", - " )" + " )" ] }, "execution_count": 6, @@ -4241,7 +4240,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -4299,7 +4298,7 @@ }, "outputs": [], "source": [ - "# Force the TICA computation\n", + "# Re-do the TICA computation to make sure we have a tica object in memory\n", "feat = pyemma.coordinates.featurizer(top)\n", "pairs = feat.pairs(range(feat.topology.n_atoms)[::2])\n", "feat.add_distances(pairs)\n", @@ -4308,6 +4307,35 @@ "Y = tica.get_output() " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The method `molpx.visualize.correlations` tries to provide a visual representation of the projected coordinates by relating them to the input features, which carry more meaning, since they are (usually) familiar parameters such as atom distances, angles, contacts etc." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# Comment or uncomment the optinal parameters and see how the method reacts\n", + "#iwd = visualize._nglview.show_mdtraj(MD_list[0][0])\n", + "iwd = None\n", + "corr, iwd = molpx.visualize.correlations(tica, \n", + " n_feats=3, \n", + " proj_idxs=[0,1,2], \n", + " geoms=MD_list[0][::100],\n", + " #verbose=True,\n", + " #proj_color_list=['red', 'blue', 'green'],\n", + " widget=iwd\n", + " )\n", + "iwd" + ] + }, { "cell_type": "markdown", "metadata": { @@ -4315,15 +4343,14 @@ "editable": true }, "source": [ - "The cell below looks pretty similar to the first `molpx.visualize.traj` call, only now we're also parssing along\n", - "the tica object itself as `projection=tica`. Can you spot the differences:\n", + "Also, `molpx.visualize.traj` can help in visualizing these correlations by parsing along the tica object itself as `projection=tica`. Can you spot the differences:\n", "* In the nglwidget?\n", "* In the trajectories?" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 13, "metadata": { "collapsed": false, "deletable": true, @@ -5095,7 +5122,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -5900,8 +5927,8 @@ " #max_frames=100,\n", " proj_idxs=[0,1], \n", " panel_height=2,\n", - " projection=tica,\n", - " #n_feats=2\n", + " projection=tica, ## this is what's new\n", + " n_feats=3\n", " )\n", " \n", "myfig.tight_layout()\n", @@ -5922,7 +5949,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 14, "metadata": { "collapsed": false, "deletable": true, @@ -5933,7 +5960,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "16-03-17 22:29:47 pyemma.coordinates.clustering.kmeans.KmeansClustering[10] INFO Algorithm did not reach convergence criterion of 1e-05 in 10 iterations. Consider increasing max_iter.\n" + "17-03-17 11:11:13 pyemma.coordinates.clustering.kmeans.KmeansClustering[7] INFO Algorithm did not reach convergence criterion of 1e-05 in 10 iterations. Consider increasing max_iter.\n" ] } ], @@ -5944,7 +5971,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "metadata": { "collapsed": false, "deletable": true, @@ -5960,7 +5987,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "metadata": { "collapsed": false, "deletable": true, @@ -6731,7 +6758,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -6779,7 +6806,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 17, "metadata": { "collapsed": false, "deletable": true, @@ -6792,7 +6819,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 18, "metadata": { "collapsed": false, "deletable": true, @@ -7563,7 +7590,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -7614,7 +7641,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 19, "metadata": { "collapsed": false, "deletable": true, @@ -7627,7 +7654,7 @@ "123" ] }, - "execution_count": 18, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -7641,7 +7668,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 20, "metadata": { "collapsed": false, "deletable": true, @@ -7655,7 +7682,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "metadata": { "collapsed": false, "deletable": true, @@ -7683,7 +7710,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "metadata": { "collapsed": false, "deletable": true, @@ -7698,7 +7725,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, "metadata": { "collapsed": false, "deletable": true, @@ -7713,7 +7740,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 24, "metadata": { "collapsed": false, "deletable": true, @@ -8484,7 +8511,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -8515,7 +8542,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 25, "metadata": { "collapsed": true, "deletable": true, @@ -8550,1074 +8577,597 @@ }, "widgets": { "state": { - "018fc0aa41c047aca2eb61f0fa986783": { + "0220dbecbc1745f68b7c2031e9bb1cc9": { "views": [ { - "cell_index": 14 - } - ] - }, - "047c029783f44befa428bc71101c1537": { - "views": [ + "cell_index": 7 + }, { - "cell_index": 19 - } - ] - }, - "0749093cd02443c29b37de56625bcd37": { - "views": [ + "cell_index": 7 + }, { - "cell_index": 10 + "cell_index": 7 } ] }, - "0a1d7a21c74444fbad3ccbc37919e30c": { + "078e31af883e42cf8443cef93536a926": { "views": [ { - "cell_index": 10 + "cell_index": 32 } ] }, - "0dbe43592927492686d79df4092eee49": { + "0bb569a95b8d456098ffa090a13cfd17": { "views": [ { - "cell_index": 27 + "cell_index": 7 } ] }, - "0f4517cd73af4937a3f25cd94db7fcf3": { + "0d663a70579e4af49886241c0a0aaece": { "views": [ { - "cell_index": 23 + "cell_index": 25 } ] }, - "0fa859cb6dfa40b6b5c4ed50ff205cf3": { + "0efb3091ddb44d3a813e51e9ac9cd86f": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "0fed1a331da34da3bc4b5f5962e6b6ed": { + "124e3b8299604770ad26c1818125b3d9": { "views": [ { - "cell_index": 23 + "cell_index": 7 } ] }, - "110c579c3fee473fa2dade260a62a60e": { + "147bcaa1692b4cf8b65f94d298ac4ebc": { "views": [ { - "cell_index": 12 + "cell_index": 39 } ] }, - "11d2aacbf2bc4d94afbbd55d9a11168e": { + "158e4fc9277540ceb63d920f529a75a9": { "views": [ { "cell_index": 23 } ] }, - "16ffeeeff2a5472b8af3e17738a5a666": { + "1599b9eb4eee46138c53c906a6c9d29b": { "views": [ { - "cell_index": 12 + "cell_index": 25 } ] }, - "178e0fae0df640b186591f58c4749f3c": { + "1653c4386bc545ffa34aa54223b607fc": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "17dbdf8e22f84b9d947efeb73c75bcdf": { + "1b3ea41633a646cbb16e67de35f62db3": { "views": [ { - "cell_index": 19 + "cell_index": 7 } ] }, - "1980932c568d430d833679aeb77e982a": { + "1d31f30bab9942dcacf758d175295dd2": { "views": [ { - "cell_index": 10 - } - ] - }, - "1b0c3bb4ab6946ed99500c6a082070ab": { - "views": [ - { - "cell_index": 10 - } - ] - }, - "1eab560d93744f51a26ee54fde14c931": { - "views": [ - { - "cell_index": 19 - } - ] - }, - "20268dfa4e5b4358bf932f8b496643e8": { - "views": [ - { - "cell_index": 12 + "cell_index": 23 } ] }, - "210f3bda53db440ebcb891aa9668dc6f": { + "1d3e5d39286e4ec28a715367ea48e40e": { "views": [ { - "cell_index": 12 + "cell_index": 23 } ] }, - "21e0fef6d2dc4f6ebec541c74b4cdcfe": { + "1e5d39b5a8c9419ab73e975f6921a243": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "22ae1e136b2041f5b0d405faf11da717": { + "2082801772414e13ac279fc669f5a8e9": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "22fe64f7eb70459b947e22e5faaccbb3": { + "20a4d3ef7159434b90c9e22dab2bba07": { "views": [ { - "cell_index": 12 + "cell_index": 32 } ] }, - "29e6fb193944432ca0f3e3ce0e85fdba": { + "24a866e4a49a4b088084d081aa5f9059": { "views": [ { "cell_index": 8 } ] }, - "2a53826052a6497a90c64c9c941bd0bc": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "2af726a38e2340108f9a86512bf19a87": { + "2cb8f9a59db2428a98cb7fb8f879467c": { "views": [ { - "cell_index": 30 + "cell_index": 25 } ] }, - "2af74c87b99a464ab7503e29276e52ee": { + "2d6427b3a89a4adc8342a66b208f6b83": { "views": [ { - "cell_index": 12 + "cell_index": 29 } ] }, - "2b2546a3c9784bec898116aa9245d230": { + "2d6520da1ef142e48d35efa1718ad0c2": { "views": [ { - "cell_index": 10 + "cell_index": 7 } ] }, - "2bd0823cf1b543f8b52adf85c01faba9": { + "2fcd52bc7ac847e4b2ed5c57ae0bff0d": { "views": [ { - "cell_index": 12 + "cell_index": 25 } ] }, - "2c463732cff34e298b17835659903d8a": { + "3410d44a5aac472c959ce9de3ae1e861": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "2c4dc7944f5f4e228100dbc3656bf0c9": { + "362f97bd68054bdc955841bb3f605cd1": { "views": [ { - "cell_index": 12 - } - ] - }, - "2ca19fd246934b5bbabd2e2e1c7b867c": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "2e31ed28a18142e090578fb857950145": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "30fc779d2f8f4c3295c96495729a34bd": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "3186d6454371425db4fccdfdd9979232": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "32afe69b1f9145919c20c97f2eded8b1": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "37892a7ecb0a4138a200e77e24497b06": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "3a7029e6cc7445389ca3e1de45ca19a3": { - "views": [ - { - "cell_index": 10 - } - ] - }, - "3b81511382b34668aae6473f1d19240d": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "3ba63f31778f4faba69675698adcbc98": { - "views": [ - { - "cell_index": 27 - } - ] - }, - "3f3d4f984a2d43c0b538243ca86a1968": { - "views": [ - { - "cell_index": 11 - } - ] - }, - "42cc4be7ad904aaa8819111a7004fc18": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "44bd423630a14f008869d062308110ca": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "46825e89c4fa45da80f3a45f02205eed": { - "views": [ - { - "cell_index": 30 + "cell_index": 23 } ] }, - "4693842948ac496395f23d46ece779b8": { + "4172828e73f34867b8e739688d445abd": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "476ac8256d7f418880e7b2ad9f0607ac": { + "479da2e462704cd0af8b80776bf1c726": { "views": [ { - "cell_index": 19 + "cell_index": 22 } ] }, - "4911c01ac6534a11950bf2417a8d7624": { + "4af96b02ece84d9281f43050340dfecc": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "49fa607769f94bada815ec6638aae0dd": { + "4c10dec35ce34ad09d40f35f57a128d0": { "views": [ { "cell_index": 19 } ] }, - "4b4c35f728574591a033f3fc9917b105": { - "views": [ - { - "cell_index": 37 - } - ] - }, - "4be58c34e4fb46aa9160f5ee1281ef51": { - "views": [ - { - "cell_index": 37 - } - ] - }, - "4f4971f6e8e443afa668c5a06d2afd14": { - "views": [ - { - "cell_index": 38 - } - ] - }, - "4fbd9f5d57234801a03ba1b9973ee49c": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "51104bc101f044fb9fd07c66d2338db1": { - "views": [ - { - "cell_index": 30 - } - ] - }, - "53b60f990ea84522905636a4d98ed33b": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "53fefd3603304a81b5f34ac101d0b765": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "542b21bc1e724f969e988ff71484d9da": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "5473c708f330442bb125fed6d82fd115": { + "4d3957b5063d42898fdb981867887041": { "views": [ { - "cell_index": 11 - } - ] - }, - "565610aef3864a5abf6f0b2f28186a72": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "578b809d38dc44c1874f6892a555fac2": { - "views": [ - { - "cell_index": 27 - } - ] - }, - "57d2e542d0404390922418b15cf12863": { - "views": [ - { - "cell_index": 12 + "cell_index": 23 } ] }, - "594d4e0d896d4319a92f831be697e0bd": { + "521779480dab4bd2bddbd558e038587e": { "views": [ { - "cell_index": 30 + "cell_index": 8 } ] }, - "5d10a5e6685f4231aede0c16e1c4334d": { + "54ba5d7298b8459a90b5ac25cda96fd1": { "views": [ { "cell_index": 10 } ] }, - "5ebc585f29ef4634a8a57841279c45cc": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "5f572a3cf4da468bab4f6d6c516bfdd2": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "624dad1c792245aaab80bd4b926a2368": { - "views": [ - { - "cell_index": 11 - } - ] - }, - "626067daeda947f391fed246bd132f58": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "62d8d016a1394d5f9e4850e323921b1c": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "63759e3d7c1841bb89872d5a8a934de4": { - "views": [ - { - "cell_index": 30 - } - ] - }, - "658d4059a1af4639875bce5e5b48b712": { + "557a7cb95d774a00988fd3cf6bcb411f": { "views": [ { "cell_index": 23 } ] }, - "674943d4205f46c180e89c3467b2dd4c": { + "570cbadfa3db4247bc0b2503b9ab9b87": { "views": [ { - "cell_index": 12 + "cell_index": 10 } ] }, - "6ae7dc40ca2341beb8e4eebb8d7541ac": { + "58902bb8ad9046b18b05c70fba648c44": { "views": [ { "cell_index": 14 } ] }, - "6b0cb0fea5e642c4a0b6390d91b9926c": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "6d10d37798d5487e89b11b23d932ef96": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "6d2d7a5b89b24dc1af4bab4bc3b92a80": { + "5c0fd22cb35145949f29d0dde1152896": { "views": [ { - "cell_index": 12 - } - ] - }, - "6f3ab259284d47598a32e27514d957bb": { - "views": [ - { - "cell_index": 30 - } - ] - }, - "70656ce17acb4aca81c2d340957d65e9": { - "views": [ - { - "cell_index": 19 + "cell_index": 8 } ] }, - "70f4f25c955e4f69ba465137ba46f401": { + "5d618806931946529653a4635f6c6935": { "views": [ { - "cell_index": 14 + "cell_index": 10 } ] }, - "75867e15272a45069b14c1bde51e9ce0": { + "61fc56c6f3f941689131f13437fd6e49": { "views": [ { "cell_index": 10 } ] }, - "7846c65b1e8f4076a36673767b8fc4e6": { + "668c9874facc4c18adea196caace96c0": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "793ab05781444084a58b05d15835b8ed": { + "69d0d9123fb8499d9e48069e43017236": { "views": [ { - "cell_index": 12 + "cell_index": 8 } ] }, - "7ad9ae43fb3444739faa1b2613971110": { + "69d6a6d505e6496fb51e582940914193": { "views": [ { - "cell_index": 12 + "cell_index": 19 } ] }, - "7cb401236f6a43a5a307496385e2b1e3": { + "69fc96e7877c4ae3a89824ac732f78a4": { "views": [ { - "cell_index": 12 + "cell_index": 25 } ] }, - "7efa07bc99b14ddaa488917a64f61f5c": { + "74bc79b0cfbc46158790cb27c24e7874": { "views": [ { - "cell_index": 10 + "cell_index": 8 } ] }, - "83ade96b936349a9992871e0f868751a": { + "7c74059708ac4e129af010765ff541b1": { "views": [ { - "cell_index": 10 + "cell_index": 8 } ] }, - "84ba7d356306416fa17a6e83f34b1eb9": { + "810c923255014e48a073acd5d13fe714": { "views": [ { - "cell_index": 11 + "cell_index": 7 } ] }, - "891d1b10bccd41b596184e1234b78e8c": { + "830872db66a741d2bfc0f5ca1a3db888": { "views": [ { - "cell_index": 12 + "cell_index": 19 } ] }, - "898b1f881787467b98230153cda96bd7": { + "846d08f6d712430f97027013c3c8c46b": { "views": [ { - "cell_index": 27 + "cell_index": 8 } ] }, - "8a70c900f8644b4c8d15cc4788b4dc2d": { + "861c6c99f17846a497348a586956ea7f": { "views": [ { - "cell_index": 23 + "cell_index": 8 } ] }, - "8afe5a4b135940f1b1e6d1d32e149c59": { + "8681c4b0fa2c490cba5e35b65198ccce": { "views": [ { - "cell_index": 10 + "cell_index": 7 } ] }, - "8b54ab898c8440ef8b8c7bb3b865f0df": { + "88da69aa10ba4879b571d0f8c7d7f4be": { "views": [ { - "cell_index": 27 + "cell_index": 39 } ] }, - "8cfdea6168774a33bc68c4720711e4ac": { + "91704a2e660643ca927686215058a11f": { "views": [ { - "cell_index": 30 + "cell_index": 25 } ] }, - "8e7a1f23075545598fe74b67a61ffc1f": { + "91f0e26d286b4d5990742dd1037038c6": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "933d642417cb464a900be96d63a751a9": { + "944368586e8f406e8d3262f781bbebcf": { "views": [ { "cell_index": 23 } ] }, - "937cdd64343b4e63849dc9ad2d308a20": { + "a40b4ecd3e53459c91478b8f318cf1d4": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "95105c41b274436186a8d7e0389ecf13": { + "a846c3597e444d21a098f72cfdbf20de": { "views": [ { - "cell_index": 27 + "cell_index": 7 } ] }, - "98e40c08a32049a6bcabc8cee9dcac31": { + "b025d273383c4a739e8640d6a6a3b79a": { "views": [ { - "cell_index": 23 + "cell_index": 7 } ] }, - "9b2b8bc2b2624e9ab6c9e77517ce2a46": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "9b461597d0964ddb9d484f7c12fe8465": { + "b5e0e4e25223492eaf9b548666eb0563": { "views": [ { "cell_index": 14 } ] }, - "9cbaaa8f799646cebb36c2ecd0bd2c1c": { - "views": [ - { - "cell_index": 27 - } - ] - }, - "9f240527f058464783c83d66509c8cf1": { - "views": [ - { - "cell_index": 8 - } - ] - }, - "9f8b14b32a4a4b5b81786340cd73cd07": { - "views": [ - { - "cell_index": 11 - } - ] - }, - "a22672667f3e4b66993f3bc4213a445d": { + "b6236b7e95f34f239bd47b3ae68a0308": { "views": [ { "cell_index": 14 } ] }, - "a4c506c4dcdf4f56bc50e8be7745efe4": { + "ba2fe2c62c99493b908cc5f3b52008e1": { "views": [ { - "cell_index": 12 + "cell_index": 22 } ] }, - "a73e1626e3724e54876b9b47722c8163": { + "bca5e659777b4f15b2109e92f3c1d685": { "views": [ { - "cell_index": 10 + "cell_index": 29 } ] }, - "a8882cf6f11c470cbc341c8012862d40": { + "bcb19a498baa42cca5d9501d0ad84a09": { "views": [ { - "cell_index": 12 - } - ] - }, - "a93b1cb51ed942998265e3701ede62e7": { - "views": [ - { - "cell_index": 30 - } - ] - }, - "ab5a9e58db35491f873210bf0c56de36": { - "views": [ - { - "cell_index": 37 - } - ] - }, - "ab81995504ba46d8b9dcfdeebae3158a": { - "views": [ - { - "cell_index": 27 - } - ] - }, - "acbe2416a224402786002b3f483ffde9": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "b70d2038c2364e118fce54b9b3ac651c": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "b8796d27cb1d45e590a58d0ebf84011b": { - "views": [ - { - "cell_index": 10 - } - ] - }, - "ba9d16be75e54f58a81363c9fb554fe5": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "babcfae794664fdd91999c4aafaaa9be": { - "views": [ - { - "cell_index": 37 - } - ] - }, - "be1fedb0eb97451dae6cf439d3549770": { - "views": [ - { - "cell_index": 10 - } - ] - }, - "be357f875393495998b7b45ba2b36a41": { - "views": [ - { - "cell_index": 11 - } - ] - }, - "be64d759283c4e838579524b3d99fcec": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "bee3a820487643059034726061ea0a08": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "c0e7e9d248894446b1dd3e491bdeb837": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "c14c7a44f81a4a758fcc01c031f6628c": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "c37858c1e2bd44f98a9567003a267396": { - "views": [ - { - "cell_index": 38 - } - ] - }, - "c55b12a8781f416e843229b3576cf01b": { - "views": [ - { - "cell_index": 12 + "cell_index": 8 } ] }, - "c690e96ab943413982bd475b92317abc": { + "bdfb14d2ef62473594812cbba4f210fe": { "views": [ { - "cell_index": 11 + "cell_index": 7 } ] }, - "c6f37f0b452549a2a921855f04ecaf0a": { + "c01fe52cba8b43508d6383582bd526bf": { "views": [ { - "cell_index": 14 + "cell_index": 7 } ] }, - "c72a4bc107a64d41a402b007d6667afa": { + "c473969001e549a29d338271e929fed8": { "views": [ { - "cell_index": 12 + "cell_index": 9 } ] }, - "c7a0110d23304e589e50f8481603b1c0": { + "c65f4b088a3540ca8004bc61843eddae": { "views": [ { - "cell_index": 10 + "cell_index": 32 } ] }, - "c880e0a6d86a448887a4443c6df0dfe2": { + "cbb047d747774f16b05f09edee7eb329": { "views": [ { "cell_index": 11 } ] }, - "cbb8f7f821974e248e1ba9acbc836634": { - "views": [ - { - "cell_index": 27 - } - ] - }, - "cbf4980b45834bf4920fbf6849f73272": { - "views": [ - { - "cell_index": 37 - } - ] - }, - "d330ebdc74c04600836e78397c9a8689": { + "ccd57357ca0f468b902713bf99713411": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "d3aa99b910314362a08ba2e3c8915e5b": { + "d31e80d3f2c443bab4e22c6f5399ff79": { "views": [ { - "cell_index": 14 + "cell_index": 7 } ] }, - "d43a56908a224407ad434a21138fd74b": { + "d53afb75e876493c94ddc3aa640a0c69": { "views": [ { - "cell_index": 12 + "cell_index": 25 } ] }, - "d5303b80f4534814ba39ee07a20e624d": { + "da3841ced96f4459809538f258e56e8a": { "views": [ { - "cell_index": 14 + "cell_index": 7 } ] }, - "d670822b81bb4f56a0989cd5eeeac0cb": { + "db90b2e63fe945cd85f9d1f9963e011a": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "d755e6ed8dea46679295cff6c780a6ea": { + "e0880eacd38747aaaca653b83fdd6b24": { "views": [ { - "cell_index": 30 + "cell_index": 8 } ] }, - "d9958626bfb54a5da5e844d3d8502a22": { + "e14e89d9f1f74141aeb051dc6c406b86": { "views": [ { - "cell_index": 12 + "cell_index": 23 } ] }, - "de0110da2428486d859e97876253d183": { + "e397d9d52a114f7aa7b483fc53429e55": { "views": [ { - "cell_index": 19 + "cell_index": 7 } ] }, - "e00108eeb9204d6ea2b835efaf1dff16": { + "e4b2787cd7494e26855984dca9d5d90f": { "views": [ { - "cell_index": 37 + "cell_index": 7 } ] }, - "e1553b0bd42e431897bf90954c6190d6": { + "ea0af8c2ddf94472a6cb25339615ee1a": { "views": [ { "cell_index": 19 } ] }, - "e432e7a220224e32bdfa5141698e0c78": { + "ed3b2d4f8643437087094cb726d5c7e9": { "views": [ { - "cell_index": 12 + "cell_index": 29 } ] }, - "e569ec592aa34b89ad439df2fb74bfa7": { + "ee120f82a18a450ca0a6bf46c290ad14": { "views": [ { - "cell_index": 12 - } - ] - }, - "e6aa2a1dc8284e2b976e598283b72c88": { - "views": [ - { - "cell_index": 23 - } - ] - }, - "ea9b3098594949e8847da9e7eb298dc7": { - "views": [ - { - "cell_index": 37 - } - ] - }, - "ebdb95cd9bff42d6aa5a6827c38496c5": { - "views": [ - { - "cell_index": 12 + "cell_index": 14 } ] }, - "ed3d93e969b84469a36cc904cd259ee1": { + "ef82d1f765834944a1cc5939d2834ee4": { "views": [ { "cell_index": 23 } ] }, - "eddb3f025e6d419dbea1dfce222a02a4": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "eee6e5f4802e4b0d9b08766263d0b6cf": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "f180d827ba0d4c9995d0b036e058e6b8": { - "views": [ - { - "cell_index": 12 - } - ] - }, - "f2d15809e80145428505ec27f68f0229": { + "f2b67cb519134c829e5dfecbd8856847": { "views": [ { "cell_index": 23 } ] }, - "f322ef6b10214e43a30bce5d5dac98e6": { + "f467118d7ca34639b73b9b8c3dceb576": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "f5f43f2f36cf4de682a21527012f5613": { + "f536f3b886004fadb35c45a655e379e2": { "views": [ { - "cell_index": 12 + "cell_index": 7 } ] }, - "f66f59189ce0465b8cc4a26b680e9154": { + "f58036be5d294f30b303cd3bd057d848": { "views": [ { - "cell_index": 10 + "cell_index": 39 } ] }, - "f967f2d1fb314eba8c245b119b2a00b0": { + "f5f0424a418d4e89aff6ab92f73556c4": { "views": [ { - "cell_index": 37 + "cell_index": 7 } ] }, - "fcc4c3c131d64c88976996c008b39cec": { + "fdce46dc72e747e59ac41b891161ecea": { "views": [ { - "cell_index": 19 - } - ] - }, - "fd437315044f4400a0f3e931d3a1e1fc": { - "views": [ - { - "cell_index": 12 + "cell_index": 8 } ] }, - "fd51d3d74b3c4093ab3cd73fc80a5511": { + "fde4e131f06f4c09bd208cbb311998e1": { "views": [ { - "cell_index": 14 + "cell_index": 7 } ] } From 1b2e24d396af1faeeea36ea517701c888b3e0e1b Mon Sep 17 00:00:00 2001 From: gph82 Date: Fri, 17 Mar 2017 11:55:15 +0100 Subject: [PATCH 12/23] [bmutils.most_corr_info] now refactored to most_corr and output to dictionary --- molpx/bmutils.py | 50 +++++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/molpx/bmutils.py b/molpx/bmutils.py index 4d39115..ecfb59e 100644 --- a/molpx/bmutils.py +++ b/molpx/bmutils.py @@ -831,7 +831,7 @@ def smooth_geom(geom, n, geom_data=None, superpose=True, symmetric=True): else: return geom_out, data_out -def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None, n_args=1, proj_names='proj'): +def most_corr(correlation_input, geoms=None, proj_idxs=None, feat_name=None, n_args=1, proj_names='proj'): r""" return information about the most correlated features from a `:obj:pyemma.coodrinates.transformer` object @@ -856,32 +856,35 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None n_args : int, default is 1 Number of argmax correlation to return for each feature. + Returns ------- - most_corr_idxs : list of lists of integers + a dictionary and the nglview widget + The dictionary has these keys: + idxs : list of lists of integers List of lists with the first :obj:`n_args` indices of the features that most correlate with the projected coordinates, for each coordinate specified in :obj:`proj_idxs` - most_corr_vals : list of lists of floats + vals : list of lists of floats List with lists of correlation values (e [-1,1]) belonging to the feature indices in :obj:`most_corr_idxs' - most_corr_labels : list lists of strings + labels : list lists of strings The labels of the most correlated features. If a string was parsed as prefix in :obj:`feat_name`, these labels will be ['feat_name_%u'%i for i in most_corr_idxs']. Otherwise it will be the full feature description found in :obj:`pyemma.coordinates. - most_corr_feats : list of ndarrays + feats : list of ndarrays If :obj:`geom` was given, this will contain the most correlated feature evaluated for every frame for every projection in :obj:`proj_idxs`. Otherwise this will just be an empty list - most_corr_atom_idxs : list of lists of integers + atom_idxs : list of lists of integers In many cases, the most correlated feature can be represented visually by the atoms involved in defining it, e.g * two atoms for a distance * three for an angle * four for a dihedral * etc. - If possible, most_corr_info will try to return these indices to be used later for visualization + If possible, most_corr will try to return these indices to be used later for visualization info : a list of dictionaries containing information as strings (for stdout printing use) @@ -889,12 +892,14 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None #TODO: extend to other inputs #todo:document proj_names # TODO: CONSIDER PURE STRING WITH \N INSTEAD for output "lines" + # TODO: write a class instead of dictionary (easier refactoring) most_corr_idxs = [] most_corr_vals = [] most_corr_feats = [] most_corr_labels = [] most_corr_atom_idxs = [] + info = [] if isinstance(proj_idxs, int): proj_idxs = [proj_idxs] @@ -930,21 +935,22 @@ def most_corr_info(correlation_input, geoms=None, proj_idxs=None, feat_name=None # TODO write a warning else: ifeat = correlation_input.data_producer.featurizer.active_features[0] - #print(ifeat) - #print(atom_idxs_from_feature(ifeat)) - #print(most_corr_idxs) most_corr_atom_idxs.append(atom_idxs_from_feature(ifeat)[most_corr_idxs[-1]]) - info = [] - for ii, iproj in enumerate(proj_names): - info.append({"lines":[], "name":iproj}) - for jj, jidx in enumerate(most_corr_idxs[ii]): - istr = 'Corr[%s|feat] = %2.1f for %-50s (feat nr. %u, atom idxs %s' % \ - (iproj, most_corr_vals[ii][jj], most_corr_labels[ii][jj], jidx, most_corr_atom_idxs[ii][jj]) - info[-1]["lines"].append(istr) - info[-1]["lines"].append('') - - return most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs, info + for ii, iproj in enumerate(proj_names): + info.append({"lines":[], "name":iproj}) + for jj, jidx in enumerate(most_corr_idxs[ii]): + istr = 'Corr[%s|feat] = %2.1f for %-30s (feat nr. %u, atom idxs %s' % \ + (iproj, most_corr_vals[ii][jj], most_corr_labels[ii][jj], jidx, most_corr_atom_idxs[ii][jj]) + info[-1]["lines"].append(istr) + + corr_dict = {'idxs': most_corr_idxs, + 'vals': most_corr_vals, + 'labels': most_corr_labels, + 'feats': most_corr_feats, + 'atom_idxs': most_corr_atom_idxs, + 'info':info} + return corr_dict def atom_idxs_from_feature(ifeat): r""" @@ -961,8 +967,12 @@ def atom_idxs_from_feature(ifeat): atom_indices : list with the atoms indices representative of this feature, whatever the feature """ from pyemma.coordinates.data.featurization.distances import DistanceFeature as _DF + from pyemma.coordinates.data.featurization.misc import SelectionFeature as _SF if isinstance(ifeat, _DF): return ifeat.distance_indexes + elif isinstance(ifeat, _SF): + return _np.repeat(ifeat.indexes, 3) + pass else: # TODO write a warning? return [] From 4633230d120015acc6563f5b1d6f078d82fe686b Mon Sep 17 00:00:00 2001 From: gph82 Date: Fri, 17 Mar 2017 11:57:05 +0100 Subject: [PATCH 13/23] [visualize.traj and correlations] refactored to deal with dictionary --- molpx/visualize.py | 62 ++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/molpx/visualize.py b/molpx/visualize.py index 64fc53a..19ebce7 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -8,7 +8,7 @@ from .bmutils import link_ax_w_pos_2_nglwidget as _link_ax_w_pos_2_nglwidget, \ data_from_input as _data_from_input, \ smooth_geom as _smooth_geom,\ - most_corr_info as _most_corr_info, \ + most_corr as _most_corr_info, \ re_warp as _re_warp, \ add_atom_idxs_widget as _add_atom_idxs_widget, \ matplotlib_colors_no_blue as _bmcolors @@ -238,7 +238,7 @@ def traj(MD_trajectories, if ii == active_traj: geoms = geoms[::stride] - # For later axes-cosmetics + # For axes-cosmetics later on tmax, tmin = _np.max([time[-1] for time in times]), _np.min([time[0] for time in times]) ylims = _np.zeros((2, len(proj_idxs))) for ii, __ in enumerate(proj_idxs): @@ -247,8 +247,8 @@ def traj(MD_trajectories, ylabels = ['$\mathregular{proj_%u}$'%ii for ii in proj_idxs] # Do we have usable projection information? - __, most_corr_vals, most_corr_labels, out_feats, most_corr_atom_idxs = _most_corr_info(projection, geoms=geoms, proj_idxs=proj_idxs, n_args=n_feats) - if out_feats != []: + corr_dict = _most_corr_info(projection, geoms=geoms, proj_idxs=proj_idxs, n_args=n_feats) + if corr_dict["feats"] != []: # Then extend the trajectory selection to include the active trajectory twice traj_selection = _np.insert(traj_selection, _np.argwhere([active_traj==ii for ii in traj_selection]).squeeze(), @@ -308,8 +308,8 @@ def traj(MD_trajectories, iax = myax[ir, ic] # Grab the right properties iproj, ifeat = _np.unravel_index(kk, (len(proj_idxs), n_feats)) - ifeat_val = out_feats[iproj][:, ifeat] - ilabel = most_corr_labels[iproj][ifeat] + ifeat_val = corr_dict["feats"][iproj][:, ifeat] + ilabel = corr_dict["labels"][iproj][ifeat] icol = colors[iproj] # Plot lines = iax.plot(time_feat, ifeat_val, color=icol)[0] @@ -325,12 +325,12 @@ def traj(MD_trajectories, clear_lines=False, widget=widget, crosshairs=False, directionality='w2a') - # Add the correlation vanlue - iax.legend([lines],['Corr(feat|%s)=%2.1f' % (ylabels[iproj], most_corr_vals[iproj][ifeat])], + # Add the correlation value + iax.legend([lines],['Corr(feat|%s)=%2.1f' % (ylabels[iproj], corr_dict["vals"][iproj][ifeat])], fontsize=smallfontsize, loc='best', frameon=False) # Add visualization (let the method decide if it's possible or not) - widget = _add_atom_idxs_widget([most_corr_atom_idxs[iproj][ifeat]], widget, color_list=[icol]) + widget = _add_atom_idxs_widget([corr_dict["atom_idxs"][iproj][ifeat]], widget, color_list=[icol]) if plot_FES: if len(proj_idxs)<2: @@ -353,9 +353,9 @@ def correlations(correlation_input, proj_idxs=None, feat_name=None, widget=None, - color_list=None, + proj_color_list=None, n_feats=1, - verbose=True): + verbose=False): r""" Provide a visual and textual representation of the linear correlations between projected coordinates (PCA, TICA) and original features. @@ -387,10 +387,10 @@ def correlations(correlation_input, Use with caution and clean bookkeeping! - color_list: list, default is None - list of colors to provide the representations with. The default None yields blue. + proj_color_list: list, default is None + projection specific list of colors to provide the representations with. The default None yields blue. In principle, the list can contain one color for each projection (= as many colors as len(proj_idxs) - but if your list is short it will just default to the last color. This way, color_list=['black'] will paint + but if your list is short it will just default to the last color. This way, proj_color_list=['black'] will paint all black regardless len(proj_idxs) @@ -414,33 +414,31 @@ def correlations(correlation_input, # todo document # todo test - most_corr_idxs, most_corr_vals, most_corr_labels, most_corr_feats, most_corr_atom_idxs, lines = \ - _most_corr_info(correlation_input, geoms=geoms, proj_idxs=proj_idxs, feat_name=feat_name, n_args=n_feats) - - if verbose: - for line in lines: - print(line["name"]) - for line in line["lines"]: - print(line) + corr_dict = _most_corr_info(correlation_input, geoms=geoms, proj_idxs=proj_idxs, feat_name=feat_name, n_args=n_feats) # Create ngl_viewer widget if geoms is not None and widget is None: widget = _nglview.show_mdtraj(geoms.superpose(geoms)) - #else: - # iwd = widget - if color_list is None: - color_list = ['blue']*len(most_corr_idxs) - elif isinstance(color_list, list) and len(color_list) Date: Wed, 22 Mar 2017 12:27:43 +0100 Subject: [PATCH 14/23] [visualize.correlations] beter proj_color_list exception handling --- molpx/visualize.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/molpx/visualize.py b/molpx/visualize.py index 19ebce7..5440bbc 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -423,7 +423,9 @@ def correlations(correlation_input, if proj_color_list is None: proj_color_list = ['blue'] * len(corr_dict["idxs"]) elif isinstance(proj_color_list, list) and len(proj_color_list) Date: Wed, 22 Mar 2017 12:28:51 +0100 Subject: [PATCH 15/23] [test_visualize] added. Better coverage of the API --- molpx/tests/test_visualize.py | 105 ++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 molpx/tests/test_visualize.py diff --git a/molpx/tests/test_visualize.py b/molpx/tests/test_visualize.py new file mode 100644 index 0000000..afb3bb6 --- /dev/null +++ b/molpx/tests/test_visualize.py @@ -0,0 +1,105 @@ +__author__ = 'gph82' +# Since the complicated stuff and the potential for undetectable errors is in bmutils, heavy testing should be done there. This is an API test for checking +# input parsing and decision making (if then) inside the visualize API +import unittest +import pyemma +import os +import tempfile +import numpy as np +import shutil +import molpx +from glob import glob +from molpx import visualize +import mdtraj as md + +class TestTrajInputs(unittest.TestCase): + + def setUp(self): + self.MD_trajectory_files = glob(molpx._molpxdir(join='notebooks/data/c-alpha_centered.stride.1000*xtc')) + self.MD_topology_file = glob(molpx._molpxdir(join='notebooks/data/*pdb'))[0] + self.MD_geoms = [md.load(ff, top=self.MD_topology_file) for ff in self.MD_trajectory_files] + self.MD_top = self.MD_geoms[0].topology + self.tempdir = tempfile.mkdtemp('test_molpx') + self.projected_files = [os.path.join(self.tempdir,'Y.%u.npy'%ii) for ii in range(len(self.MD_trajectory_files))] + self.feat = pyemma.coordinates.featurizer(self.MD_topology_file) + self.feat.add_all() + source = pyemma.coordinates.source(self.MD_trajectory_files, features=self.feat) + self.tica = pyemma.coordinates.tica(source,lag=1, dim=10) + self.Y = self.tica.get_output() + self.F = source.get_output() + [np.save(ifile,iY) for ifile, iY in zip(self.projected_files, self.Y)] + [np.savetxt(ifile.replace('.npy','.dat'),iY) for ifile, iY in zip(self.projected_files, self.Y)] + + def tearDown(self): + shutil.rmtree(self.tempdir) + + def test_simplest_inputs_memory(self): + visualize.traj(self.MD_geoms, self.MD_top, self.Y) + + def test_simplest_inputs_disk(self): + visualize.traj(self.MD_trajectory_files, self.MD_topology_file, self.projected_files) + visualize.traj(self.MD_trajectory_files, self.MD_topology_file, [ifile.replace('.npy', '.dat') for ifile in self.projected_files]) + + def test_fail_without_top(self): + # This should fail + try: + visualize.traj(self.MD_trajectory_files, "unexisting_file", self.Y) + except OSError: + pass + # This should pass + visualize.traj(self.MD_geoms, "unexisting_file", self.Y) + + def test_listify_inputs(self): + visualize.traj(self.MD_geoms[0], self.MD_top, self.Y[0]) + + def test_listify_params(self): + visualize.traj(self.MD_geoms, self.MD_top, self.Y, proj_idxs=1) + visualize.traj(self.MD_geoms, self.MD_top, self.Y, active_traj=1) + + def test_plotting_params(self): + visualize.traj(self.MD_geoms, self.MD_top, self.Y, sharey_traj=True) + + def test_fail_on_FES(self): + try: + visualize.traj(self.MD_geoms, self.MD_top, self.Y, sharey_traj=True, plot_FES=True, proj_idxs=[0,1,2]) + except NotImplementedError: + pass + +class TestCorrelationsInput(unittest.TestCase): + + def setUp(self): + self.MD_trajectory_files = glob(molpx._molpxdir(join='notebooks/data/c-alpha_centered.stride.1000*xtc'))[:1] + self.MD_topology_file = glob(molpx._molpxdir(join='notebooks/data/*pdb'))[0] + self.MD_geoms = [md.load(ff, top=self.MD_topology_file) for ff in self.MD_trajectory_files] + self.MD_top = self.MD_geoms[0].topology + self.tempdir = tempfile.mkdtemp('test_molpx') + self.projected_files = [os.path.join(self.tempdir, 'Y.%u.npy' % ii) for ii in + range(len(self.MD_trajectory_files))] + self.feat = pyemma.coordinates.featurizer(self.MD_topology_file) + self.feat.add_all() + source = pyemma.coordinates.source(self.MD_trajectory_files, features=self.feat) + self.tica = pyemma.coordinates.tica(source, lag=1, dim=10) + self.Y = self.tica.get_output() + self.F = source.get_output() + [np.save(ifile, iY) for ifile, iY in zip(self.projected_files, self.Y)] + [np.savetxt(ifile.replace('.npy', '.dat'), iY) for ifile, iY in zip(self.projected_files, self.Y)] + + def tearDown(self): + shutil.rmtree(self.tempdir) + + def test_correlations_inputs(self): + visualize.correlations(self.tica) + + def test_correlations_inputs_verbose(self): + visualize.correlations(self.tica, verbose=True) + + def test_correlations_inputs_color_list_parsing(self): + visualize.correlations(self.tica, proj_color_list=['green']) + + def test_correlations_inputs_FAIL_color_list_parsing(self): + try: + visualize.correlations(self.tica, proj_color_list='green') + except TypeError: + pass +if __name__ == '__main__': + unittest.main() From 6c907fc230b5371cbcc591a41ead2bb23c11268d Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 22 Mar 2017 15:06:54 +0100 Subject: [PATCH 16/23] [test_visualize] TICA not needed to test API --- molpx/tests/test_visualize.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/molpx/tests/test_visualize.py b/molpx/tests/test_visualize.py index afb3bb6..a9e005d 100644 --- a/molpx/tests/test_visualize.py +++ b/molpx/tests/test_visualize.py @@ -23,10 +23,8 @@ def setUp(self): self.projected_files = [os.path.join(self.tempdir,'Y.%u.npy'%ii) for ii in range(len(self.MD_trajectory_files))] self.feat = pyemma.coordinates.featurizer(self.MD_topology_file) self.feat.add_all() - source = pyemma.coordinates.source(self.MD_trajectory_files, features=self.feat) - self.tica = pyemma.coordinates.tica(source,lag=1, dim=10) - self.Y = self.tica.get_output() - self.F = source.get_output() + self.source = pyemma.coordinates.source(self.MD_trajectory_files, features=self.feat) + self.Y = self.source.get_output(dimensions=np.arange(10)) [np.save(ifile,iY) for ifile, iY in zip(self.projected_files, self.Y)] [np.savetxt(ifile.replace('.npy','.dat'),iY) for ifile, iY in zip(self.projected_files, self.Y)] From dcd306a05f333960865860f2393adf827a0e0d9e Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 22 Mar 2017 15:07:32 +0100 Subject: [PATCH 17/23] [visualize] all calls nglwidget are wrapped in new method _initialize_nglwidget_if_save --- molpx/visualize.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/molpx/visualize.py b/molpx/visualize.py index 5440bbc..68a4ad2 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -19,6 +19,27 @@ import nglview as _nglview import mdtraj as _md +# All calls to nglview call actually this function +def _initialize_nglwidget_if_save(geom, mock=True): + try: + return _nglview.show_mdtraj(geom) + except: + if mock: + print("molPX has to be used inside a notebook, not from terminal. A mock nglwidget is being returned." + "Ignore this message if testing, " + "otherwise refer to molPX documentation") + return _mock_nglwidget(geom) + else: + raise Exception("molPX has to be used inside a notebook, not from terminal") + +class _mock_nglwidget(object): + r""" + mock widget, which isn't even a widget, to allow for testing inside of the terminal + """ + def __init__(self, geom): + self.trajectory_0 = geom + def observe(self,*args, **kwargs): + pass def FES(MD_trajectories, MD_top, projected_trajectory, proj_idxs = [0,1], @@ -418,7 +439,7 @@ def correlations(correlation_input, # Create ngl_viewer widget if geoms is not None and widget is None: - widget = _nglview.show_mdtraj(geoms.superpose(geoms)) + widget = _initialize_nglwidget_if_save(geoms.superpose(geoms)) if proj_color_list is None: proj_color_list = ['blue'] * len(corr_dict["idxs"]) @@ -501,7 +522,7 @@ def sample(positions, geom, ax, # Create ngl_viewer widget if widget is None: - iwd = _nglview.show_mdtraj(geom) + iwd = _initialize_nglwidget_if_save(geom) else: iwd = widget From 41c5df8fcb14fa6a865b13ec3d92727371301a15 Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 22 Mar 2017 15:08:58 +0100 Subject: [PATCH 18/23] [test_molpx] widget tests now available --- molpx/tests/test_molPX.py | 2 +- molpx/tests/test_visualize.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/molpx/tests/test_molPX.py b/molpx/tests/test_molPX.py index d9acc03..d140980 100644 --- a/molpx/tests/test_molPX.py +++ b/molpx/tests/test_molPX.py @@ -33,7 +33,7 @@ def test_generate_sample(self): molpx.generate.sample(self.MD_trajectory, self.topology, self.projected_file) # Cannot get the widget to run outside the notebook because it needs an interact bar - def _test_visualize_qsample(self): + def test_visualize_qsample(self): pos, geom_smpl = molpx.generate.sample(self.MD_trajectory, self.topology, self.projected_file) plt.figure() iwd = molpx.visualize.sample(pos, geom_smpl, plt.gca()) diff --git a/molpx/tests/test_visualize.py b/molpx/tests/test_visualize.py index a9e005d..2a4f30b 100644 --- a/molpx/tests/test_visualize.py +++ b/molpx/tests/test_visualize.py @@ -42,7 +42,7 @@ def test_fail_without_top(self): # This should fail try: visualize.traj(self.MD_trajectory_files, "unexisting_file", self.Y) - except OSError: + except (OSError, IOError): pass # This should pass visualize.traj(self.MD_geoms, "unexisting_file", self.Y) From aea45064882a6980ae434157d9ed00c61a7911bb Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 22 Mar 2017 15:10:39 +0100 Subject: [PATCH 19/23] [visualize.traj] bugfix on when to plot FES --- molpx/visualize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/molpx/visualize.py b/molpx/visualize.py index 68a4ad2..a6b3da1 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -354,7 +354,7 @@ def traj(MD_trajectories, widget = _add_atom_idxs_widget([corr_dict["atom_idxs"][iproj][ifeat]], widget, color_list=[icol]) if plot_FES: - if len(proj_idxs)<2: + if len(proj_idxs)!=2: raise NotImplementedError('Can only plot 2D FES if more than one projection idxs has been ' 'specificed, but only got %s. \n In the future a 1D histogramm will ' 'be shown.'%proj_idxs) From dd2c89ed7b05723713dbb503fbee607ebf6106bd Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 22 Mar 2017 16:55:17 +0100 Subject: [PATCH 20/23] Revert "[visualize] all calls nglwidget are wrapped in new method _initialize_nglwidget_if_save" This reverts commit dcd306a05f333960865860f2393adf827a0e0d9e. --- molpx/visualize.py | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/molpx/visualize.py b/molpx/visualize.py index a6b3da1..c7ce5dd 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -19,27 +19,6 @@ import nglview as _nglview import mdtraj as _md -# All calls to nglview call actually this function -def _initialize_nglwidget_if_save(geom, mock=True): - try: - return _nglview.show_mdtraj(geom) - except: - if mock: - print("molPX has to be used inside a notebook, not from terminal. A mock nglwidget is being returned." - "Ignore this message if testing, " - "otherwise refer to molPX documentation") - return _mock_nglwidget(geom) - else: - raise Exception("molPX has to be used inside a notebook, not from terminal") - -class _mock_nglwidget(object): - r""" - mock widget, which isn't even a widget, to allow for testing inside of the terminal - """ - def __init__(self, geom): - self.trajectory_0 = geom - def observe(self,*args, **kwargs): - pass def FES(MD_trajectories, MD_top, projected_trajectory, proj_idxs = [0,1], @@ -439,7 +418,7 @@ def correlations(correlation_input, # Create ngl_viewer widget if geoms is not None and widget is None: - widget = _initialize_nglwidget_if_save(geoms.superpose(geoms)) + widget = _nglview.show_mdtraj(geoms.superpose(geoms)) if proj_color_list is None: proj_color_list = ['blue'] * len(corr_dict["idxs"]) @@ -522,7 +501,7 @@ def sample(positions, geom, ax, # Create ngl_viewer widget if widget is None: - iwd = _initialize_nglwidget_if_save(geom) + iwd = _nglview.show_mdtraj(geom) else: iwd = widget From d354ecc98740de7a5e55de4c5fd8dfb0f9f5185b Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 22 Mar 2017 16:58:43 +0100 Subject: [PATCH 21/23] [tests] choose mpl Agg backend for tests --- molpx/tests/test_molPX.py | 2 ++ molpx/tests/test_visualize.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/molpx/tests/test_molPX.py b/molpx/tests/test_molPX.py index d140980..86a5363 100644 --- a/molpx/tests/test_molPX.py +++ b/molpx/tests/test_molPX.py @@ -8,6 +8,8 @@ import shutil import molpx from matplotlib import pyplot as plt +plt.switch_backend('Agg') # allow tests + class MyTestCase(unittest.TestCase): def setUp(self): diff --git a/molpx/tests/test_visualize.py b/molpx/tests/test_visualize.py index 2a4f30b..b14ced5 100644 --- a/molpx/tests/test_visualize.py +++ b/molpx/tests/test_visualize.py @@ -11,6 +11,8 @@ from glob import glob from molpx import visualize import mdtraj as md +import matplotlib.pyplot as plt +plt.switch_backend('Agg') # allow tests class TestTrajInputs(unittest.TestCase): From 2d231dc9a3b3463e60c5eaf1a802cc1f7e326080 Mon Sep 17 00:00:00 2001 From: gph82 Date: Wed, 22 Mar 2017 15:07:32 +0100 Subject: [PATCH 22/23] [visualize] all calls nglwidget are wrapped in new method _initialize_nglwidget_if_safe --- molpx/visualize.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/molpx/visualize.py b/molpx/visualize.py index c7ce5dd..b7ee493 100644 --- a/molpx/visualize.py +++ b/molpx/visualize.py @@ -19,6 +19,27 @@ import nglview as _nglview import mdtraj as _md +# All calls to nglview call actually this function +def _initialize_nglwidget_if_safe(geom, mock=True): + try: + return _nglview.show_mdtraj(geom) + except: + if mock: + print("molPX has to be used inside a notebook, not from terminal. A mock nglwidget is being returned." + "Ignore this message if testing, " + "otherwise refer to molPX documentation") + return _mock_nglwidget(geom) + else: + raise Exception("molPX has to be used inside a notebook, not from terminal") + +class _mock_nglwidget(object): + r""" + mock widget, which isn't even a widget, to allow for testing inside of the terminal + """ + def __init__(self, geom): + self.trajectory_0 = geom + def observe(self,*args, **kwargs): + pass def FES(MD_trajectories, MD_top, projected_trajectory, proj_idxs = [0,1], @@ -418,7 +439,7 @@ def correlations(correlation_input, # Create ngl_viewer widget if geoms is not None and widget is None: - widget = _nglview.show_mdtraj(geoms.superpose(geoms)) + widget = _initialize_nglwidget_if_safe(geoms.superpose(geoms)) if proj_color_list is None: proj_color_list = ['blue'] * len(corr_dict["idxs"]) @@ -501,7 +522,7 @@ def sample(positions, geom, ax, # Create ngl_viewer widget if widget is None: - iwd = _nglview.show_mdtraj(geom) + iwd = _initialize_nglwidget_if_safe(geom) else: iwd = widget From b99676a78cc6e891cd354b2e8b48705d563526e1 Mon Sep 17 00:00:00 2001 From: gph82 Date: Thu, 23 Mar 2017 10:30:43 +0100 Subject: [PATCH 23/23] [docs] Added changelog --- doc/source/CHANGELOG.rst | 25 +++++++++++++++++++++++++ doc/source/index.rst | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 doc/source/CHANGELOG.rst diff --git a/doc/source/CHANGELOG.rst b/doc/source/CHANGELOG.rst new file mode 100644 index 0000000..ed3958b --- /dev/null +++ b/doc/source/CHANGELOG.rst @@ -0,0 +1,25 @@ +========= +Changelog +========= + +0.1.5 (tba) + +**New features**: + +- ``molpx.visualize``: + - new method ``visualize.correlations()`` to visualize the feature_TIC_correlation attribute of PyEMMA TICA-objects + in the widget + - method ``visualize.traj()`` has new optional parameter ``projection`` to accept a PyEMMA TICA object to + visualize the linear correlations in the widget AND in as trajectories f(t) + +- ``molpx.bmutils``: + - new method ``bmutils.most_corr_info()`` to support the new methods in ``molpx.visualize`` + +- notebooks: + - new section added to showcase the better PyEMMA integration, in particular with TICA + +**Fixes**: + +- ``molpx.visualize``: + - all calls to ``nglview.show_mdtraj()`` has been wrapped in ``_initialize_nglwidget_if_safe`` to avoid + erroring in tests \ No newline at end of file diff --git a/doc/source/index.rst b/doc/source/index.rst index beaefc3..ec205d9 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -13,7 +13,8 @@ Example Jupyter Notebook About & YouTube Introduction Installation Guide - + Changelog + Indices and tables ==================