diff --git a/calour/analysis.py b/calour/analysis.py index 906749fb..93c0ceb7 100644 --- a/calour/analysis.py +++ b/calour/analysis.py @@ -65,13 +65,14 @@ def correlation(exp, field, method='spearman', nonzero=False, transform=None, nu the desired FDR control level numperm : int number of permutations to perform + fdr_method : str + method to compute FDR. Allowed method include "", "" Returns ------- newexp : calour.Experiment - The experiment with only significant (FDR<=maxfval) correlated features, sorted according to correlation size + The experiment with only significant (FDR<=maxfval) correlated features, sorted according to correlation coefficient ''' - # remove features not present in both groups cexp = exp.filter_min_abundance(0, strict=True) data = cexp.get_data(copy=True, sparse=False).transpose() @@ -112,7 +113,7 @@ def diff_abundance(exp, field, val1, val2=None, method='meandiff', transform='ra The field to test by val1: str or list of str The values for the first group. - val1: str or list of str or None (optional) + val2: str or list of str or None (optional) None (default) to compare to all other samples (not in val1) method : str or function the method to use for the t-statistic test. options: @@ -198,7 +199,7 @@ def diff_abundance_kw(exp, field, transform='rankdata', numperm=1000, alpha=0.1, labels[exp.sample_metadata[field].values == clabel] = idx logger.debug('Found %d unique sample labels' % (idx+1)) keep, odif, pvals = dsfdr.dsfdr(data, labels, method='kruwallis', transform_type=transform, alpha=alpha, numperm=numperm, fdr_method=fdr_method) - print(keep) + logger.info('Found %d significant features' % (np.sum(keep))) return _new_experiment_from_pvals(cexp, exp, keep, odif, pvals) diff --git a/calour/experiment.py b/calour/experiment.py index ce827406..39f6e58d 100644 --- a/calour/experiment.py +++ b/calour/experiment.py @@ -165,16 +165,29 @@ def __getitem__(self, pos): The abundance of feature ID in sample ID ''' if not isinstance(pos, tuple) or len(pos) != 2: - raise ValueError('Must supply sample ID, feature ID') + raise SyntaxError('Must supply sample ID, feature ID') + sample = pos[0] feature = pos[1] - if sample not in self.sample_metadata.index: - raise ValueError('SampleID %s not in experiment samples' % sample) - if feature not in self.feature_metadata.index: - raise ValueError('FeatureID %s not in experiment features' % feature) - sample_pos = self.sample_metadata.index.get_loc(sample) - feature_pos = self.feature_metadata.index.get_loc(feature) - return self.data[sample_pos, feature_pos] + if isinstance(sample, slice): + sample_pos = sample + else: + try: + sample_pos = self.sample_metadata.index.get_loc(sample) + except KeyError: + raise KeyError('SampleID %s not in experiment samples' % sample) + if isinstance(feature, slice): + feature_pos = feature + else: + try: + feature_pos = self.feature_metadata.index.get_loc(feature) + except KeyError: + raise KeyError('FeatureID %s not in experiment features' % feature) + if self.sparse: + dat = self.get_data(sparse=False) + else: + dat = self.get_data() + return dat[sample_pos, feature_pos] def copy(self): '''Copy the object. @@ -220,12 +233,14 @@ def inner(*args, **kwargs): exp = args[0] log = exp._log try: + logger.debug('Run func {}'.format(fn)) new_exp = func(*args, **kwargs) if exp._log is True: param = ['%r' % i for i in args[1:]] + ['%s=%r' % (k, v) for k, v in kwargs.items()] param = ', '.join(param) new_exp._call_history.append('{0}({1})'.format(fn, param)) exp._log = False + logger.debug('Current object: {}'.format(new_exp)) finally: # set log status back exp._log = log @@ -275,7 +290,7 @@ def get_data(self, sparse=None, copy=False): @property def shape(self): - return self.get_data().shape + return self.data.shape def reorder(self, new_order, axis=0, inplace=False): '''Reorder according to indices in the new order. diff --git a/calour/filtering.py b/calour/filtering.py index 7a42aacf..ed91fa61 100644 --- a/calour/filtering.py +++ b/calour/filtering.py @@ -16,6 +16,7 @@ filter_mean filter_prevalence filter_min_abundance + filter_sample_categories ''' # ---------------------------------------------------------------------------- @@ -96,6 +97,44 @@ def downsample(exp, field, axis=0, num_keep=None, inplace=False): return exp.reorder(np.concatenate(indices), axis=axis, inplace=inplace) +@Experiment._record_sig +def filter_sample_categories(exp, field, min_samples=5, inplace=False): + '''Filter sample categories that have too few samples. + + This is useful to get rid of categories with few samples for + supervised classification training. It also drops the samples + that don't have any value in the field. + + Examples + -------- + + Parameters + ---------- + field : str + The name of the column in samples metadata table. This column + should has categorical values + min_samples : int (optional) + Filter away the samples with a value in the given column if its sample count is + less than min_samples. + inplace : bool (optional) + False (default) to create a copy of the experiment, True to filter inplace + + Returns + ------- + ``Experiment`` + filtered so contains only features/samples present in exp and in ids + + ''' + exp = exp.reorder(exp.sample_metadata[field].notnull(), inplace=inplace) + unique, counts = np.unique(exp.sample_metadata[field].values, return_counts=True) + drop_values = [i for i, j in zip(unique, counts) if j < min_samples] + if drop_values: + logger.debug('Drop samples with {0} values in column {1}'.format(drop_values, field)) + return exp.filter_samples(field, drop_values, negate=True, inplace=inplace) + else: + return exp + + @Experiment._record_sig def filter_by_metadata(exp, field, select, axis=0, negate=False, inplace=False): '''Filter samples or features by metadata. @@ -120,8 +159,6 @@ def filter_by_metadata(exp, field, select, axis=0, negate=False, inplace=False): ``Experiment`` the filtered object ''' - logger.debug('filter_by_metadata') - if axis == 0: x = exp.sample_metadata elif axis == 1: @@ -324,7 +361,7 @@ def _unique_cut(x, unique=0.05): def _freq_ratio(x, ratio=2): - '''the ratio of the most common value to the second most common value + '''the ratio of the counts of the most common value to the second most common value Return True if the ratio is not greater than "ratio". @@ -425,7 +462,6 @@ def filter_ids(exp, ids, axis=1, negate=False, inplace=False): ``Experiment`` filtered so contains only features/samples present in exp and in ids ''' - logger.debug('filter_ids') okpos = [] tot_ids = 0 if axis == 0: diff --git a/calour/tests/test_experiment.py b/calour/tests/test_experiment.py index 5da1057c..7b49045c 100644 --- a/calour/tests/test_experiment.py +++ b/calour/tests/test_experiment.py @@ -218,13 +218,23 @@ def test_from_pandas_round_trip(self): def test_getitem(self): self.assertEqual(self.test1['S5', 'TACGTAGGGTGCAAGCGTTAATCGGAATTACTGGGCGTAAAGCGTGCGCAGGCGGTTTTGTAAGTCTGATGTGAAATCCCCGGGCTCAACCTGGGAATTGCATTGGAGACTGCAAGGCTAGAATCTGGCAGAGGGGGGTAGAATTCCACG'], 5) self.assertEqual(self.test1['S4', 'TACGTAGGTCCCGAGCGTTGTCCGGATTTATTGGGCGTAAAGGGTGCGTAGGCGGCCTGTTAAGTAAGTGGTTAAATTGTTGGGCTCAACCCAATCCGGCCACTTAAACTGGCAGGCTAGAGTATTGGAGAGGCAAGTGGAATTCCATGT'], 0) - with self.assertRaises(ValueError): + with self.assertRaises(KeyError): self.test1['Pita', 'TACGTAGGTCCCGAGCGTTGTCCGGATTTATTGGGCGTAAAGGGTGCGTAGGCGGCCTGTTAAGTAAGTGGTTAAATTGTTGGGCTCAACCCAATCCGGCCACTTAAACTGGCAGGCTAGAGTATTGGAGAGGCAAGTGGAATTCCATGT'] - with self.assertRaises(ValueError): + with self.assertRaises(KeyError): self.test1['S5', 'Pita'] - with self.assertRaises(ValueError): + with self.assertRaises(SyntaxError): self.test1['S5'] + def test_shape(self): + self.assertEqual(self.test1.shape, (21, 12)) + + def test_getitem_slice(self): + # 1st sample + npt.assert_array_equal(self.test1['S1', :], self.test1.data.toarray()[0, :]) + # 2nd feature + npt.assert_array_equal(self.test1[:, 'TACATAGGTCGCAAGCGTTATCCGGAATTATTGGGCGTAAAGCGTTCGTAGGCTGTTTATTAAGTCTGGAGTCAAATCCCAGGGCTCAACCCTGGCTCGCTTTGGATACTGGTAAACTAGAGTTAGATAGAGGTAAGCAGAATTCCATGT'], + self.test1.data.toarray()[:, 1]) + if __name__ == "__main__": main() diff --git a/calour/tests/test_filtering.py b/calour/tests/test_filtering.py index 78be1996..0262b71b 100644 --- a/calour/tests/test_filtering.py +++ b/calour/tests/test_filtering.py @@ -211,6 +211,14 @@ def test_filter_ids_samples_inplace_negate(self): self.assertCountEqual(list(exp.sample_metadata.index.values), oksamples) self.assertIs(exp, self.test1) + def test_filter_sample_categories(self): + test = self.test1.filter_ids(['badsample'], axis=0, negate=True) + # does not filter anything + assert_experiment_equal(test.filter_sample_categories('group', 9), test) + # filter group of 2 + assert_experiment_equal(test.filter_sample_categories('group', 10), + test.filter_samples('group', '1')) + if __name__ == '__main__': main() diff --git a/notebooks/Example-feces-egypt.ipynb b/notebooks/Example-feces-egypt.ipynb deleted file mode 100644 index 945fd7f5..00000000 --- a/notebooks/Example-feces-egypt.ipynb +++ /dev/null @@ -1,1939 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# load calour" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import calour as ca\n", - "% matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "we want to get info messages (10 is debug, 20 is info, 30 is warning)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "ca.set_log_level(20)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Load the dataset\n", - "## Data from:\n", - "**Differences in Gut Metabolites and Microbial Composition and Functions between Egyptian and U.S. Children Are Consistent with Their Diets**\n", - "\n", - "*Shankar, V., Gouda, M., Moncivaiz, J., Gordon, A., Reo, N. V., Hussein, L., & Paliy, O. (2017).*\n", - "\n", - "*mSystems, 2(1), e00169-16*\n", - "\n", - "It is an amplicon experiment, so we use `load_amplicon`. This gives us some more amplicon experiment specific functions and defaults (i.e. plotting by taxonomy, etc.)\n", - "\n", - "We load the biom table and mapping file.\n", - "\n", - "Specify normalization depth to 10000 reads/sample\n", - "\n", - "And filter away samples with < 1000 reads\n", - "\n", - "By default the data is loaded as sparse scipy matrix. Can use dense instead by setting `sparse=False`" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-03-12 23:06:17 INFO loaded 42 samples, 4658 observations\n", - "2017-03-12 23:06:17 INFO 42 remaining\n" - ] - } - ], - "source": [ - "exp = ca.read_amplicon('data/egypt.biom', 'data/egypt.sample.txt', normalize=10000, filter_reads=1000)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "AmpliconExperiment egypt.biom with 42 samples, 4658 features" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## An Experiment (which AmpliconExperiment is a subclass) contains 3 basic attributes:\n", - "- data : an S (number samples) x F (number features) 2d numpy array or scipy.Sparse matrix\n", - "- sample_metadata : pandas.DataFrame. Stores all the per-sample information. Index is the SampleID\n", - "- feature_metadata : pandas.DataFrame. Stores all the per-feature information. For AmpliconExperiment, index is the sequence\n", - "\n", - "Data, sample_metadata and feature_metadata are synchronized, so position (s,f) in the data matrix corresponds to position s in the sample_metadata and position f in the feature_metadata" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Index(['#SampleID', 'BioSample_s', 'Experiment_s', 'Library_Name_s',\n", - " 'LoadDate_s', 'MBases_l', 'MBytes_l', 'Run_s', 'SRA_Sample_s',\n", - " 'Sample_Name_s', 'collection_date_s', 'geo_loc_name_s',\n", - " 'host_subject_id_s', 'lat_lon_s', 'Assay_Type_s', 'AssemblyName_s',\n", - " 'BioProject_s', 'BioSampleModel_s', 'Center_Name_s', 'Consent_s',\n", - " 'InsertSize_l', 'LibraryLayout_s', 'LibrarySelection_s',\n", - " 'LibrarySource_s', 'Organism_s', 'Platform_s', 'ReleaseDate_s',\n", - " 'SRA_Study_s', 'env_biome_s', 'env_feature_s', 'env_material_s',\n", - " 'g1k_analysis_group_s', 'g1k_pop_code_s', 'host_s', 'source_s',\n", - " '_calour_original_abundance'],\n", - " dtype='object')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp.sample_metadata.columns" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Analysis" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Cluster the features (bacteria)\n", - "So similar behaving features will be close to each other.\n", - "\n", - "We also specify `min_abundance=10` to filter away features with less than 10 (normalized) reads total over all samples.\n", - "\n", - "This makes clustering and analysis faster, as well as adding more power (as the < 10 reads total features don't contain a lot of information)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-03-12 23:06:37 INFO 714 remaining\n" - ] - } - ], - "source": [ - "exp_c = exp.cluster_features(min_abundance=10)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "AmpliconExperiment egypt.biom with 42 samples, 714 features" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp_c" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## let's look at the data" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": 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": "stdout", - "output_type": "stream", - "text": [ - "found 15\n" - ] - } - ], - "source": [ - "dd.plot_sort('geo_loc_name_s',gui='qt5')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "anaconda-cloud": {}, - "kernelspec": { - "display_name": "Python [conda env:testcalour]", - "language": "python", - "name": "conda-env-testcalour-py" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.3" - }, - "widgets": { - "state": { - "243cbc18d1284bf3b4dedb9b4c7ead37": { - "views": [ - { - "cell_index": 14 - } - ] - }, - "4299a89f85bc49cd889109bb3eda3a28": { - "views": [ - { - "cell_index": 14 - } - ] - }, - "9ed55c0ab4ce409f8c62e2c7e5efb926": { - "views": [ - { - "cell_index": 14 - } - ] - }, - "a107ec45f74d4c3db936021c91bb091a": { - "views": [ - { - "cell_index": 14 - } - ] - }, - "bb3f7a1dcb884b0d9a2b8e017145fcf3": { - "views": [ - { - "cell_index": 14 - } - ] - }, - "d57925d3612a4350863c53f5cedc0a33": { - "views": [ - { - "cell_index": 14 - } - ] - } - }, - "version": "1.2.0" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/notebooks/Example-marine-sea-urchin.ipynb b/notebooks/Example-marine-sea-urchin.ipynb deleted file mode 100644 index f21a5c8b..00000000 --- a/notebooks/Example-marine-sea-urchin.ipynb +++ /dev/null @@ -1,1169 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# load calour" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import calour as ca\n", - "% matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "we want to get info messages (10 is debug, 20 is info, 30 is warning)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "ca.set_log_level(20)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Load the dataset\n", - "## data is from: \n", - "**The gut microbiome of the sea urchin, Lytechinus variegatus, from its natural habitat demonstrates selective attributes of microbial taxa and predictive metabolic profiles**\n", - "\n", - "*Joseph A. Hakim Hyunmin Koo Ranjit Kumar Elliot J. Lefkowitz Casey D. Morrow Mickie L. Powell Stephen A. Watts Asim K. Bej*\n", - "\n", - "*FEMS Microbiol Ecol (2016) 92 (9)*\n", - "\n", - "It is an amplicon experiment, so we use `load_amplicon`. This gives us some more amplicon experiment specific functions and defaults (i.e. plotting by taxonomy, etc.)\n", - "\n", - "We load the biom table and mapping file.\n", - "\n", - "Specify normalization depth to 10000 reads/sample\n", - "\n", - "And filter away samples with < 1000 reads\n", - "\n", - "By default the data is loaded as sparse scipy matrix. Can use dense instead by setting `sparse=False`" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-03-12 23:13:43 INFO loaded 18 samples, 16909 observations\n", - "2017-03-12 23:13:43 INFO 15 remaining\n" - ] - } - ], - "source": [ - "exp = ca.read_amplicon('data/sea-urchin.biom', 'data/sea-urchin.sample.txt', normalize=10000, filter_reads=1000)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "AmpliconExperiment sea-urchin.biom with 15 samples, 16909 features" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## An Experiment (which AmpliconExperiment is a subclass) contains 3 basic attributes:\n", - "- data : an S (number samples) x F (number features) 2d numpy array or scipy.Sparse matrix\n", - "- sample_metadata : pandas.DataFrame. Stores all the per-sample information. Index is the SampleID\n", - "- feature_metadata : pandas.DataFrame. Stores all the per-feature information. For AmpliconExperiment, index is the sequence\n", - "\n", - "Data, sample_metadata and feature_metadata are synchronized, so position (s,f) in the data matrix corresponds to position s in the sample_metadata and position f in the feature_metadata" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Index(['#SampleID', 'BioSample_s', 'Experiment_s', 'MBases_l', 'MBytes_l',\n", - " 'Run_s', 'SRA_Sample_s', 'Sample_Name_s', 'isolation_source_s', 'type',\n", - " 'Assay_Type_s', 'AssemblyName_s', 'BioProject_s', 'BioSampleModel_s',\n", - " 'Center_Name_s', 'Consent_s', 'InsertSize_l', 'LibraryLayout_s',\n", - " 'LibrarySelection_s', 'LibrarySource_s', 'Library_Name_s', 'LoadDate_s',\n", - " 'Organism_s', 'Platform_s', 'ReleaseDate_s', 'SRA_Study_s',\n", - " 'collection_date_s', 'cultured_location_s', 'g1k_analysis_group_s',\n", - " 'g1k_pop_code_s', 'geo_loc_name_s', 'host_s', 'lat_lon_s', 'source_s',\n", - " '_calour_original_abundance'],\n", - " dtype='object')" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp.sample_metadata.columns" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Analysis" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Cluster the features (bacteria)\n", - "So similar behaving features will be close to each other.\n", - "\n", - "We also specify `min_abundance=10` to filter away features with less than 10 (normalized) reads total over all samples.\n", - "\n", - "This makes clustering and analysis faster, as well as adding more power (as the < 10 reads total features don't contain a lot of information)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-03-12 23:13:52 INFO 759 remaining\n" - ] - } - ], - "source": [ - "exp_c = exp.cluster_features(min_abundance=10)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "AmpliconExperiment sea-urchin.biom with 15 samples, 759 features" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp_c" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## let's look at the data\n", - "We will use two databases:\n", - "'sponge' - the sponge-EMP automatic database\n", - "'dbbact' - the manual annotation database" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": { - "collapsed": 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" - } - ], - "source": [ - "explore('M3')" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": 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" - } - ], - "source": [ - "def explore2(host, site=None):\n", - " exp = mov.filter_samples('HOST_SUBJECT_ID', host)\n", - " if site is not None:\n", - " exp.filter_samples('BODY_SITE', site, inplace=True)\n", - " exp.filter_min_abundance(10, inplace=True)\n", - " exp.sort_samples('DAYS_SINCE_EXPERIMENT_START', inplace=True)\n", - " exp.sort_samples('BODY_SITE', inplace=True)\n", - " exp.sort_center_mass(inplace=True)\n", - " exp.plot(gui='jupyter', sample_color_bars=['HOST_SUBJECT_ID', 'BODY_SITE'])\n", - "explore2('M3', 'UBERON:feces')" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": { - "collapsed": 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" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "106c92d728c6489a931a5b222f8dcb15" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "cd1f117e456140119dc12f2e4406ac0e" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "cfab9922a75948e5b01e7a03e8bb6ead" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7a4bc326b1f5499f88b34c32d9528c74" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8717907fd9c641d6993991f0a5d49900" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d16939591c87434bbd2c534129dd6867" + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f = tt.plot_sort('BODY_PRODUCT',gui='jupyter',sample_color_bars=['HOST_SUBJECT_ID'], clim=[0, 1000])" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": true, + "run_control": { + "frozen": false, + "read_only": false + } + }, + "outputs": [], + "source": [ + "# you can save figures\n", + "f.save_figure('fig.pdf')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "run_control": { + "frozen": false, + "read_only": false + } + }, + "source": [ + "## Sort bacteria by the taxonomy (just because we can :D)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "run_control": { + "frozen": false, + "read_only": 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" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "09e170713fe74d4ab41ad70e6a07a348" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "9723bafc89ce483396d80b0a717046b4" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "47c5f1a82f414b3494d5e8bb93361106" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c110fca44ba9413fb6c3d6e6c673499b" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0a17e6b380074e12860f860d1a7e3629" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8f8f6cd79e4c49aeabaddba6a0377841" + } + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "f=ttt.plot_sort('BODY_PRODUCT',gui='jupyter',sample_color_bars=['HOST_SUBJECT_ID','COMMON_SAMPLE_SITE'],\n", + " feature_field=None, xticklabel_rot=None, xticklabel_len=None, clim=[0,1000])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "run_control": { + "frozen": false, + "read_only": false + } + }, + "source": [ + "This is the same plot but focused on a specific region that is interesting:" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "run_control": { + "frozen": false, + "read_only": 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" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5c41cec9ee75468390456034c9f0c389" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "4375c505b59d4e82ad67b9622bbd915f" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "0d6f26ac18dd426bb108b6b2743e0b16" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7e12a1e226cd4e5ab55e7489f3493610" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7eb94d965c994744b13092f793d52e6c" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6100332d8d1b44b2ab464f42f29fe92b" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dd.plot(feature_field=None, gui='jupyter')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "run_control": { + "frozen": false, + "read_only": false + } + }, + "source": [ + "## We can also sort by the center of mass" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "run_control": { + "frozen": false, + "read_only": false + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2017-09-13 19:26:44 INFO 76 remaining\n" + ] + } + ], + "source": [ + "ttt=tt.filter_prevalence(0.3)" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": true, + "run_control": { + "frozen": false, + "read_only": false + } + }, + "outputs": [], + "source": [ + "ttt=ttt.sort_centroid()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "run_control": { + "frozen": false, + "read_only": false + } + }, + "outputs": [ + { + "data": { + "text/plain": [ + "M3 336\n", + "Name: HOST_SUBJECT_ID, dtype: int64" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ttt.sample_metadata.HOST_SUBJECT_ID.value_counts()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "run_control": { + "frozen": false, + "read_only": 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" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "a911bb336b5c4b448eeb4e952a4553e7" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "c489cc58cbd645c69c0808c7286d661d" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "8c5cd7d1f5934c9a89d8995f57455171" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f34844db740e4f85af3bedf407de515e" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d1d0b85b71ce42a8a09181a17ddf4f68" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fa5dec6b2f9144438da99fa42e2f7172" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tt.plot(sample_field='HOST_SUBJECT_ID', feature_field=None, gui='jupyter')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "run_control": { + "frozen": false, + "read_only": false + } + }, + "source": [ + "## we can find the sOTUs that are different between left and right hands" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": { + "run_control": { + "frozen": false, + "read_only": false + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2017-09-13 19:26:47 INFO 2 remaining\n", + "2017-09-13 19:26:47 INFO ignoring 2 features\n", + "2017-09-13 19:26:47 INFO 5247 remaining\n", + "2017-09-13 19:26:47 INFO 365 samples with value 1 (['L_palm'])\n", + "2017-09-13 19:26:51 INFO method meandiff. number of higher in ['L_palm'] : 3. number of higher in None : 870. total 873\n" + ] + }, + { + "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/vnd.jupyter.widget-view+json": { + "model_id": "505689774f8642898bf3a766de5bace1" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "99f6bf0320f24185b093b980f391476c" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "2673f57d6af5447abf47b6dc1c98df9b" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "d71ba432afa24e2496694fd19fd846ca" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "fd58bdc5dc0847d1a63d5d61a7269d5f" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "93b20678e89541758295300f7312d2d6" + } + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m3s=hand.filter_samples('HOST_SUBJECT_ID','F4')\n", + "\n", + "m3s=m3s.sort_samples('DAYS_SINCE_EPOCH')\n", + "\n", + "dd=m3s.diff_abundance('COMMON_SAMPLE_SITE','L_palm')\n", + "\n", + "dd.plot_sort('COMMON_SAMPLE_SITE',gui='jupyter')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "run_control": { + "frozen": false, + "read_only": false + } + }, + "source": [ + "## Conclusions\n", + "\n", + "* We can identify the taxa that colonize and persist, the ones that disappear forever in the middle of the period, and the ones that stochastically come and go, which is also reported in the original paper.\n", + "* In addition, with convenient exploration of the data in heatmap, we find a set of sOTUs appear together in a group. This set is enriched with skin bacteria. We can hypothesize that this set is likely from skin and is a result of sample collecting protocol." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + }, + "toc": { + "colors": { + "hover_highlight": "#DAA520", + "running_highlight": "#FF0000", + "selected_highlight": "#FFD700" + }, + "moveMenuLeft": true, + "nav_menu": { + "height": "497px", + "width": "251px" + }, + "navigate_menu": true, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "threshold": 4, + "toc_cell": false, + "toc_position": { + "height": "742px", + "left": "0px", + "right": "1900px", + "top": "107px", + "width": "212px" + }, + "toc_section_display": "block", + "toc_window_display": true, + "widenNotebook": false + }, + "widgets": { + "state": { + "03b515dd8e074d2fba2ce5d888abba78": { + "views": [ + { + "cell_index": 57 + } + ] + }, + "1499d11dea4e4e759f5e17d7bb2cb53a": { + "views": [ + { + "cell_index": 39 + } + ] + }, + "18e728483c524d5e9f87e5ccb399ea30": { + "views": [ + { + "cell_index": 46 + } + ] + }, + "23eabe972f9b4de1984a06056477f250": { + "views": [ + { + "cell_index": 51 + } + ] + }, + "40036d64343341a7badacd7378a373b2": { + "views": [ + { + "cell_index": 33 + } + ] + }, + "487ce0c6c22c4c95aa3f7909a8b9ecd7": { + "views": [ + { + "cell_index": 55 + } + ] + }, + "4f6143458fc04da0873a8419a6a82c48": { + "views": [ + { + "cell_index": 36 + } + ] + }, + "4fb731afd9e74c819095387eec39c188": { + "views": [ + { + "cell_index": 33 + } + ] + }, + "5731850935144a0788a1f40148d5fe3d": { + "views": [ + { + "cell_index": 31 + } + ] + }, + "60a663d13e734f088f80cbd7121f0a85": { + "views": [ + { + "cell_index": 31 + } + ] + }, + "70a89313a2dc4ea8ae21a67ba9183c36": { + "views": [ + { + "cell_index": 55 + } + ] + }, + "758f9bb4798e4c50a0b0f6d25b8322d0": { + "views": [ + { + "cell_index": 57 + } + ] + }, + "85bdac9d6132458a8db07680530b9f1d": { + "views": [ + { + "cell_index": 58 + } + ] + }, + "8f1fc42d52134687922e20b79af09a92": { + "views": [ + { + "cell_index": 51 + } + ] + }, + "cbf01fd6ea7b459a8a07ef40b7fcaf15": { + "views": [ + { + "cell_index": 39 + } + ] + }, + "cde762fa894f47bca37af4132089a60b": { + "views": [ + { + "cell_index": 33 + } + ] + }, + "d35675efc311473182cb6d566dc05d2d": { + "views": [ + { + "cell_index": 58 + } + ] + }, + "d82ba87d9c1f4bb1929ceaf0e42bc1f4": { + "views": [ + { + "cell_index": 46 + } + ] + }, + "dca2c613bb5f4a77b76beabdba7444a5": { + "views": [ + { + "cell_index": 36 + } + ] + } + }, + "version": "1.2.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/moving_picture/figure-M3-fecal-sort-centroid.pdf b/notebooks/moving_picture/figure-M3-fecal-sort-centroid.pdf deleted file mode 100644 index 6f21442d..00000000 Binary files a/notebooks/moving_picture/figure-M3-fecal-sort-centroid.pdf and /dev/null differ diff --git a/notebooks/moving_picture/figure-all-clustered-zoom-sporadic.pdf b/notebooks/moving_picture/figure-all-clustered-zoom-sporadic.pdf deleted file mode 100644 index 3f1c08b8..00000000 Binary files a/notebooks/moving_picture/figure-all-clustered-zoom-sporadic.pdf and /dev/null differ diff --git a/notebooks/moving_picture/figure-all-clustered.pdf b/notebooks/moving_picture/figure-all-clustered.pdf deleted file mode 100644 index 701372c0..00000000 Binary files a/notebooks/moving_picture/figure-all-clustered.pdf and /dev/null differ diff --git a/notebooks/moving_picture/moving_pic.biom b/notebooks/moving_picture/moving_pic.biom deleted file mode 100644 index f40e9513..00000000 Binary files a/notebooks/moving_picture/moving_pic.biom and /dev/null differ diff --git a/notebooks/moving_picture/moving_pic.html b/notebooks/moving_picture/moving_pic.html deleted file mode 100644 index 987200cd..00000000 --- a/notebooks/moving_picture/moving_pic.html +++ /dev/null @@ -1,20568 +0,0 @@ - - - -moving_pic - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-
-

Setup

import calour

-
-
-
-
-
-
In [1]:
-
-
-
import calour as ca
-
- -
-
-
- -
-
-
-
-
-
-

let's set to print messages of INFO level from Calour

Calour uses Python's builtin logging module to print out logging messages. By default the logging level is set to WARNING. Let's change it to INFO for the purpose of this tutorial, so we get more detailed information about the function outputs.

- -
-
-
-
-
-
In [2]:
-
-
-
ca.set_log_level('INFO')
-
- -
-
-
- -
-
-
-
-
-
-

and we want interactive plots inside the notebook

-
-
-
-
-
-
In [3]:
-
-
-
%matplotlib notebook
-
- -
-
-
- -
-
-
-
-
-
-

Moving picture data set

This data set is from: -Caporaso JG, Lauber CL, Costello EK, Berg-Lyons D, Gonzalez A, Stombaugh J, Knights D, Gajer P, Ravel J, Fierer N, et al. (2011) Moving pictures of the human microbiome. Genome Biology, 12, R50.

-

The raw data are reproccessed with deblur method, which is published in mSystem

-

Load the data

We use read_amplicon to read the data into AmpliconExperiment class. This class has some amplicon experiment specific functions such as filter_taxonomy etc.

-

Useful parameters are:

-
    -
  • biom table name
  • -
  • mapping file name (can be None if no sample metadata available)
  • -
  • filter_reads - the minimal number of reads per sample in order to keep it
  • -
  • normalize - the depth to normalize each sample to (note it is not rarefaction butn normalization to constant sum)
  • -
- -
-
-
-
-
-
In [4]:
-
-
-
exp = ca.read_amplicon(data_file='./moving_pic.biom', sample_metadata_file='./moving_pic.sample.txt', filter_reads=1000, normalize=10000)
-
- -
-
-
- -
-
- - -
-
-
2017-05-09 19:20:21 INFO loaded 1968 samples, 7056 observations
-2017-05-09 19:20:21 INFO 1967 remaining
-
-
-
- -
-
- -
-
-
-
In [5]:
-
-
-
exp
-
- -
-
-
- -
-
- - -
Out[5]:
- - -
-
AmpliconExperiment moving_pic.biom with 1967 samples, 7056 features
-
- -
- -
-
- -
-
-
-
-
-
-

each Experiment has the following attributes:

data : a data sparse (or dense) 2D array

This stores the abundance information. Each row is a sample, each column a feature (i.e. OTU, gene, metabolites, etc)

- -
-
-
-
-
-
In [6]:
-
-
-
exp.data
-
- -
-
-
- -
-
- - -
Out[6]:
- - -
-
<1967x7056 sparse matrix of type '<class 'numpy.float64'>'
-	with 130081 stored elements in Compressed Sparse Row format>
-
- -
- -
-
- -
-
-
-
-
-
-

sample_metadata : a pandas dataframe with one row per sample

index is the SampleID (first column in the mapping file), matching the biom table sampleIDs

- -
-
-
-
-
-
In [7]:
-
-
-
exp.sample_metadata.head(5)
-
- -
-
-
- -
-
- - -
Out[7]:
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#SampleIDBarcodeSequenceLinkerPrimerSequenceDAYS_SINCE_EPOCHTARGET_SUBFRAGMENTASSIGNED_FROM_GEOEXPERIMENT_CENTERTITLECOMMON_SAMPLE_SITERUN_PREFIX...KEY_SEQBODY_PRODUCTAGE_IN_YEARSRUN_CENTERLIBRARY_CONSTRUCTION_PROTOCOLLATITUDEREGIONHOST_INDIVIDUALDescription_calour_original_abundance
#SampleID
L2S137.273277L2S137.273277AATCAGTCTCGTGTGCCAGCMGCCGCGGTAA14223V4nCCMEMoving_pictures_of_the_human_microbiomeL_palms_2_sequence...noneUBERON:zone of skin of handNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L2F4illumina_time_series10000.0
L3S167.273782L3S167.273782TACTTCGCTCGCGTGCCAGCMGCCGCGGTAA14526V4nCCMEMoving_pictures_of_the_human_microbiomeL_palms_3_sequence...noneUBERON:zone of skin of handNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L3M3illumina_time_series10000.0
L4S102.275028L4S102.275028GCAATAGCTGCTGTGCCAGCMGCCGCGGTAA14310V4nCCMEMoving_pictures_of_the_human_microbiomeR_palms_4_sequence...noneUBERON:zone of skin of handNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L4M3illumina_time_series10000.0
L6S243.274842L6S243.274842ACGAGTGCTATCGTGCCAGCMGCCGCGGTAA14507V4nCCMEMoving_pictures_of_the_human_microbiomeTongues_6_sequence...noneUBERON:tongueNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L6M3illumina_time_series10000.0
L3S240.274358L3S240.274358AGTACGCTCGAGGTGCCAGCMGCCGCGGTAA14178V4nCCMEMoving_pictures_of_the_human_microbiomeR_palms_3_sequence...noneUBERON:zone of skin of handNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L3F4illumina_time_series10000.0
-

5 rows × 49 columns

-
-
- -
- -
-
- -
-
-
-
-
-
-

feature_metadata : a pandas dataframe with one row per feature (i.e. sOTU)

For deblurred data set, index is the actual sequence, matching the biom table

-

Additional properties are loaded from biom table observation metadata (i.e. taxonomy)

- -
-
-
-
-
-
In [8]:
-
-
-
exp.feature_metadata.head(5)
-
- -
-
-
- -
-
- - -
Out[8]:
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
idtaxonomy
TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTGCTTAGGCGGCAAATTAAGTTAGTGGTTAAATAGTTCGGCTCAACCGGATTTCGCCATTAAAACTGATATGCTAGAGATTAAACGAGGTAGGCGGAATAAGTTATACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTG...k__Bacteria;p__Bacteroidetes;c__Bacteroidia;o_...
TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTGCGTAGGCTGTTTCGTAAGTCGTGTGTGAAAGGTGCGGGCTCAACCCGCGGACGGCACATGATACTGCGAGACTAGAGTAATGGAGGGGGAACCGGAATTCTCGTACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTG...k__Bacteria;p__Verrucomicrobia;c__Verrucomicro...
TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCTCGTAGGCGGTTTGTTGCGTCGGGAGTGAAAACTCAGGGCTTAACCCTGAGCCTGCTTCCGATACGGGCAGACTAGAGGTATGCAGGGGAGAACGGAATTCCTGTACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCT...k__Bacteria;p__Actinobacteria;c__Actinobacteri...
TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAGTGTAGGTGGCCATGCAAGTCAGAAGTGAAAATCCGGGGCTCAACCCCGGAACTGCTTTTGAAACTGCAGGGCTAGAGTGCAGGAGGGGCAAGTGGAATTCCTATACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAG...k__Bacteria;p__Firmicutes;c__Clostridia;o__Clo...
TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAGCGTAGGCGGCTGATTAAGTCAGCGGTGAAAGGTAGCAGCTTAACTGTTTTACATGCCGTTGATACTGGTTAGCTTGAGTTGACAGAAGGCAGATAGAATTCCTTACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAG...k__Bacteria;p__Bacteroidetes;c__Cytophagia;o__...
-
-
- -
- -
-
- -
-
-
-
-
-
-

Sort the samples

sort by the time field, COMMON_SAMPLE_SITE (to get separation between left/right hand), and subject id

- -
-
-
-
-
-
In [9]:
-
-
-
exp.sample_metadata.COMMON_SAMPLE_SITE.value_counts()
-
- -
-
-
- -
-
- - -
Out[9]:
- - -
-
Tongue    508
-L_palm    499
-R_palm    493
-feces     467
-Name: COMMON_SAMPLE_SITE, dtype: int64
-
- -
- -
-
- -
-
-
-
In [10]:
-
-
-
exp=exp.sort_samples('DAYS_SINCE_EXPERIMENT_START').sort_samples('COMMON_SAMPLE_SITE').sort_samples('HOST_SUBJECT_ID')
-
- -
-
-
- -
-
-
-
In [11]:
-
-
-
exp.feature_metadata.head()
-
- -
-
-
- -
-
- - -
Out[11]:
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
idtaxonomy
TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTGCTTAGGCGGCAAATTAAGTTAGTGGTTAAATAGTTCGGCTCAACCGGATTTCGCCATTAAAACTGATATGCTAGAGATTAAACGAGGTAGGCGGAATAAGTTATACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTG...k__Bacteria;p__Bacteroidetes;c__Bacteroidia;o_...
TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTGCGTAGGCTGTTTCGTAAGTCGTGTGTGAAAGGTGCGGGCTCAACCCGCGGACGGCACATGATACTGCGAGACTAGAGTAATGGAGGGGGAACCGGAATTCTCGTACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTG...k__Bacteria;p__Verrucomicrobia;c__Verrucomicro...
TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCTCGTAGGCGGTTTGTTGCGTCGGGAGTGAAAACTCAGGGCTTAACCCTGAGCCTGCTTCCGATACGGGCAGACTAGAGGTATGCAGGGGAGAACGGAATTCCTGTACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCT...k__Bacteria;p__Actinobacteria;c__Actinobacteri...
TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAGTGTAGGTGGCCATGCAAGTCAGAAGTGAAAATCCGGGGCTCAACCCCGGAACTGCTTTTGAAACTGCAGGGCTAGAGTGCAGGAGGGGCAAGTGGAATTCCTATACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAG...k__Bacteria;p__Firmicutes;c__Clostridia;o__Clo...
TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAGCGTAGGCGGCTGATTAAGTCAGCGGTGAAAGGTAGCAGCTTAACTGTTTTACATGCCGTTGATACTGGTTAGCTTGAGTTGACAGAAGGCAGATAGAATTCCTTACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAG...k__Bacteria;p__Bacteroidetes;c__Cytophagia;o__...
-
-
- -
- -
-
- -
-
-
-
-
-
-

divide to per sample-type experiments

-
-
-
-
-
-
In [12]:
-
-
-
exp.sample_metadata['BODY_PRODUCT'].value_counts()
-
- -
-
-
- -
-
- - -
Out[12]:
- - -
-
UBERON:zone of skin of hand    992
-UBERON:tongue                  508
-UBERON:feces                   467
-Name: BODY_PRODUCT, dtype: int64
-
- -
- -
-
- -
-
-
-
-
-
-

let's split the dataset:

- -
-
-
-
-
-
In [13]:
-
-
-
feces = exp.filter_samples('BODY_PRODUCT', 'UBERON:feces')
-tongue = exp.filter_samples('BODY_PRODUCT', 'UBERON:tongue')
-# just to have fun, let's negate and use multiple values
-hand = exp.filter_samples('BODY_PRODUCT', ['UBERON:feces', 'UBERON:tongue'], negate=True )
-
- -
-
-
- -
-
-
-
-
-
-

NOTE: The data array and sample and feature metadata are always synchronized to the same order for all the manipulations (filtering, sorting, transforming, etc.) done on Experiment object.

- -
-
-
-
-
-
In [14]:
-
-
-
feces
-
- -
-
-
- -
-
- - -
Out[14]:
- - -
-
AmpliconExperiment moving_pic.biom with 467 samples, 7056 features
-
- -
- -
-
- -
-
-
-
In [15]:
-
-
-
tongue
-
- -
-
-
- -
-
- - -
Out[15]:
- - -
-
AmpliconExperiment moving_pic.biom with 508 samples, 7056 features
-
- -
- -
-
- -
-
-
-
In [16]:
-
-
-
hand
-
- -
-
-
- -
-
- - -
Out[16]:
- - -
-
AmpliconExperiment moving_pic.biom with 992 samples, 7056 features
-
- -
- -
-
- -
-
-
-
-
-
-

Note that filtering samples does not change or get rid of features not present in the set of samples.

- -
-
-
-
-
-
-
-
-

get rid of features with <50 reads total over all samples

(Where we have 10000 reads/sample after normalization in the load)

- -
-
-
-
-
-
In [17]:
-
-
-
tt=exp.filter_min_abundance(50)
-
- -
-
-
- -
-
- - -
-
-
2017-05-09 19:20:31 INFO 2512 remaining
-
-
-
- -
-
- -
-
-
-
-
-
-

And plot the data naively

We plot by sorting samples according to body site, with sample color bars for the subject id.

-

We use the plot_sort function which does a sort on a (set) of fields on the fly and then plots. -We can specify the type of interactive heatmap using the gui with following options:

-
    -
  • 'jupyter' plots an interactive plot inside the notebook
  • -
  • 'qt5' opens the plot in an interactive qt5 window
  • -
  • None just creates the static matplotlib figure
  • -
- -
-
-
-
-
-
In [18]:
-
-
-
tt.plot_sort('BODY_PRODUCT',gui='jupyter',sample_color_bars=['HOST_SUBJECT_ID'])
-
- -
-
-
- -
-
- - -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
Out[18]:
- - -
-
<calour.heatmap.plotgui_jupyter.PlotGUI_Jupyter at 0x1137a1ac8>
-
- -
- -
-
- -
-
-
-
-
-
-

Sort bacteria by the taxonomy (just because we can :D)

-
-
-
-
-
-
In [19]:
-
-
-
zz=tt.sort_taxonomy()
-zz.plot_sort('BODY_PRODUCT',gui='jupyter',sample_color_bars=['HOST_SUBJECT_ID'])
-
- -
-
-
- -
-
- - -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
Out[19]:
- - -
-
<calour.heatmap.plotgui_jupyter.PlotGUI_Jupyter at 0x113386e48>
-
- -
- -
-
- -
-
-
-
-
-
-

Sort bacteria by clustering

So similar behaving bacteria will be close to each other -We also remove bacteria with < 50 reads total, so the heatmap will be of the more interesting bacteria.

- -
-
-
-
-
-
In [20]:
-
-
-
ttt=tt.cluster_features()
-
- -
-
-
- -
-
- - -
-
-
2017-05-09 19:20:54 INFO 2512 remaining
-
-
-
- -
-
- -
-
-
-
In [22]:
-
-
-
f=ttt.plot_sort('BODY_PRODUCT',gui='jupyter',sample_color_bars=['HOST_SUBJECT_ID','COMMON_SAMPLE_SITE'],
-                feature_field=None, xticklabel_rot=None, xticklabel_len=None, show_legend=True,
-                clim=[0,10])
-
- -
-
-
- -
-
- - -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
-
- -
-
-
-
In [30]:
-
-
-
f.save_figure('figure-all-clustered.pdf')
-
- -
-
-
- -
-
-
-
-
-
-

This is the same plot but focused on a specific region that is interesting:

- -
-
-
-
-
-
In [23]:
-
-
-
f=ttt.plot_sort('BODY_PRODUCT',gui='jupyter',sample_color_bars=['HOST_SUBJECT_ID','COMMON_SAMPLE_SITE'],
-                rect=[-0.5, 1966.5, 2511.5, 2354.5],
-                clim=[0,10], feature_field=None)
-
- -
-
-
- -
-
- - -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
-
- -
-
-
-
-
-
-

We can see there is a set of sOTUs showing up in together in the individual of "M3" sporadically (near the bottom of the heatmap above). This behavior is difficult to see in a naive heatmap without clustering and sorting the features.

- -
-
-
-
-
-
In [24]:
-
-
-
f.save_figure('figure-all-clustered-zoom-sporadic.pdf')
-
- -
-
-
- -
-
-
-
-
-
-

find features correlated with time in the individule of "M3"

-
-
-
-
-
-
In [25]:
-
-
-
tt = feces.filter_samples('HOST_SUBJECT_ID','M3')
-tt=tt.cluster_features(50)
-
- -
-
-
- -
-
- - -
-
-
2017-05-09 19:24:42 INFO 493 remaining
-
-
-
- -
-
- -
-
-
-
In [26]:
-
-
-
dd = tt.correlation('DAYS_SINCE_EXPERIMENT_START')
-
- -
-
-
- -
-
- - -
-
-
2017-05-09 19:24:43 INFO 493 remaining
-2017-05-09 19:24:43 INFO method spearman for field DAYS_SINCE_EXPERIMENT_START. Positive correlated features : 60. Negative correlated features : 191. total 251
-
-
-
- -
-
- -
-
-
-
-
-
-

We get 259 features with significant correlation following FDR control.

-

Note features are sorted by the effect size (biggest/smallest correlation is top/bottom)

- -
-
-
-
-
-
In [27]:
-
-
-
dd.plot(feature_field=None, gui='jupyter')
-
- -
-
-
- -
-
- - -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
Out[27]:
- - -
-
<calour.heatmap.plotgui_jupyter.PlotGUI_Jupyter at 0x1254bc1d0>
-
- -
- -
-
- -
-
-
-
-
-
-

We can also sort by the center of mass

-
-
-
-
-
-
In [28]:
-
-
-
ttt=tt.filter_prevalence(0.3)
-
- -
-
-
- -
-
- - -
-
-
2017-05-09 19:25:03 INFO 76 remaining
-
-
-
- -
-
- -
-
-
-
In [29]:
-
-
-
ttt=ttt.sort_centroid()
-
- -
-
-
- -
-
-
-
In [30]:
-
-
-
ttt.sample_metadata.HOST_SUBJECT_ID.value_counts()
-
- -
-
-
- -
-
- - -
Out[30]:
- - -
-
M3    336
-Name: HOST_SUBJECT_ID, dtype: int64
-
- -
- -
-
- -
-
-
-
In [31]:
-
-
-
f=ttt.plot(gui='jupyter',feature_field=None, clim=[0,10])
-
- -
-
-
- -
-
- - -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
-
- -
-
-
-
In [33]:
-
-
-
f.save_figure('figure-M3-fecal-sort-centroid.pdf')
-
- -
-
-
- -
-
-
-
-
-
-

Some more analyses

We can sort the features based on abundance in a specific field/value group. For example, let's sort the features by their abundances in the individual "M3" and then look how abundant those bacteria are in the individual "F4":

- -
-
-
-
-
-
In [34]:
-
-
-
tt = feces.sort_abundance({'HOST_SUBJECT_ID': ['M3']})
-
- -
-
-
- -
-
-
-
In [35]:
-
-
-
tt.plot(sample_field='HOST_SUBJECT_ID', feature_field=None, gui='jupyter')
-
- -
-
-
- -
-
- - -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
Out[35]:
- - -
-
<calour.heatmap.plotgui_jupyter.PlotGUI_Jupyter at 0x114320cf8>
-
- -
- -
-
- -
-
-
-
-
-
-

we can find the sOTUs that are different between left and right hands

-
-
-
-
-
-
In [36]:
-
-
-
m3s=hand.filter_samples('HOST_SUBJECT_ID','M3')
-m3s=m3s.normalize_compositional()
-m3s=m3s.sort_samples('DAYS_SINCE_EPOCH')
-
-dd=m3s.diff_abundance('COMMON_SAMPLE_SITE','L_palm')
-
-dd.plot_sort('COMMON_SAMPLE_SITE',gui='jupyter')
-
- -
-
-
- -
-
- - -
-
-
2017-05-09 19:27:03 INFO 2 remaining
-2017-05-09 19:27:03 INFO ignoring 2 features
-2017-05-09 19:27:03 INFO 5247 remaining
-2017-05-09 19:27:04 INFO 365 samples with value 1 (['L_palm'])
-2017-05-09 19:27:07 INFO method meandiff. number of higher in ['L_palm'] : 3. number of higher in None : 930. total 933
-
-
-
- -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
Out[36]:
- - -
-
<calour.heatmap.plotgui_jupyter.PlotGUI_Jupyter at 0x1200d1080>
-
- -
- -
-
- -
-
-
-
In [37]:
-
-
-
m3s=hand.filter_samples('HOST_SUBJECT_ID','F4')
-
-m3s=m3s.sort_samples('DAYS_SINCE_EPOCH')
-
-dd=m3s.diff_abundance('COMMON_SAMPLE_SITE','L_palm')
-
-dd.plot_sort('COMMON_SAMPLE_SITE',gui='jupyter')
-
- -
-
-
- -
-
- - -
-
-
2017-05-09 19:27:08 INFO 1892 remaining
-2017-05-09 19:27:08 INFO 134 samples with value 1 (['L_palm'])
-2017-05-09 19:27:09 INFO method meandiff. number of higher in ['L_palm'] : 204. number of higher in None : 4. total 208
-
-
-
- -
- - - -
-
- -
- -
- -
- -
- -
- -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
- - - -
- -
Out[37]:
- - -
-
<calour.heatmap.plotgui_jupyter.PlotGUI_Jupyter at 0x1225d0160>
-
- -
- -
-
- -
-
-
-
-
-
-

Conclusions

    -
  • We can identify the taxa that colonize and persist, the ones that disappear forever in the middle of the period, and the ones that stochastically come and go, which is also reported in the original paper.
  • -
  • In addition, with convenient exploration of the data in heatmap, we find a set of sOTUs appear together in a group. This set is enriched with skin bacteria. We can hypothesize that this set is likely from skin and is a result of sample collecting protocol.
  • -
- -
-
-
-
-
- - diff --git a/notebooks/moving_picture/moving_pic.ipynb b/notebooks/moving_picture/moving_pic.ipynb deleted file mode 100644 index 48d8432f..00000000 --- a/notebooks/moving_picture/moving_pic.ipynb +++ /dev/null @@ -1,12580 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Setup\n", - "## import calour" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "import calour as ca" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## let's set to print messages of INFO level from Calour\n", - "Calour uses Python's builtin [`logging` module](https://docs.python.org/3.5/library/logging.html#levels) to print out logging messages. By default the logging level is set to `WARNING`. Let's change it to `INFO` for the purpose of this tutorial, so we get more detailed information about the function outputs." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "ca.set_log_level('INFO')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## and we want interactive plots inside the notebook" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "%matplotlib notebook" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Moving picture data set\n", - "\n", - "This data set is from:\n", - "Caporaso JG, Lauber CL, Costello EK, Berg-Lyons D, Gonzalez A, Stombaugh J, Knights D, Gajer P, Ravel J, Fierer N, et al. (2011) Moving pictures of the human microbiome. Genome Biology, 12, R50.\n", - "\n", - "The raw data are reproccessed with [deblur method](https://github.com/biocore/deblur), which is published in [mSystem](http://msystems.asm.org/content/2/2/e00191-16)\n", - "\n", - "## Load the data\n", - "\n", - "We use __`read_amplicon`__ to read the data into __`AmpliconExperiment`__ class. This class has some amplicon experiment specific functions such as `filter_taxonomy` etc.\n", - "\n", - "Useful parameters are:\n", - "- biom table name\n", - "- mapping file name (can be None if no sample metadata available)\n", - "- filter_reads - the minimal number of reads per sample in order to keep it\n", - "- normalize - the depth to normalize each sample to (note it is not rarefaction butn normalization to constant sum)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-05-09 19:20:21 INFO loaded 1968 samples, 7056 observations\n", - "2017-05-09 19:20:21 INFO 1967 remaining\n" - ] - } - ], - "source": [ - "exp = ca.read_amplicon(data_file='./moving_pic.biom', sample_metadata_file='./moving_pic.sample.txt', filter_reads=1000, normalize=10000)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "AmpliconExperiment moving_pic.biom with 1967 samples, 7056 features" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## each `Experiment` has the following attributes:\n", - "### `data` : a data sparse (or dense) 2D array\n", - "\n", - "This stores the abundance information. Each row is a sample, each column a feature (i.e. OTU, gene, metabolites, etc)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "<1967x7056 sparse matrix of type ''\n", - "\twith 130081 stored elements in Compressed Sparse Row format>" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp.data" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### `sample_metadata` : a pandas dataframe with one row per sample\n", - "index is the SampleID (first column in the mapping file), matching the biom table sampleIDs" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
#SampleIDBarcodeSequenceLinkerPrimerSequenceDAYS_SINCE_EPOCHTARGET_SUBFRAGMENTASSIGNED_FROM_GEOEXPERIMENT_CENTERTITLECOMMON_SAMPLE_SITERUN_PREFIX...KEY_SEQBODY_PRODUCTAGE_IN_YEARSRUN_CENTERLIBRARY_CONSTRUCTION_PROTOCOLLATITUDEREGIONHOST_INDIVIDUALDescription_calour_original_abundance
#SampleID
L2S137.273277L2S137.273277AATCAGTCTCGTGTGCCAGCMGCCGCGGTAA14223V4nCCMEMoving_pictures_of_the_human_microbiomeL_palms_2_sequence...noneUBERON:zone of skin of handNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L2F4illumina_time_series10000.0
L3S167.273782L3S167.273782TACTTCGCTCGCGTGCCAGCMGCCGCGGTAA14526V4nCCMEMoving_pictures_of_the_human_microbiomeL_palms_3_sequence...noneUBERON:zone of skin of handNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L3M3illumina_time_series10000.0
L4S102.275028L4S102.275028GCAATAGCTGCTGTGCCAGCMGCCGCGGTAA14310V4nCCMEMoving_pictures_of_the_human_microbiomeR_palms_4_sequence...noneUBERON:zone of skin of handNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L4M3illumina_time_series10000.0
L6S243.274842L6S243.274842ACGAGTGCTATCGTGCCAGCMGCCGCGGTAA14507V4nCCMEMoving_pictures_of_the_human_microbiomeTongues_6_sequence...noneUBERON:tongueNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L6M3illumina_time_series10000.0
L3S240.274358L3S240.274358AGTACGCTCGAGGTGCCAGCMGCCGCGGTAA14178V4nCCMEMoving_pictures_of_the_human_microbiomeR_palms_3_sequence...noneUBERON:zone of skin of handNoneCGS-GLFive primers, two for PCR and three for sequen...40.014986L3F4illumina_time_series10000.0
\n", - "

5 rows × 49 columns

\n", - "
" - ], - "text/plain": [ - " #SampleID BarcodeSequence LinkerPrimerSequence \\\n", - "#SampleID \n", - "L2S137.273277 L2S137.273277 AATCAGTCTCGT GTGCCAGCMGCCGCGGTAA \n", - "L3S167.273782 L3S167.273782 TACTTCGCTCGC GTGCCAGCMGCCGCGGTAA \n", - "L4S102.275028 L4S102.275028 GCAATAGCTGCT GTGCCAGCMGCCGCGGTAA \n", - "L6S243.274842 L6S243.274842 ACGAGTGCTATC GTGCCAGCMGCCGCGGTAA \n", - "L3S240.274358 L3S240.274358 AGTACGCTCGAG GTGCCAGCMGCCGCGGTAA \n", - "\n", - " DAYS_SINCE_EPOCH TARGET_SUBFRAGMENT ASSIGNED_FROM_GEO \\\n", - "#SampleID \n", - "L2S137.273277 14223 V4 n \n", - "L3S167.273782 14526 V4 n \n", - "L4S102.275028 14310 V4 n \n", - "L6S243.274842 14507 V4 n \n", - "L3S240.274358 14178 V4 n \n", - "\n", - " EXPERIMENT_CENTER TITLE \\\n", - "#SampleID \n", - "L2S137.273277 CCME Moving_pictures_of_the_human_microbiome \n", - "L3S167.273782 CCME Moving_pictures_of_the_human_microbiome \n", - "L4S102.275028 CCME Moving_pictures_of_the_human_microbiome \n", - "L6S243.274842 CCME Moving_pictures_of_the_human_microbiome \n", - "L3S240.274358 CCME Moving_pictures_of_the_human_microbiome \n", - "\n", - " COMMON_SAMPLE_SITE RUN_PREFIX ... \\\n", - "#SampleID ... \n", - "L2S137.273277 L_palm s_2_sequence ... \n", - "L3S167.273782 L_palm s_3_sequence ... \n", - "L4S102.275028 R_palm s_4_sequence ... \n", - "L6S243.274842 Tongue s_6_sequence ... \n", - "L3S240.274358 R_palm s_3_sequence ... \n", - "\n", - " KEY_SEQ BODY_PRODUCT AGE_IN_YEARS RUN_CENTER \\\n", - "#SampleID \n", - "L2S137.273277 none UBERON:zone of skin of hand None CGS-GL \n", - "L3S167.273782 none UBERON:zone of skin of hand None CGS-GL \n", - "L4S102.275028 none UBERON:zone of skin of hand None CGS-GL \n", - "L6S243.274842 none UBERON:tongue None CGS-GL \n", - "L3S240.274358 none UBERON:zone of skin of hand None CGS-GL \n", - "\n", - " LIBRARY_CONSTRUCTION_PROTOCOL LATITUDE \\\n", - "#SampleID \n", - "L2S137.273277 Five primers, two for PCR and three for sequen... 40.014986 \n", - "L3S167.273782 Five primers, two for PCR and three for sequen... 40.014986 \n", - "L4S102.275028 Five primers, two for PCR and three for sequen... 40.014986 \n", - "L6S243.274842 Five primers, two for PCR and three for sequen... 40.014986 \n", - "L3S240.274358 Five primers, two for PCR and three for sequen... 40.014986 \n", - "\n", - " REGION HOST_INDIVIDUAL Description \\\n", - "#SampleID \n", - "L2S137.273277 L2 F4 illumina_time_series \n", - "L3S167.273782 L3 M3 illumina_time_series \n", - "L4S102.275028 L4 M3 illumina_time_series \n", - "L6S243.274842 L6 M3 illumina_time_series \n", - "L3S240.274358 L3 F4 illumina_time_series \n", - "\n", - " _calour_original_abundance \n", - "#SampleID \n", - "L2S137.273277 10000.0 \n", - "L3S167.273782 10000.0 \n", - "L4S102.275028 10000.0 \n", - "L6S243.274842 10000.0 \n", - "L3S240.274358 10000.0 \n", - "\n", - "[5 rows x 49 columns]" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp.sample_metadata.head(5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### `feature_metadata` : a pandas dataframe with one row per feature (i.e. sOTU)\n", - "For deblurred data set, index is the actual sequence, matching the biom table\n", - "\n", - "Additional properties are loaded from biom table observation metadata (i.e. taxonomy)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
idtaxonomy
TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTGCTTAGGCGGCAAATTAAGTTAGTGGTTAAATAGTTCGGCTCAACCGGATTTCGCCATTAAAACTGATATGCTAGAGATTAAACGAGGTAGGCGGAATAAGTTATACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTG...k__Bacteria;p__Bacteroidetes;c__Bacteroidia;o_...
TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTGCGTAGGCTGTTTCGTAAGTCGTGTGTGAAAGGTGCGGGCTCAACCCGCGGACGGCACATGATACTGCGAGACTAGAGTAATGGAGGGGGAACCGGAATTCTCGTACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTG...k__Bacteria;p__Verrucomicrobia;c__Verrucomicro...
TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCTCGTAGGCGGTTTGTTGCGTCGGGAGTGAAAACTCAGGGCTTAACCCTGAGCCTGCTTCCGATACGGGCAGACTAGAGGTATGCAGGGGAGAACGGAATTCCTGTACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCT...k__Bacteria;p__Actinobacteria;c__Actinobacteri...
TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAGTGTAGGTGGCCATGCAAGTCAGAAGTGAAAATCCGGGGCTCAACCCCGGAACTGCTTTTGAAACTGCAGGGCTAGAGTGCAGGAGGGGCAAGTGGAATTCCTATACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAG...k__Bacteria;p__Firmicutes;c__Clostridia;o__Clo...
TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAGCGTAGGCGGCTGATTAAGTCAGCGGTGAAAGGTAGCAGCTTAACTGTTTTACATGCCGTTGATACTGGTTAGCTTGAGTTGACAGAAGGCAGATAGAATTCCTTACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAG...k__Bacteria;p__Bacteroidetes;c__Cytophagia;o__...
\n", - "
" - ], - "text/plain": [ - " id \\\n", - "TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTGC... TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTG... \n", - "TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTGC... TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTG... \n", - "TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCTC... TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCT... \n", - "TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAGT... TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAG... \n", - "TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAGC... TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAG... \n", - "\n", - " taxonomy \n", - "TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTGC... k__Bacteria;p__Bacteroidetes;c__Bacteroidia;o_... \n", - "TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTGC... k__Bacteria;p__Verrucomicrobia;c__Verrucomicro... \n", - "TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCTC... k__Bacteria;p__Actinobacteria;c__Actinobacteri... \n", - "TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAGT... k__Bacteria;p__Firmicutes;c__Clostridia;o__Clo... \n", - "TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAGC... k__Bacteria;p__Bacteroidetes;c__Cytophagia;o__... " - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp.feature_metadata.head(5)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Sort the samples \n", - "sort by the time field, COMMON_SAMPLE_SITE (to get separation between left/right hand), and subject id" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Tongue 508\n", - "L_palm 499\n", - "R_palm 493\n", - "feces 467\n", - "Name: COMMON_SAMPLE_SITE, dtype: int64" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp.sample_metadata.COMMON_SAMPLE_SITE.value_counts()" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "exp=exp.sort_samples('DAYS_SINCE_EXPERIMENT_START').sort_samples('COMMON_SAMPLE_SITE').sort_samples('HOST_SUBJECT_ID')" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
idtaxonomy
TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTGCTTAGGCGGCAAATTAAGTTAGTGGTTAAATAGTTCGGCTCAACCGGATTTCGCCATTAAAACTGATATGCTAGAGATTAAACGAGGTAGGCGGAATAAGTTATACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTG...k__Bacteria;p__Bacteroidetes;c__Bacteroidia;o_...
TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTGCGTAGGCTGTTTCGTAAGTCGTGTGTGAAAGGTGCGGGCTCAACCCGCGGACGGCACATGATACTGCGAGACTAGAGTAATGGAGGGGGAACCGGAATTCTCGTACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTG...k__Bacteria;p__Verrucomicrobia;c__Verrucomicro...
TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCTCGTAGGCGGTTTGTTGCGTCGGGAGTGAAAACTCAGGGCTTAACCCTGAGCCTGCTTCCGATACGGGCAGACTAGAGGTATGCAGGGGAGAACGGAATTCCTGTACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCT...k__Bacteria;p__Actinobacteria;c__Actinobacteri...
TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAGTGTAGGTGGCCATGCAAGTCAGAAGTGAAAATCCGGGGCTCAACCCCGGAACTGCTTTTGAAACTGCAGGGCTAGAGTGCAGGAGGGGCAAGTGGAATTCCTATACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAG...k__Bacteria;p__Firmicutes;c__Clostridia;o__Clo...
TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAGCGTAGGCGGCTGATTAAGTCAGCGGTGAAAGGTAGCAGCTTAACTGTTTTACATGCCGTTGATACTGGTTAGCTTGAGTTGACAGAAGGCAGATAGAATTCCTTACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAG...k__Bacteria;p__Bacteroidetes;c__Cytophagia;o__...
\n", - "
" - ], - "text/plain": [ - " id \\\n", - "TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTGC... TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTG... \n", - "TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTGC... TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTG... \n", - "TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCTC... TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCT... \n", - "TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAGT... TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAG... \n", - "TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAGC... TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAG... \n", - "\n", - " taxonomy \n", - "TACGGAGGATCCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGTGC... k__Bacteria;p__Bacteroidetes;c__Bacteroidia;o_... \n", - "TACAGAGGTCTCAAGCGTTGTTCGGAATCACTGGGCGTAAAGCGTGC... k__Bacteria;p__Verrucomicrobia;c__Verrucomicro... \n", - "TACGTAGGGTGCGAGCGTTGTCCGGAATTATTGGGCGTAAAGGGCTC... k__Bacteria;p__Actinobacteria;c__Actinobacteri... \n", - "TACGTATGGAGCAAGCGTTATCCGGATTTACTGGGTGTAAAGGGAGT... k__Bacteria;p__Firmicutes;c__Clostridia;o__Clo... \n", - "TACGTAGGTGGCGAGCGTTATCCGGATTTATTGGGTTTAAAGGGAGC... k__Bacteria;p__Bacteroidetes;c__Cytophagia;o__... " - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp.feature_metadata.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## divide to per sample-type experiments" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "UBERON:zone of skin of hand 992\n", - "UBERON:tongue 508\n", - "UBERON:feces 467\n", - "Name: BODY_PRODUCT, dtype: int64" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "exp.sample_metadata['BODY_PRODUCT'].value_counts()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "let's split the dataset:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "feces = exp.filter_samples('BODY_PRODUCT', 'UBERON:feces')\n", - "tongue = exp.filter_samples('BODY_PRODUCT', 'UBERON:tongue')\n", - "# just to have fun, let's negate and use multiple values\n", - "hand = exp.filter_samples('BODY_PRODUCT', ['UBERON:feces', 'UBERON:tongue'], negate=True )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "__NOTE: The data array and sample and feature metadata are always synchronized to the same order__ for all the manipulations (filtering, sorting, transforming, etc.) done on `Experiment` object." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "AmpliconExperiment moving_pic.biom with 467 samples, 7056 features" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "feces" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "AmpliconExperiment moving_pic.biom with 508 samples, 7056 features" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "tongue" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "AmpliconExperiment moving_pic.biom with 992 samples, 7056 features" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "hand" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Note that filtering samples does not change or get rid of features not present in the set of samples." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## get rid of features with <50 reads total over all samples\n", - "(Where we have 10000 reads/sample after normalization in the load)" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-05-09 19:20:31 INFO 2512 remaining\n" - ] - } - ], - "source": [ - "tt=exp.filter_min_abundance(50)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## And plot the data naively\n", - "We plot by sorting samples according to body site, with sample color bars for the subject id.\n", - "\n", - "We use the `plot_sort` function which does a sort on a (set) of fields on the fly and then plots.\n", - "We can specify the type of interactive heatmap using the `gui` with following options:\n", - "- 'jupyter' plots an interactive plot inside the notebook\n", - "- 'qt5' opens the plot in an interactive qt5 window\n", - "- None just creates the static matplotlib figure" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "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/vnd.jupyter.widget-view+json": { - "model_id": "915a8c618eb14d3d9ed6fa093e425ad8" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "37a063f370aa404cbf53c50a4ba964e9" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "01f8e719cce84303990042cb02cb8fca" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4e203cc6e0b2445288f9fd251fc1db15" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "695c4f605e5c4ad0a1b7b24fd801eb36" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "494f540608e244f9b815b50632bc0895" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "zz=tt.sort_taxonomy()\n", - "zz.plot_sort('BODY_PRODUCT',gui='jupyter',sample_color_bars=['HOST_SUBJECT_ID'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Sort bacteria by clustering\n", - "So similar behaving bacteria will be close to each other\n", - "We also remove bacteria with < 50 reads total, so the heatmap will be of the more interesting bacteria." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-05-09 19:20:54 INFO 2512 remaining\n" - ] - } - ], - "source": [ - "ttt=tt.cluster_features()" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "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/vnd.jupyter.widget-view+json": { - "model_id": "c04bcbc0e87044aeb3c2f6bdafde6913" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "e7888f6605a649a5bd5d801d6014f051" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "760955d1f471436c81d678f9f3c72c2a" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d6619f197db84df9bad710b6784dce6f" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "dcf54030ad5642a4a4def0c1eb6630c6" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "157b19ad03c44485aaaf7f0633603dd6" - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "f=ttt.plot_sort('BODY_PRODUCT',gui='jupyter',sample_color_bars=['HOST_SUBJECT_ID','COMMON_SAMPLE_SITE'],\n", - " rect=[-0.5, 1966.5, 2511.5, 2354.5],\n", - " clim=[0,10], feature_field=None)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "__We can see there is a set of sOTUs showing up in together in the individual of \"M3\" sporadically__ (near the bottom of the heatmap above). This behavior is difficult to see in a naive heatmap without clustering and sorting the features." - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "f.save_figure('figure-all-clustered-zoom-sporadic.pdf')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## find features correlated with time in the individule of \"M3\"" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-05-09 19:24:42 INFO 493 remaining\n" - ] - } - ], - "source": [ - "tt = feces.filter_samples('HOST_SUBJECT_ID','M3')\n", - "tt=tt.cluster_features(50)" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-05-09 19:24:43 INFO 493 remaining\n", - "2017-05-09 19:24:43 INFO method spearman for field DAYS_SINCE_EXPERIMENT_START. Positive correlated features : 60. Negative correlated features : 191. total 251\n" - ] - } - ], - "source": [ - "dd = tt.correlation('DAYS_SINCE_EXPERIMENT_START')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We get 259 features with significant correlation following FDR control.\n", - "\n", - "Note features are sorted by the effect size (biggest/smallest correlation is top/bottom)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": { - "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" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "07dcaf189b654ca394c84cc12c7ad54b" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "996d65f07b444981a83adf7b2d9eaf47" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "cae6be1f849e4f4e913768370ec70f81" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "52922ddd1b2f4024a51d97ef4d16e827" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "e9d1c12ab8514cadb51085c8e37a4fa7" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "51a113a8a2c7419599c43bd38056b4cf" - } - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "f=ttt.plot(gui='jupyter',feature_field=None, clim=[0,10])" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "f.save_figure('figure-M3-fecal-sort-centroid.pdf')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Some more analyses\n", - "We can sort the features based on abundance in a specific field/value group. For example, let's sort the features by their abundances in the individual \"M3\" and then look how abundant those bacteria are in the individual \"F4\":" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "tt = feces.sort_abundance({'HOST_SUBJECT_ID': ['M3']})" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "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/vnd.jupyter.widget-view+json": { - "model_id": "e8572270a1b54515b5a87ebe1ae3f6b7" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "65e332d721784487ae0a2871fab5cc8c" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ea9711f2ddda44d99697d172ee5fbc00" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2beff49171384009abb18e6e00a7c4c5" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "12740e48d3ea4a288221d4226f9cb22d" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ae98b9f319b64cb789609bcfefd563d0" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "m3s=hand.filter_samples('HOST_SUBJECT_ID','M3')\n", - "m3s=m3s.normalize_compositional()\n", - "m3s=m3s.sort_samples('DAYS_SINCE_EPOCH')\n", - "\n", - "dd=m3s.diff_abundance('COMMON_SAMPLE_SITE','L_palm')\n", - "\n", - "dd.plot_sort('COMMON_SAMPLE_SITE',gui='jupyter')" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-05-09 19:27:08 INFO 1892 remaining\n", - "2017-05-09 19:27:08 INFO 134 samples with value 1 (['L_palm'])\n", - "2017-05-09 19:27:09 INFO method meandiff. number of higher in ['L_palm'] : 204. number of higher in None : 4. total 208\n" - ] - }, - { - "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": "stdout", - "output_type": "stream", - "text": [ - "------\n", - "\n" - ] - } - ], - "source": [ - "feces.plot(sample_field='HOST_SUBJECT_ID', feature_field=None, gui='jupyter')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "__We can see there is a set of sOTUs showing up in together in the individual of \"M3\" sporadically__ (near the bottom of the heatmap above). This behavior is difficult to see in a naive heatmap without clustering and sorting the features." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Let's look at bacteria that are more abundance (mean abundance at least 0.1%)" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-03-14 17:11:24 INFO 114 remaining\n" - ] - } - ], - "source": [ - "tt=feces.filter_mean(0.001)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "and let's do Qt gui to test the enrichment of the strange sporadic bacteria" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "#tt.plot(sample_field='HOST_SUBJECT_ID', gui='qt5')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Some more analyses\n", - "We can sort the features based on abundance in a specific field/value group. For example, let's sort the features by their abundances in the individual \"M3\" and then look how abundant those bacteria are in the individual \"F4\":" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "tt = feces.sort_abundance({'HOST_SUBJECT_ID': ['M3']})" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAABvIAAAEqCAYAAADHx8cRAAAgAElEQVR4nOzdeXRU9d3H8Q+4VMFal6qoVbtvtrV9nqctttoqslZFq9IWF5BVdnBDKIsgIIiyK9YFLSpqQJClIILIqmiFSDKZZIaELCRAAjGEmIWs3+eP3x0ISwIJzCSQ9+ucz6kkd+69szTnd+5nfr8rAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3DWZIukfRdSd8+xrZNJP1K0p8kXR7e02rwmkr6vqQL6vpEJJ0j6Uq5zwkAAAAAAAAAAAAi4EpJYyXtkpQlySfpMbni5nBNJD0gabekjZJuP4HjniupraQRcoUVjvQbSc9Luu0E93MyXusrJT0h91lpdILnAwAAAAAAAAAAgGNoKqmLpC8l9ZR0naRRkjZL+stRtm8maaikOXLFztHKvuPVRFJHSf8+wf2czq6TNFUnVphKJ+e1vkLSYEnjRZEHAAAAAAAAAAAQdldIGinpNUnnSWos6aeSpskVSGdU2va7ksZJ+kJu1t4ISVdLulDSfZJWS4qWm7X1He8xTSTdJOlNSamSVsoVh1dI+puk/0raLmmit11bSWPkSkJJ+oakFpKGyJWI7SR1lvQPSbMltZH0M7lZa6mSlnj7aCzpbEn/I+kV73cfeufZpIrX4kpJj0haIyneew1+7e2nuaSBklpKmiKpr6SLqnnelTXyXrvR3usWLTfjMbQs6bnec58rKUHSC95xJbeE6WQdLPKqe63Pkiv+Qs93uaR7vdft8Nf698c4buicx3jn/LGk7t5zGCGKPAAAAAAAAAAAgLC7VtK/5GbZNfZ+doVcYfOWXLkXcomk4ZK+lvS5pH7e4/tJ8ssVXxMkbZGb+XWZpNaS1sqVS70kzfIe+w+5GWIr5EqnJ+XuudddrjT6kXfMppLul/SG97MxknLlCqkouULtQ7nybaikt+UKq/aS/leuzFouqb93bL93jMOLqCslPS03E/FRuYJspaSXvefRXVKe3PKj6yV1q+Z5X3zYvq+WK/82eft+xtt2ivf63ur9bq5cSfahl2t1aJF3QTXH/LZcObfaey0GyZWbW+WWwrzvsNe6+TGO+wPvuW+RNEzSU3KFXqL32lDkAQAAAAAAAAAAhNlPJb0qV/qEZt99U1JXueUzKxd5jSV9T24G3yRvuz9Imic3w+x8Sd+SdKek+ZLukivh5kq6Sm4G2A1yhVp7uRlt3eUKuW/LFVU95YqyH3vHbCqpk3cuP5Yrr+Ik3SPp+3Iz9dZI+oW37Y/lZg3+W9Jfvd/1lJuF931JD3rndXgR9XNJz8rN9msqV1r29o57maSHJO3wnnszuZlsVT3vNoft+1eS3pGb8XaR91zvkCvbfipX6M32jtlUrmR7WdLjcjPkJnuvV/NqjvkPuZLwE2+7JnIz6kbIlaBXHfZa/7ia4w6XK1m/lJvR11RuJmBHudmYw4/y+gEAAAAAAAAAAOAku1auyBulgzPyLpG7F9rhRZ7kZus9Ljd77UxJreRmaq2XK4aelyuWtkv6p1zh9HO5IuoZSbFys95u08GSLjTzr6mOXuQ94J3Lj+RmCkbJFWKXy92vbbtcATVd0utys9DWys1imytpr6SNcrPyfiNXKB7uTLmC7ga5Au9tudl3oSKvp6RPJf1SrvCs7nkPqfRaynv8aEn5cjPghkn6s1w59gtJi7xznipphnfOX8mVbH+QK/LuPMYxp8mVjP/WwaVDG+tgCXfeYa/1tdUc9z1JD3uv4Xe9fTXyzjVU9FHkAQAAAAAAAAAAhNlP5Eqgyvc9u1xu+cWqirzBckXeWXJLZ34h6V254m6Y3BKX/eXuVXe/pEy5AutxubLpA7mSrfJsu6qKvAvkluQMzch7Qm7m3BneuUyQFPT2O8w7h396+71U7v5xd8stHxr0MsI798p+KOkluWUrZ0jq4/07VOR1lisQL/SOXd3z/tNh+24sNwvuFrlCb42kDO+c/ixXxn0iVwAO9/KYXPn5PzpY5FV3zH94j/uXXClZ+dhnyRWqlV/rX1Rz3I7e8//Iew1DQrP4KPIAAAAAAAAAAAAi4HK5Emy2DpZ2P5VbBnK0Dp1ZJh1a5J0ht8Tkf+RKovO8/EjS3yS1kysE35a7T1xo+cZ/eb8LFXlvSjpHbqZcF0nr5JbBlNyMsCk6WOSFjt1IrmQaJmmh3D3uzpMr2v7o7ffXcveyu1xuGcqfe8/pDR1aUIaKuf/ILdn5LblZid3lZrBdokNLsMbHeN7XHfaaXeX9/FfedlfJLYO5Vu4+dS/KlXXne7+/Um55zlbevkJLa1Z3zLZysxNX6GD5dr5cMTpX0jWHvdY/qea4d3iv2ybvtZT3et8gV+5R5AEAAAAAAAAAAERAqDxLkiuXfi/pKUmfy5Vbh7tSbgbX03KF1jVySzN+KldKXSu3TOfHcrPInvN+9wdv369I2iY38+tiuXvPRcuVR6EiaZVcAfVLuZLxKx29yDtLbonOL+Tu2Xet3Ey/RXLLTraStME7h59JulHSa96+vlnpOZ0hV4R96u3/597xt3mP/70OLfJ0jOf9f4e9Zr+Qu0feO5J+K1fOPSc38/C3kgZIivdei594//uR3CzAX8mVbbcf45h/lCv0EuRmLP5Mbmbdeu+1ueCw1/on1Ry3i3deyyW9L+l6b/9z5JbxfEIUeQAAAAAAAAAAAGHXSG75yfGS8iTtkRQnqZ/czK3DXSKprw6WaWfIFVWvS8qRtFtuJldHubKsjVzRli23bOVsuXJolVzZ1FxuFtnncmXVVXJFVK6kdG+71yTNkvQDuXu3jdTBIulCST0kBbxjp8jd8+8ncstZ9qn0uwxJS+QKvcOLqO9Imui9Bru985npnfMLcqVa5SKvuuf9jcP23URuBuJK7/UNbfsPSWfLzVacIGmf97s4uULx2zq0yDvWMb8tt8xmkve7JLni7xrvsZVf6/bHOO65ckXoCrn3Lii3FOccMSMPAAAAAAAAAAAgYhrLlW5Xyy1leaVc+VTVtk3llmMMOUOuUPu+3Ky5K+RKwEZyRdWlcmXS1XIzwy6RK+zOlJtVd7G3zTne/s/3fn+19/NveY870zt25dl0jeRKpyvklpn8rrf9Gd7vmni/+6H3u4t05P3xQs8rdNxrJDXzjnmV999NvOdYucCq6nkfLvQ6XCLpe3KFZLNK24aO/V1vP6FlSEOzDs+vtG11xww93yvlisxrvMeGlket6rU+2nGlg+/dj7zzvsh7TSq//gAAAAAAAAAAAIiQRqr9bKvqHnv4747nGDU9j5oc/3iPezyPq+m+j3WOx/vaVLddbc7pZLx2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg9LJjx46rEhMTn96yZcv2TZs27SCEEEJIw0l0dPT2+Pj4ZRkZGbfU9ZjkVJOenv7LYDC4IDo6OqOu30dCCCGERD4+n88fDAb/npKSck5dj0tONVu3bh2+ZcuWQF2/h4QQQgiJbKKjozPi4+PXJyYm/rmuxyOnlC1btrTZunVrfn5+vpWUlBBCCCGkAaWoqMh27dpVHBsbO6euxySnkpSUlAvi4+MHpqamFu/fv7/O30dCCCGERD7Z2dnl27ZtiwkEAjfX9djkVJKYmHhPcnLyln379pXX9XtICCGEkMhm//79tmvXrtKtW7f+OxAI/KSuxyWnjM2bN9+WmJhoFRUVBgAAGp69e/fa5s2bF9f1mORU4vP5LktISBidnp5e128fAACoI4WFhZacnLwnNjb2jroem5xK/H5/r9TU1OTCwsK6fgsBAEAdyMnJsaSkpI/9fv/v6npccsoIFXkAAKBhys3NpcirIZ/Pd1l8fPyYjIyMun77AABAHSkqKrKUlJRsv99PkVcD8fHxvdPS0ijyAABooLwib01MTEzzuh6XnDIo8gAAaNgo8mqOIg8AAFDk1Q5FHgAADRtFXi1Q5AEA0LBR5NUcRR4AAKDIqx2KPAAAGjaKvFqgyAMAoGGjyKs5ijwAAECRVzsUeQAANGwUebVAkQcAQMNGkVdzFHkAAIAir3Yo8gAAaNgo8mqBIg8AgIaNIq/mKPIAAABFXu1Q5AEA0LBR5NUCRR4AAA0bRV7NUeQBAACKvNqhyAMAoGELd5HXWNK3Jf1J0t8l3S3pl5LODMfBjkNTSd+XdMGJ7IQiDwCAhi3MRd45kr4n6TeSflUp10n6kaSzw3TcsKLIAwAAFHm1Q5EHAEDDFs4i7yxJLSR9JmmXpO2SciSlSposV6pF2m8kPS/pthPZCUUeAAANW5iLvCskjZG0R9Luw/IfST8+gX2fK6mtpOGK8FiMIg8AAFDk1Q5FHgAADVs4i7zvSZoqaZGk/5PUTNJPJY2UtEXSrSf7gMfhOu+cbj+RnVDkAQDQsEWgyHtKbgz1a0k/lJuJ9yNJV0n6xgnsu4mkeyX9W27mX8RQ5AEAAIq82jmRIs8bt9pHH31kmzZtstzc3DC8swAAIJzCWeRdJ+kdSc/Jzc6T3FKb10r6p9y3wSXpSkmPSFojKV7SNLmLVudKukXSCEkPSPpUbnZfT0k3SnrN236KpF94+75O0lhJw+QufsXIXQgLfXP9V3KzAUNF3oWS7pO0WlK0pCckfedYT4wiDwCAhi0CRd4oSW/KzZprdFik6scwTSTdLOktuZUQVkrq4u33b5L+K7dSwkRJN8mNycbIjckkVxS2kDRE0uWS2knqLKmjXAHY0vv5E5LiJG2U9KCk86p7UhR5AACAIq92alvkZWdn29SpU61r167Wr18/e+ihh+zFF1+0HTt2hOkdBgAA4RDOIu8quZItVdIzkv4o6VK5+7o0lbtIdKWkpyVtlvSo3AWhlZJelnSZpO6Svpa74DRcrrzbJ8kvaYZcyfeJpJckfVPuolOC3EWl0XKF3meSFku6WocWeRdI6ufta5qkCXIzBf8t6eLqnhhFHgAADVuEiry5ciscXCI3hrpYrqSragzzutz4qbWktZJekdRL0ixJn0v6h1wZt1JufPak3Jejekj6WG7Gn+TGaQ9Imi33ZaixknLlyr935e57PFXSl955viIpRW5cdkZVT4oiDwAAUOTVTm2LvBUrVtjAgQNt6dKllp2dbfPnz7dBgwbZ+vXrraysLEzvMgAAONnCWeSdIekncsVZuqRsSZlyF5bayxV5P5f0rNy3vJvKXajqLWmO3IWonpJ8ku7wfn+9pIWSpst9E/1SSX297c+X+4b4x94+zvN+do/ct9W7yM3Ym+wdv7mkeZIe87b7lqQ7Jc2X1Ka6J0aRBwBAwxaBIm+CpEJJWXL3Gs6UtMEbqxxtDPNXbwzzV7kSbq7cl6rOlSvrXpUb/1wkV9y9K1cMXiDpIUnrdXAFg6ZyY7O3vJ89I/clqXvklkrvJDcL71a58VYzudUVPpL0/aqeFEUeAACgyKud2hR5FRUVNmvWLHvmmWcsdA0rPT3dnnrqKVu6dKkVFRWF620GAAAnWTiLPMmVed+UdI2kP8tdcFojaZvcbLlz5C7+3CBXvr0td7GqcpG3Xge/If4rSS9Iut/7d1O5i0mVi7w5cst3hvxAbumocXJLdk6WuwjWSq4kXC83c/B5uQtg2+WWkmpc1ZOiyAMAoGGLQJE3WtIyubHNH738n9xqBq2PMoZZ4I1hhsqNiX4u90WoZyTFyq1+cJsOjp3e8v67qY5e5IW2+bF3Lu/KlYDnyc3yC43XJsutpLBabknz0NLpR6DIAwAAFHm1U5sib//+/TZt2jR74403LDs7+5Cfvf3225aTkxOutxkAAJxk4SryGkn6mdyFoe96/z5TbjmoX8ldcHpDbobcSzq4VGYf79+HF3mH3+Ouvffvw4u81nL35ftBpXP5jlxp+LQOLfJaS/pC7sLUP71thkrqL+lP1T252hR5ZWVllp2dbcFg0LZu3WpJSUn21VdfheltBQAA4RShpTXfkhvfnOnlDLn7DrepZgzTVm5GXqakTZIelzRSrhQMFXmh2Xbn6ehF3gVyX7AKFXlD5L4UdYb3mIfkluacUun4/5TUTW41hqOqbZFXXFxsGRkZB8ZQKSkplp+fH6Z3FgAAhBNFXu3UpsgrKSmxGTNm2JtvvnmgyCspKbHp06fbnDlzuCYFAMApJFxFXmNJN0v6UK6Ma1Tpd5fJXfB5V275p//ILdX0LbmlNbvLXTi6RFUXebd7/z7ajLyF3v+G/FbS+3IXoUJFXntJN3nH7iR3Ueo8uZl/f5MrGKtUmyIvKyvLZs2aZV27drWuXbvakCFDbMOGDWF6WwEAQDhFsMg777DfNZYbwyzR0ccw7eTuffe23P2BQ0uT/0uu5AsVeW/IrYxwrqSuckufh5bF/K5cSRcq8gbLfSGqUaXtP5P0u0rHv05uGfNmVT2p2hZ5wWDQhg4demAMNXbsWEtLSwvTOwsAAMKJIq92alPkFRUV2dSpU2327NkHirzCwkKbMmWKvfXWWxR5AACcQsK5tOb3Jb0oKV7uvinXyl3kGSEpTdJUuULuU7kLRD+XK+62yd0D5vdySzfVpMi7RVJAbnmnGyT9j9zsv8/lZtlVfvw13jl8KnePl2vlLpp9LLd0VZVqU+SVl5dbfn6+5eTkWE5OjuXm5lpxcXGY3lYAABBOdVjkSW4MM02HjmFGS1olt+rAJEmfSPqD3P30XpEbXz0md1+8XpKi5b7YdKXcDL9VcvfO+6XcDL5s7/g/kRunjZMr8hrJfUlqmaT35Mq838str7lE7v7FR1XbIq+0tNRyc3MPjKHy8vKsrKwsTO8sAAAIJ4q82qlNkVdeXm4vvfSSjR8/3pKSkszMbMeOHTZ27Fj7z3/+YzXZFwAAqFvhLPLOkFte81+S8iTt9hIvt/xTM7llLydW+v3nkmbKLbU5Xe4b3zWdkbdJ7sLWVkl7vH93kHT2YY8/Q9IvJL0uKcc7/iZJHSV9o7onxj3yAABo2MJc5F0mt1RlVUXeGXKFW+UxzBeS/iF3b+K23r+z5cZUs+VWJ/hIbmzWXNIKuXHXbZKukvScpFxJ6XKl3muSZsktV/6I3BexQissnCt3r+EVcmOtnZKWy80UrPIew9wjDwAAUOTVTm2KPDOzdevW2eOPP25RUVGWmppqs2bNsv79+9vGjRutvLw8TO8yAAA42cJZ5EnuQtO3JH1PbsbdT+XKu6ZyF4MayxVwV8l9u7yZ3H1ZrpK7iNVE0rfl7gsjufvCnC+3FJS8fTSRdKG3TWtJc+WW0PyOpB96+/xGFY8/w3vs9+XKwisq/a5KFHkAADRsYS7yGssVeBfq0OXJK6tqDNNIbtxzqdzY6mq5sdUlcuOrM+XGQxd725zj7Ss0Hrva+/m3vMed6Z3LNw87/tnedj+SK/su9vZbJYo8AABAkVc7tS3yCgsL7e2337a+fftat27drFOnTjZv3jzbt29fmN5hAAAQDuEu8kJCpV1jVX1BqtFh/13VdlU5Q+4b6FFyheHh+zzW+R338SjyAABo2MJc5NVEdWOYw393PGOdmo6/jnsMRZEHAAAo8mqntkVe6DXPysqy9PR02717txUVFVlFRUUY3l0AABAukSryIqGx3D3xHpGbxRc2FHkAADRs9ajIO2VQ5AEAAIq82jmRIs/MrKKigvIOAIBT2OlU5EluSaemqub+LCcDRR4AAA0bRV7NUeQBAACKvNo50SIPAACc2k63Ii8iKPIAAGjYKPJqjiIPAABQ5NUORR4AAA0bRV4tUOQBANCwUeTVHEUeAACgyKsdijwAABo2irxaoMgDAKBho8irOYo8AABAkVc7FHkAADRsFHm1QJEHAEDDRpFXcxR5AACAIq92KPIAAGjYKPJqgSIPAICGjSKv5ijyAAAARV7tUOQBANCwNYQi7xxJ35P0Q0lnSmoq6aeSfuXlOknXSrroeHcYKvKKi4vr+v0DAAARVl5ebtnZ2RUxMTELT/6wpV45T27MdLXcGKqZpF/r4BjqF5KukXT28ezM7/dfFBcX90RKSoqVl5fX9dsIAADqQF5eniUnJ6cEAoG2xxg6XC53rebCw35+oaQfSfrW8Q5oToILJX1HUpMIHvMQwWCw87Zt24L5+fl1/RYCAIA6sHv3bktMTHwvISHhl3U1Hgm3KySNkDRL7oLUryQtkbT7sMRIekxHDhKPkJKS8utgMLjK5/NVxMTEGCGEEEIaVuLj45PS09O7hWvwUk9cJ+ltSU9L+qakLpL26NDxU5akDyU1l9Soup2ZWePU1NSbg8FgYl2/f4QQQgipm/j9/tKtW7eOSUlJaVbNsKGJ3DWc3ZJ6y13LCWku6RVJrY419jiJ/iDpZUm3RPCYh/D7/c0SExPnxMXF7a/r95AQQgghkU8gEMhLTEy8z8zOrIuxSCRcIWm0pDlyg79fSPq3pOck/UDum1z/K+kJuTJvutwsvipt2rTprPT09Iuio6OvIIQQQkjDS0xMzKXp6ennhm/4Ui/8UtJrkkbKFXkPSfpC7iLW9yT9TNKtcmOsNZJuONYO/X7/2UlJSZfW9ftHCCGEkLqL3+8/z8waVzNk+LU3tjBJb8qtEBByvaTnJd1Uo1HNiamL8vAQo0aNapySknJBfHz85XX9/hFCCCEk8vH7/c1SUlKq7a1OdVdIGqVDi7xX5WbpNZYbhJ0h6duSHpa0WdLNdXGiAAAA9UhozDRcB4u89ZJ+LDd+aiy3rObvJEVJminpdC83AQBAeDWS9LikqZIGSJov6S65Zb4lV6otkDRD0ly5L2Q/L/cFpDPkvmg0UtKfKz3mx3Iz+66T1EZSJ0l/l/QfSUFJ4yV9XwfHNy0kvSMpSdIUSb3kZuTd5G3zE0nDJG2S9LmkMXJfEj9LUldJ93mPWSdpo9wY6hLvXJpI6iBXVAYlvSTp/7zHSu62MOMkxXrnd6ek82v4GgIAAJxyqivyKn+TqrFcgTdf0m2RPUUAAIB6p7oir7LLJP1T0ls6dOkrAACAmmomV9QNkRtzLJA01vu55Iq8dZJ2SJosV/p9Lmmx3GpLv/ce01EH7+P7R7nC7BZJnSVFy5V0z0h60vv3w5IukLse9IlcSThI7lrSdu+YN8rdOzhKrmR7WK40/FLuVi2XypWCaZJWeD+bJulTuTLyG97PtnjnM0BubPWxd44/lPSepI+8/c6VFCfpAfFlKQAAcJo73iJPct/OmiKpfQTPDwAAoD463iKvqdw32ynyAADAifqLXFH2F7kZdb3kxhg3yF3DaS5puVwhdpncOKStpA2S+ktqKWmR3Ky4UJF3vdyMupaSHpQr1npJulhuttsUuXsC/1ru2tEcuVKwiaQrJb0oaZXcLL/fSXpBrvBrKlf+vShX6jWTNFHSMrmZf+dJukbSEkmDvccukzRBbpnyJnL331vgne9Q79gtvMdeKldWPiN3axgAAIDTVk2KvN9Lmi3p9gieHwAAQH10vEXeBZL6iCIPAACcmG/IFWoJcjPb/i7p35ISJXWXK86aS5olV96F7rN3vvezR+UKwMOLvOZyM+BCRV6UXFkWuib0kNzMvJvkSrcn5MY38rbpJOlt7/dnS7pKbkWnAXIz9fLlltoMFXlTdHC89A25Mm6Ad27zvecVWkrzTEkXeseb6D33d+SWDp0qySdXPP5JdXR/PgAAgEg43iLvbLnB1JdiaU0AAIDjLfJ+IPfNdIo8AABwIn4u6UNJKZIyJO2VFJCULekVuaUnm0uaroP3q5NcWTZNbinMW3VkkddS0r+8xzyog6Vc6PE9dPC+ekvkSremlc7rbrlC8Sa5e/EtkCsXX5D7MtPncteYQkXeVB0cL50lV+wN9M4tStIdOlhCSq7MayrpObmx1jS5YvCfckuMdpOb2QcAAHDaOlqR95LcsgahQVsj7+fz5W44fHWkTxIAAKCeOVqRt1bS9yttc76k3nIX2fqLb4oDAIDaaSQ3ppgnt0rS5XLXcy6VK8tWyt0G5Y/eNn/TwVltP5RbsnKIXNn2ntwXtc/09vuY3D30blL1Rd4NciXgVLlZd5J0hve7Zd5jusiVen+Rm0V3vlyhN0Buqc+jFXlTdbDIWys3ZgoVhdd459NTbubey5J+K3f96jy5mYO3efsGAAA4bR2tyJsrNzhrKzeQekJSrNySBQ/IDdQAAAAasuskvaFDi7wEuYtpt8hdIHtNUpbcl6GuOvpuAAAAjuliuWs1U3Xk7LNfyBV5I+VKrbVyS1re6f1uhqQ4uZlzV8uVds/L3Rvv73Iz5j6RdKNcYRalI4u8J+VmBA6U9F+52XDXSuost3JT5cevk9TPO/YQSUmSXpebrfesjizynpUr734gN3b6VFJHb/+TvH3/RVIr77nNkLtH358kfSBprNy1LQAAgNPWJXKz70JF3k8kvStpv6SvJOXILYnwvNwa5+fUzWkCAADUKz+Wu7g0XO5b490llUraJzeG2i63/FRvuYtmjY++GwAAgGP6raT35e5Hd/h1mSZys9XmyI07lsgVXF9K2i1X4j0k6SK5L2Y/KClabknOTyTNlltloLmku+RKt5t0aJH3uNyqAxfLzeDzefv+VO6edXPllt78gdyMvB3e7+fJLS/+paT75e7x96wOLfImeud3oVxZ+IakdO/xX3jP+QK5JULvkbRR0h7v/N+U9BvxhXMAAHCaayxX4F0oN0gL3Uj4ikq5TG45hLOq2AcAAEBDc6bc+OibcmOoJjp0/NRM7oLZuWJJTQAAcGLOVtXjikZyY5IL5b5cdJGXq+SW1bzisMedK7c053flrvdcIOlb3jHO8f59tg5qInfd6AxvH029ff/Y2/cF3lKJ+I4AACAASURBVLHP9ra5QNKV3v6/7Z3LNd4xzvdy5mHn3kTu+lTo8d/z9n+5d06V7/fXTNKP5ErDiyrtCwAAAAAAAAAAADglNFL1XyY6kS8aNVLN9n+sbavaf21/DwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACInG3btv02EAisiY6Ozti0adMOQgghLps3b94RGxubERMTE5b9f/nll8nBYPDVnTt3XlP573JqaupvAoHAB/xdJoQQQgghhBBCCCGEkIYTv9/vS0xM7JCSknKOJCklJeWCQCAwKDU1tXT//v1WUlJCCCHES35+vqWlpdn27dvDsv+CgoKKHTt2ZAUCgbGhEi8lJeWC+Pj4QSkpKSX8XSaEEEIIIYQQQgghhJCGk+zs7PLk5OSNwWDwBklScnLyZYFAYEx6eroBAA61f/9+S09Pt4yMjLDsv7S01LKysgp9Pt9roSLP5/NdFh8fz99lAAAAAAAAAGhgCgsLLTk5OSsmJqa9JMnv9zdLSEgYF66L1ABwKotQkVcUFxf3eqjI8/v9zeLj48fydxkAAAAAAAAAGpaioiJLSUnJjo2NvYMiDwCOgSIPAAAAAAAAABApFHkAUAMUeQAAAAAAAACASKHIA4AaoMgDAAAAAAAAAEQKRR4A1ABFHgAAAAAAAAAgUijyAKAGKPIAAAAAAAAAAJFCkQcANUCRBwAAAAAAAACIFIo8AKgBijwAAAAAAAAAQKRQ5AFADVDkAQAAAAAAAAAihSIPNZKXl2eJiYmWm5trWVlZlpycbBUVFVZWVmapqan26quv2sCBA61fv372zjvv2K5duyJ6fjt27LAVK1ZYVlZWldtUVFRYWlqaLV261LKysmzfvn22du1ae/311+2NN96w2bNn29y5c83v91tpaWkEzx6nAoo8AAAAAAAAAECkUOShRrZs2WJjxoyxuLg4W7p0qY0dO9bKysosOjraOnbsaPfdd5+99NJLNn78eGvbtq098sgjlpmZGZFzKysrs9WrV1v//v0tKSnpmNv169fPkpKSbOfOnfbss8/anXfeacOHD7cnnnjCOnXqZK1atbIRI0bYV199FZHzx6mBIg8AAAAAAAAAECkUeThuFRUV9umnn9rQoUNt+/btNnfuXIuKirL8/HyLioqyLl26WFxcnBUUFFhubq4tXrzYHnjgAfvwww8jcn5lZWW2du1a69evnyUmJla5XXl5ua1evdp69+5tiYmJtnPnTps2bZqNGjXKcnNzbd++fbZjxw6bPXu23Xrrrfbqq69aeXl5RJ4D6j+KPAAAAAAAAABApFDk4bjs37/fEhISbMqUKda5c2d76623bMiQITZhwgQLBoP29ttvW7du3Sw1NfXAY9LS0uydd96xmJgYKysrs0AgYCNHjrS2bdtahw4dbObMmZaTk2Opqak2a9YsmzlzpvXq1cvuuusue+aZZ2zp0qXWq1cva9++vY0ZM8Z27txpqamp9vzzz9v48eNt0KBB1q5dO3v44YfN7/dbeXm5rVmzxvr06WOJiYlWVFRk69evt549e1q7du3skUcesWAweGC7UJG3a9cumzFjhj399NMHCruKigrbvn27TZgwwR599FHLz8+vq5ce9QxFHgAAAAAAAAAgUijycFxycnLsvffes06dOtldd91lgwcPtvbt29vIkSNt06ZNtmrVKmvZsqV16NDBpk2bZp999pllZmZaUVGRlZSUWCAQsAEDBljfvn1t3bp1Nnv2bOvSpYstXLjQ/H6/9ejRw+677z6bO3euvfbaa9amTRvr1KmTzZs3z6Kioqxr1642efJk8/l81r17d/vrX/9qL7/8sq1cudKeeOIJ69OnjwUCgQMFXUJCgq1Zs8YeeOABmz59uq1cudJGjhxpAwYMsNTU1GMWeWZm+fn59u6771r37t0tLS2tDl991CfHW+Tt2rXL5s2bZ2+++eYhWbBggSUkJFT5OIo8AAAAAAAAAEAIRR6OS3l5uWVnZ9u8efPsmWeesQ0bNtjw4cMtKSnJSkpKDszYe+WVV6xbt2528803W5s2bWzw4MGWlpZmOTk5tnHjRgsEAlZQUGAbN260/v3724QJEywmJsYeffRRmz17dugDaRMmTLDRo0dbYWGhpaen27Rp02zcuHEWGxtrAwYMsGeffdby8/Ot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dOlSW7p0qZWXl1tmZqbNmDHD2rZta7fffruNGDHCfD6fLV++3MaMGWN5eXlmdnCJzqioKCssLLT169dbz549rV27dvbII480qOU6T+cir6CgwObPn289e/a0Dz/80IYOHWqzZ8+2iooKy87OtoULF9rUqVNt9OjR1rZtW+vTp49FR0dbYWGhrV692p566imbMmWKtW3b1jp16mRLliyx8vJyKysrs0AgcODvzv3332/z5s2z7OxsW7JkibVq1eqQv59H+1zGxsYedduioqLT6vNIkQcAAAAAAACgXopE0ZKZmWnPPfectWzZ0p588klbs2aNPfvss3bvvffaBx98YOvXr7c2bdrY3XffbdOnT7cNGzbY9OnT7emnnza/32+9evWyjh072rvvvmsLFy60fv362YQJEywhIcEmTJhgd911l82ZM8e2b99+yHEDgYANGDDA+vbta+vWrbPZs2dbly5d7P3337ft27fbuHHjrH///rZlyxabPn269e7d21JTU83n89lDDz1kjz76qK1cudImT55snTp1shUrVtjixYutc+fOtmjRIlu+fLkNHDjQBg8ebPn5+QeOG5opWPk5LVu2rMpzSUhIOOpznDRpku3du9fefvtt69ixo73xxhu2ePFi69Gjh3Xo0ME+/PDDEz7Xk4kiz82s8vv91rNnT7v11lttxIgR9tFHH1laWpoVFhba/v37LSsry2bMmGFdunSx5cuX27Jly2zgwIH25JNP2sqVK61Hjx72+eefm5lZdHS0DRw40BYtWmRr1qyxBx54wKZPn24rV660kSNH2oABA4743J+uTuciLy0tzcaOHWujR4+2Xbt22cyZM23QoEGWm5tru3btskmTJtmtt95qEydOtOXLl9vw4cNtyJAhtnv3bps7d67dcMMN1rdvX1u5cqVNmjTJHnroIUtKSjKfz2ddu3a17t2729KlS+2FF16w9u3b28SJEy0+Pt4mTJhgd999t82ZM8c2b9581M/lyJEjj9g2OTn5tPs8UuQBAAAAAAAAqJciUbSELkT369fPMjMzraSkxFJTU23ixIk2dOhQ++ijj6xjx44WFRVl+fn5lpGRYdOnT7dx48ZZbGysPfroo/b6669bUVGR7d271+bMmWODBg2yvXv32urVq61v374WDAatrKzskOPm5OTYxo0bLRAIWEFBgW3cuNH69+9v48ePt5KSEouNjbV+/fpZixYtrEuXLvbZZ5/Z119/bfPnz7fOnTvbpk2bLCcnx2JjY2348OH2xBNPWFRUlN111122ePFi27VrlyUnJ1tcXNwh97MKLUNX+Tnt2bOnynOp6jk+/PDDFh0dbcOGDbMXX3zRCgsLraioyD766CN78MEHbcGCBVWe65AhQywqKsruvvvuas/1ZKLIc0pLS2379u02b948GzBggLVs2dJatWplvXr1si+++MIKCgosNjbW/vvf/1pBQYEFAgF76qmnbNCgQebz+Wz06NH27LPPWmFhoS1evNh69eplW7ZssalTp1qfPn0sNTXVsrOzbdWqVda3b19bsmRJXT/liDhdi7zQ/ee6detmy5Yts6KiIlu0aJHdf//99sknn9iuXbts8uTJ9thjj1lubq7t37/fVq5caX369DGfz2dRUVHWo0cPS05OtuLiYtu8ebMNGTLEFi5caO+995517drVfD6fFRcX2549e+y1116zHj162LZt2+zjjz+2fv36WTAYtLy8vCo/l3v37j1k2507d552n0eKPAAAAAAAAAD1UqSKvBdeeMEmTpx44P5gX3/9tb377rvWv39/W7p0qfXu3du2bt16YPsZM2bYuHHjLCYmxoYNG2bLli0zM7P8/HybN2+eDRw40Pbt22dr16613r17W2Ji4hHHzcvLs0WLFlnHjh2tTZs21qJFC2vdurVNnTrVysvLLT8/36Kioux3v/udPfbYY1ZUVHTgZ82bN7eWLVta69atrWXLlv/f3p1HaUHe9wL/uSSNW1I1MY2a7TZJT3tq0va2t9pb1wjU402sIWgaqEFwJagoGo1Rb6oNCkKAELnRmNxqGzUgNehRltzL5gJaqwV0Bi7IIs44AwgMI6sz87t/PO8MAzKDyuJIP59znnPgXZ7l5TnvH++X3/PkKaecktdee20uWbIkf/KTn2SPHj2ye/fubcfYbd26tW3c5ubmtnm1rqmjuYwcObLTNc6ZMydvvvnmnDJlSlv/8+fPzxtvvDHHjx/f4Vyvu+66dzTXPUmQV0KZNWvWZE1NTW7cuDHXrVuXtbW1OX369Bw4cGBeddVVuXz58nzuuedy0KBB2aNHjzzzzDPz5JNPzkGDBmVdXV0++OCDbYHJ3XffnUOHDs0VK1bksGHD8qSTTspu3bpl9+7d2/bQXXfd9Z/i3r39Nchbs2ZN/vznP88TTzwxTz/99OzRo0eedtppeeqpp+bQoUO3+48Nzc3N2dzcnDNmzMjLL788586dm+PGjcurrroqGxsbM7N8P9x00005YcKEfOihh3LAgAHZ0NCQmdu+m1r314wZM3LAgAG5ePHi3LJlS4f7sqGhYbvXvv766/vdfhTkAQAAAABd0r4K8kaOHJnXX399btmyJTPLnWF33313Dho0KCdPnrxdGLezIG/SpEmZ+fYgr/XH5SVLlmw3ZnNzcz799NN50UUX5SOPPJJ1dXU5b968vP3223PEiBHZ1NSU8+bNy759++YZj0P/HgAAEvVJREFUZ5yRvXr1yieeeCI3bNjQVsWyYMGCXLlyZb722mv53HPP5dNPP521tbW5YMGCrKury5deeilHjx6d/fr1yxdffHG7sVt/aF+0aFGncxk+fHina5wzZ04OHjw477///mxpacnm5uZ86qmn2irydneue5IgrwTU48ePz2uvvTbfeOONzCzHbW7YsCEfeeSR7Nu3bz766KN5ww035KhRo3L58uW5dOnSvPfee3PQoEHZ2NiYc+bMyQEDBuSPf/zjvPHGG3P27NlZV1eXo0aNymuuuSbr6upy5cqVuWTJknzqqaeyurr6fV71vrG/Bnkvv/xyXn311XnHHXfk/Pnzc+7cuTlnzpwcPnx4XnLJJfnss8/mmDFjcsiQIR0GeYMGDWo7Mrc1yHv44YfzgQceyEsvvTRXrlyZmZmbN2/OiRMnZr9+/bYL8pYsWZLV1dUd7ssdv2v3x/0oyAMAAAAAuqR9FeTdeeededZZZ+W9996btbW1OWHChDz//PPzZz/7Wc6YMSMHDhzYaZDXUUXetGnT8oILLsjp06fnpk2b2sZsamrKadOmZe/evXPSpEm5YsWK/MUvfpE9evTIYcOG5dKlS3PIkCF5xRVX5Msvv5xjx47Niy++OF9++eV85pln8vzzz88xY8ZkTU1NTp8+PS+55JIcOXJkPvzww20/rtfW1uZ9992Xffr0yblz57aN3Xq0ZuuaOpvL0KFD247P3NkalyxZkqNHj84LLrggZ82albNnz87LLrssv/nNb+bUqVM7nev48eN3Odc9SZBX9t2MGTPyrLPOyquvvjqrqqqyrq4uZ82alZdddlleeeWVOWvWrLz00ktzzJgxWVtbmxMnTsyzzz47Bw4cmKtXr866urocOXJknnLKKTl48OBcv359btq0KX/zm99kz54987HHHsu6urocN25c9u/fP5955pn3e9n7xP4Y5G3atCkfffTRvPDCC3Pu3LnZ1NSUTU1NuXXr1pw5c2b27t07R48e3XZn6LupyHv88cfzqaeeynPPPTdvvfXWfOWVV3Ly5MnZs2fP/N73vpeNjY05bdq0/M53vpPTp0/POXPmdLgv6+vrt3vt2rVr97v9KMgDAAAAALqkfRnk9ejRI/v375/dunXLr3/96zlixIhctWpVzpo1q+3IwdbXjx07Nu+888586aWX8rbbbsvf/va3mbl9yNXY2JjV1dU5YMCA/Pa3v51Tp05tG7OlpSWXLVuWP/zhD/O0007L7t27Z8+ePbNv377Zp0+fHDVqVPbt2zfnzJmTTU1NWVVVlddcc03+4Ac/yPr6+pw4cWJ+4xvfyG7duuXXvva1HDJkSNbW1uYrr7ySt9xyS55xxhnZrVu37NWrV95///25efPmtrFbg7zWNXU2l/79++djjz3W4RrXr1+fy5cvz2HDhuXpp5+ePXv2zIsvvjgvvPDCfPLJJ7OxsfFtc7399tvf8Vz3JEFe0djYmJMmTco+ffrkV7/61ezWrVv26NEjBw8enNXV1bl69eq855578uSTT87u3bvneeedlxdddFH27Nkzp0yZklu2bMkpU6bk+eefn+PGjcuWlpZsaWnJ+vr6HDt2bFufvXr1yvvuuy83btz4fi95n9gfg7z6+vocPXp0XnvttW/7d2z9zujXr1+OGTMmR4wY0RbkzZw5M6+44oqcN29eTpgwIQcNGpQbNmzIzG1B3uTJk7f7fjjzzDPzrLPOyptuuimXLVuWLS0tWVVVlQMGDMjevXvnr3/96073ZfvXTp06db/bj4I8AAAAAKBL2pd35A0ZMiRXrVqVy5cvz5qamnzzzTezpaUlt2zZkuvWrcumpqbMzLb76xobG/Ott97K9evXt4VPLS0tbXePtbS05FtvvZXr1q3LN954Y7uKvMxSHdXQ0JArVqzIFStW5OrVq3P16tVZU1OT69evz7Vr17bdF/fWW29lQ0NDNjQ0ZHNzc27evDlXrlyZy5Yty5qammxsbMyWlpZsamrK9evXZ01NTb766qu5cuXKnf5wveOaOppLbW1tbty4scM1rlu3LmfPnp0zZ87M+vr6rK+vzyee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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACALuj/A1si8nMyrHqgAAAAAElFTkSuQmCC", - "text/html": [ - "\n", - "" - ] - }, - "metadata": { - "isWidgetSnapshot": true - }, - "output_type": "display_data" - }, - { - "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" - } - ], - "source": [ - "dd.plot(feature_field=None, gui='jupyter')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Conclusions\n", - "\n", - "* We can identify the taxa that colonize and persist, the ones that disappear forever in the middle of the period, and the ones that stochastically come and go, which is also reported in the original paper.\n", - "* In addition, with convenient exploration of the data in heatmap, we find a set of sOTUs appear together in a group. This set is enriched with skin bacteria. We can hypothesize that this set is likely from skin and is a result of sample collecting protocol." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Time Series tutorial 2: Eric Alm dataset\n", - "\n", - "This data set is from:\n", - "David LA, Materna AC, Friedman J, Campos-Baptista MI, Blackburn MC, Perrotta A, Erdman SE and Alm EJ (2014) Host lifestyle affects human microbiota on daily timescales. Genome Biology, 15, R89.\n", - "\n", - "The raw data are reproccessed with [deblur method](https://github.com/biocore/deblur), which is published in [mSystem](http://msystems.asm.org/content/2/2/e00191-16)\n", - "\n", - "## Load data" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": { - "collapsed": false, - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-03-14 17:11:26 INFO loaded 811 samples, 7289 observations\n" - ] - } - ], - "source": [ - "# we can also read into the generic `Experiment` object\n", - "alm = ca.read('data/alm.biom','data/alm.samples.txt', normalize=10000)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Get rid of the 'unknown' days and convert to number" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "alm.sample_metadata['collection_day'] = alm.sample_metadata.collection_day.replace('unknown', -1).astype(float)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## `DonorA` was abroad days 71-122, let's add that info to sample metadata" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "alm.sample_metadata['travel'] = None\n", - "alm.sample_metadata.loc[(alm.sample_metadata.host_subject_id == 'DonorA'),\n", - " 'travel'] = 'no'\n", - "alm.sample_metadata.loc[(alm.sample_metadata.host_subject_id == 'DonorA') & \n", - " (71 <= alm.sample_metadata.collection_day) &\n", - " (alm.sample_metadata.collection_day <=122),\n", - " 'travel'] = 'yes'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Both donors had diarrhea at some time points - let's also add that info to sample metadata\n", - "be careful with what you eat `:)`" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "# donor A had diarrhea during his/her travel\n", - "alm.sample_metadata['diarrhea_donor_A'] = None\n", - "# no diarrhea except for 2 periods ...\n", - "alm.sample_metadata.loc[(alm.sample_metadata.host_subject_id == 'DonorA'),\n", - " 'diarrhea_donor_A'] = 'n'\n", - "# 1st period of diarrhea\n", - "alm.sample_metadata.loc[(alm.sample_metadata.host_subject_id == 'DonorA') & \n", - " (80 <= alm.sample_metadata.collection_day) &\n", - " (alm.sample_metadata.collection_day <=85),\n", - " 'diarrhea_donor_A'] = 'y'\n", - "# 2nd period of diarrhea\n", - "alm.sample_metadata.loc[(alm.sample_metadata.host_subject_id == 'DonorA') & \n", - " (104 <= alm.sample_metadata.collection_day) &\n", - " (alm.sample_metadata.collection_day <=113),\n", - " 'diarrhea_donor_A'] = 'y'\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "__Donor B had diarrehea but from Salmonella infection instead of traveling__:" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "alm.sample_metadata['diarrhea_donor_B'] = None\n", - "\n", - "# before diarrhea\n", - "alm.sample_metadata.loc[(alm.sample_metadata.host_subject_id == 'DonorB') & \n", - " (151 > alm.sample_metadata.collection_day),\n", - " 'diarrhea_donor_B'] = 'n'\n", - "# diarrhea\n", - "alm.sample_metadata.loc[(alm.sample_metadata.host_subject_id == 'DonorB') & \n", - " (151 <= alm.sample_metadata.collection_day) &\n", - " (alm.sample_metadata.collection_day <=159),\n", - " 'diarrhea_donor_B'] = 'y'\n", - "# after diarrhea\n", - "alm.sample_metadata.loc[(alm.sample_metadata.host_subject_id == 'DonorB') & \n", - " (alm.sample_metadata.collection_day > 159),\n", - " 'diarrhea_donor_B'] = 'n'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Take the fecal samples" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "UBERON:feces 526\n", - "UBERON:tongue 285\n", - "Name: body_site, dtype: int64" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "alm.sample_metadata['body_site'].value_counts()" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Experiment alm.biom with 811 samples, 7289 features" - ] - }, - "execution_count": 32, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "alm.sort_samples('collection_day',inplace=True)\n", - "alm.sort_samples('host_subject_id',inplace=True)" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "alm_feces = alm.filter_samples('body_site','UBERON:feces')\n", - "alm_saliva = alm.filter_samples('body_site','UBERON:tongue')" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2017-03-14 17:11:28 INFO 908 remaining\n" - ] - }, - { - "data": { - "text/plain": [ - "Experiment alm.biom with 526 samples, 908 features" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "alm_feces.cluster_features(min_abundance=10,inplace=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let's plot it with color bars showing the travel and diarrhea status of samples:" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "image/png": "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bGtdC/cgLz8/3z788MNyQd6xY8ds5cqVtnz5cissLLTMzEx7/vnnLSIiwv/ebN682ebPn28DBgyw7OxsM3P/70ybNs3eeOMNy8nJsRUrVljbtm2tSZMm9uCDD1pqamp9XWq9OF+DvJycHJs5c6b16NHD1q1bZ0888YRNnTrVioqK7PDhw/bee+9ZfHy89e/f3yIiIvyjO3Nzc23p0qXWv39/Gzp0qEVERFhkZKTNmjXLCgsLy30H3nnnnfbWW2/Z4cOHbdasWeW+Pyv6XCYnJ1e4b15e3nn3eSTIAwAAAAAAANAgBTtoycrKspEjR1qzZs3smWeesc8++8wmTpxod999t82bN8/WrFljzZo1szvuuMNeeukl27hxo40dO9aGDh1qqampFh0dbffcc4+9//77tnLlSuvdu7c9/fTTtmvXLps4caK1a9fOEhIS7ODBg6XOm5qaag8++KD16tXLUlJSbPbs2da5c2ebOXOmZWVl2YgRIyw6OtoSExNt5MiR1r17d8vKyrJPP/3UOnXqZI8++qh98sknNmXKFLvnnnvsgw8+sDlz5th9991nK1eutPXr11tcXJzFxMTYyZMn/ectLCwsd01LliypsC0zZsywtLS0Cq8xPj7evvrqK3v99detTZs2NnfuXFu5cqV169bN2rRpY0uWLKmyrbNnz7YOHTpU2da6Fu5BnpnZ9u3brUePHva3v/3N4uLibNGiRbZ3717/SDzf/w9dunSxjRs32rp16ywuLs4GDhxoK1assOjoaH8I+Mknn1jPnj1twYIFtmzZMmvTpo298sorlpiYaM8++6xFR0fb3r176/FqQ+t8DfL27t1rzzzzjMXHx9uRI0fslVdesZiYGPv666/9n5eWLVvamDFjbOPGjfbMM89YXFycHTp0yGbMmGHXX3+99ezZ0z755BObPHmyRUVF2eeff26bN2+2tm3b+j9Tr732mrVs2dKefvppS09PtwkTJli7du1s7ty5tnnz5go/lwMGDCi37/79+8/LzyNBHgAAAAAAAIAGKRRB3pgxY6xfv36Wk5NjZmaHDh2yCRMmWP/+/W358uXWuXNnW7hwoX//SZMm2bBhw2zLli02YMAAmzFjhpmZ5ebm2pw5cywuLs5OnDhR5dSax48ft5SUFMvIyLDTp09bYmKixcXFWXx8vBUWFtrOnTstNjbWIiIirEuXLrZ161b/yJioqChLS0uzEydO2I4dO+yZZ56xfv362cyZM61Nmzb2/vvv25EjR+zIkSO2b9++UtOA+oK8ktdUWVuGDh1a6TX26dPHEhMTbdCgQfbGG29YUVGRFRUV2fr16+3BBx+0hISEKts6Y8aMatta1wjynOzsbFuyZInFxsZWOJJp586dtn37djtz5ozt3LnThg0bZnFxcbZt2zYbNmyYxcfHW25urs2bN88efvhh27p1q40ePdp69+5thw4dsuzsbFu7dq317t3b5s2bV9+XGzLnY5BXUFBgH330kXXt2tVWrFhhp06dsoULF1rHjh1t9erVlpWVZWPHjrXHH3/c8vPz/d8vPXv2tC1bttjMmTOtV69eduTIETMz27p1qz3xxBM2e/ZsmzFjhkVHR/tH9+bk5Pgf2717d6npMqv6XJ44caLUvllZWefl55EgDwAAAAAAAECDFIog78UXX7QxY8ZYUVGRmbkbyrNnz7bevXvbwoULrVevXv4wrmyQ98QTT9iSJUtKPS8uLs6OHz9uq1atsp49e1pF7T9x4oQlJCTYHXfcYREREf4pLSdMmGCFhYWWl5dn8+bNs6ZNm9rAgQMtPz/fH+T59vdV06ZN7dFHH7WMjAybOnWq3XTTTRYREWGtWrWyuXPn2pkzZ/znLSwstFWrVpW6pqraUtU1bty40Z588klbvny5//ipqak2ZMgQmz17dqVtHTBggGVkZPinAa2srXUt3IO8goICO3r0qGVkZPg/62fOnLFPP/3U+vTpYw899JDt3bvXNm3aZN26dfO/Z02aNLG+ffva4cOHbfbs2dazZ0/btm2b//+bzMxMGzlyZLn3ukWLFjZx4sSwWXfvfAzyvvrqK3vppZfKvbc33XSTDR061DIyMmzSpEk2fPhwKyws9H+/+IK8WbNmWd++ff0/kti6dasNGTLEEhISbMaMGRYTE2MnTpwws+K17mJjY23Hjh2lvj9Pnz5d6eey7Hetb5Tg+fZ5JMgDAAAAAAAA0CCFIsgbO3asDRgwwE6dOmVmxeu+9e3b15YuXVoqjAs0yCsZmPn4bnZ36tTJli1bZgUFBZaRkWHjxo2z0aNHW0FBgW3evNnat29vLVu29E9d6RsN16NHD/8Il1OnTll6erpt3rzZsrKybO/evVZQUGAHDx60l19+2Tp06GCJiYnlzu27puraUl2Q169fP/+IPN9onC5dutjcuXPPuq11LdyDvBMnTti0adPs4Ycf9r8nZi7MW7x4sUVFRVlCQoL16dPHpkyZYrm5uXby5El77733/GFMUlKSxcTE2PDhw23QoEG2efNm/wjWwYMH+0dUnjhxwlJSUs7pqQwDdT4GeSkpKda7d2+bMGGCZWZm2oEDB2zHjh02ZcoUi46OtvXr19cqyJszZ469++671qNHD/vyyy/NzPw/XnjggQf8QV5MTIzt2bPHtm7dWunn0vdd69v3fP08EuQBAAAAAAAAaJBCtUZey5YtbeLEiXbgwAF79913rXXr1vbaa6/Z6tWrrXfv3lUGeYsXLzaz0iFXdna2rVy50rp06WLLly+3vLw8/znz8/Nt5cqV1qlTJ1uyZInt27fPpkyZYs2aNbMRI0bYrl277KmnnrK4uDjLzMy0119/3bp06WJbtmyxTZs2Wdu2bW3EiBF24MAB+9e//mUdOnSwF154waZPn2733XefrV271g4ePGhvv/22de7c2bZs2eI/ty9s811TdW3ZvHlzpde4b98+mzx5srVv395WrFhhq1evtvvvv9/uueceW758eZVtnTZtmnXo0KHKtta1cA/yfCOebr31VuvWrZtt2bLFMjMzbfny5da1a1eLi4uzdevWWY8ePWzSpEmWmZlps2bNsubNm1vv3r39U6BOmjTJrr/+euvfv7/l5eXZ6dOnbcGCBdaqVSubPXu2//1s166drV27tr4vO2TOtyAvLy/P5s6da1FRUbZjxw7/474pdDt27GijRo2yiRMnVhnkxcXF+de+9AV5ixcvtg0bNlirVq1s0KBBtmPHDps/f77dfvvt9thjj9k333xT6vtzw4YNlX4uDx065N93xYoVlp2dfV5+HgnyAAAAAAAAADRIoQjyRo0aZbfddpvdf//9FhERYS1btrTJkydbTk6OrVmzxuLi4mz//v3+/V966SUbPXq0paamWnx8vH9qyZIh18mTJ23Hjh0WExNjd999ty1YsKDUeTMyMmzYsGH+KeIiIyOtW7du1r59e3v++eetS5culpKSYmZmu3btskcffdT69etnX331la1YscIiIyMtIiLCmjdvbqNGjbLjx4/bgQMH7LnnnvNPJRcZGWkzZ86scI28ktdUWVu6du1q8+fPr/Qac3Jy7PDhwzZ+/HiLiIiwW2+91bp3727R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", - "text/html": [ - "\n", - "" - ] - }, - "metadata": { - "isWidgetSnapshot": true - }, - "output_type": "display_data" - }, - { - "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" - } - ], - "source": [ - "alm_feces.plot(sample_field='host_subject_id', gui='jupyter',sample_color_bars=['travel','diarrhea_donor_A', 'diarrhea_donor_B'], rect=[None, None, 113.0, 56.25]);" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "## Let's also look at the saliva samples" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "Experiment alm.biom with 285 samples, 7289 features" - ] - }, - "execution_count": 39, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "alm_saliva.sort_centroid(inplace=True, n=2)" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "image/png": "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hiz+7Zo1a2aZmZmWk5NjgwcPtmbNmtnixYtt4cKFNm3aNGvfvr29+OKLtmzZMisuLg7KOeDiQJAHAAAAAAAAAAgWgjycU1FRke3du9emT59uLVu2tOXLl9vQoUMtJibGPv/8c5s2bZo1adKkZCScz+ez9evXW9++fW3lypXm8/ls3759lpiYaDExMTZhwgRbuXKlFRYWlkzJ+cknn1hcXJy9++67tnTpUvvss88sLi7Oxo8fb4sWLbKDBw/a/v37beXKlbZkyRKbM2eOjRkzxuLj40umwVy+fLm1atXKMjMzraioyLKysiw2NtbGjBljc+fOtby8vJLt/IFfbm6uDR8+3Pr161cyleaJEycsJSXFWrVqZb169bJjx45V5+VHDUOQBwAAAAAAAAAIFoI8nNOhQ4ds6dKl1r59e3v22Wetf//+9sorr1ivXr0sPT3d5s+fb08++aQNHz7cPvroI9u5c6fl5uZaRkaG5eXl2d69e23s2LHWpk0b6927t4WHh1toaKglJyfb5s2brUuXLhYSEmJ9+/a1sLCwkn3369fPOnfubC1btrT58+dbRkaGhYWFWePGja1nz54WERFhbdq0sVGjRtnevXtLArotW7bY5s2brX///tapUyeLiIiwDh062NixY23//v3nDPLMzA4cOGDjx4+3Fi1a2L59+6rx6qOmOd8gb+fOnRYTE1OmFixYcF77J8gDAAAAAAAAAJgR5OE8fPXVV5aammr9+vWzkJAQmzBhgjVt2tTmzZtn2dnZtmPHDhsxYoR17NjROnToYF27drVhw4bZ/PnzLT8/33bv3m1jxoyx6dOnW05Oji1evNhef/11GzlypG3YsMFatWplERERtmXLFlu9erU1b97c2rZta1u2bLG0tDTr1q2b9e3b19avX2/Nmze3du3aWVpamn3++ec2Y8YMa926tSUkJNiyZcusRYsWlpqaapMnT7ZGjRrZ8uXLbfv27TZp0iRr1qyZrVy58ryCvMLCQouLi7NXX33Vtm3bVo1XHzVNZYK8rl272j333GP33HOPPfnkk0EN8oqKiqygoMDy8vIsLy/P9u/fb8ePH6/UPgAAAAAAAAAA1YsgD+e0f/9+mzt3roWFhVnz5s0tMjLSXnrpJZsxY4YdOHDADh8+bHv37rX169fbnDlzbMSIERYeHm4NGza02NhYy8/Pt2XLltmo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WrSo1q1bVytXrqz58+dv2ONpzZo1tXjx4lqwYEE9+eSTdeedd25YOnPdunW1fPnymj9/fr344ov19NNP19y5c+uKK66oH/zgB5v1O7Cv03nnnVdTp06tyy67rK677rq6/PLL6+67765rrrmmVq1aVVVtz76bb765brzxxnr++efr0UcfrRkzZtTkyZProosuqgULFtQLL7ywYYm5qVOn1pQpU2rGjBm1bNmyzZaSW79+/RZz2tpYvv3tb9fDDz+81TmuXr26HnrooZo5c2adf/75NW3atJo0aVIdf/zxdd9991VfX98bGuuO9ose5FW1atDHH3+8Zs6cWZMmTaqJEyfW+eefv6Fq8oUXXqglS5bU1KlT67zzzqsZM2bUnDlzavr06fXII49Uf39/rVixombNmlUPP/zwhnbXrl1bS5YsqQsuuKCmTJlS06dPH/Tf567m7RbkrVmzphYuXFi33HJLvfTSS5udG9gD9Jprrql77rmnFi5cWOvXr9/w/TJv3rxatWpVPfTQQ3XjjTfWunXrqqrqpz/9ad12223V29tbfX19tWLFirrssstq8uTJdeGFF9Ydd9xRzz//fFXVZt+fDzzwwDbfy5d/174d30dBHgAAAACwSxrsoOWJJ56oiRMnVk9PT7300ku1bt26zZbBHEzr16+vvr6+Df319/dv+IP39vT399eLL774imMdmMdr+aP16xnLs88+W9dee2319PTULbfcUrfddlt99atfrZEjR25RBbgjx/p6CfI26u/vrxdeeKHWrl273d9Lf39/9fX1varf0cB78/Lg5xfB2y3I21m29f3wcq/1vXw7vY+CPAAAAABglzTYQcvPfvazmj17dk2fPr36+/sHrZ+3o7Vr19Z3v/vd6unpqXHjxtXYsWPrtNNOq7lz5+60MPS1EOQxmAR5DCZBHgAAAACwSxrsoKWvr6+eeuqp+tGPfvSWXnbtzbJu3bp6/PHHa+HChXXXXXdVb2/vq64q3NkEeQwmQR6DSZAHAAAAAOySBC3sKII8BpMgj8EkyAMAAAAAdkmCFnYUQR6DSZDHYBLkAQAAAAC7JEELO4ogj8EkyGMwCfIAAAAAgF2SoIUdRZDHYBLkMZgEeQAAAADALknQwo6wdu3aWrFihSCPQbG190uQx46wtfcLAAAAAOBNd++99/7ZsmXL6sc//rHD8bqPFStW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", - "text/html": [ - "\n", - "" - ] - }, - "metadata": { - "isWidgetSnapshot": true - }, - "output_type": "display_data" - }, - { - "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 = $('