[med-svn] [Git][med-team/q2-taxa][master] 3 commits: New upstream version 2019.7.0

Liubov Chuprikova gitlab at salsa.debian.org
Sat Sep 7 13:40:35 BST 2019



Liubov Chuprikova pushed to branch master at Debian Med / q2-taxa


Commits:
7dcaa182 by Liubov Chuprikova at 2019-09-07T12:38:55Z
New upstream version 2019.7.0
- - - - -
ca2edc39 by Liubov Chuprikova at 2019-09-07T12:38:57Z
Update upstream source from tag 'upstream/2019.7.0'

Update to upstream version '2019.7.0'
with Debian dir 3c42721d7dd4d5418db2b17c0c64a92bc5cde571
- - - - -
8ce6fc42 by Liubov Chuprikova at 2019-09-07T12:40:10Z
New upstream version

- - - - -


8 changed files:

- debian/changelog
- q2_taxa/_version.py
- q2_taxa/_visualizer.py
- q2_taxa/assets/barplot/src/init.js
- q2_taxa/assets/barplot/src/main.js
- q2_taxa/assets/barplot/src/render.js
- q2_taxa/assets/barplot/src/toolbar.js
- q2_taxa/tests/test_visualizer.py


Changes:

=====================================
debian/changelog
=====================================
@@ -1,3 +1,9 @@
+q2-taxa (2019.7.0-1) UNRELEASED; urgency=medium
+
+  * New upstream version
+
+ -- Liubov Chuprikova <chuprikovalv at gmail.com>  Sat, 07 Sep 2019 14:39:31 +0200
+
 q2-taxa (2019.4.0-1) unstable; urgency=medium
 
   * Initial release (Closes: #932050)


=====================================
q2_taxa/_version.py
=====================================
@@ -23,9 +23,9 @@ def get_keywords():
     # setup.py/versioneer.py will grep for the variable names, so they must
     # each be defined on a line of their own. _version.py will just call
     # get_keywords().
-    git_refnames = " (tag: 2019.4.0)"
-    git_full = "b68f7f2cf216a6dd942c115337a4c0eaeda84006"
-    git_date = "2019-05-03 04:14:42 +0000"
+    git_refnames = " (tag: 2019.7.0)"
+    git_full = "bc018fe8540f9f0fb4f4cf6729d840a53f5d8c31"
+    git_date = "2019-07-30 18:15:55 +0000"
     keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
     return keywords
 


=====================================
q2_taxa/_visualizer.py
=====================================
@@ -24,6 +24,11 @@ TEMPLATES = pkg_resources.resource_filename('q2_taxa', 'assets')
 
 def barplot(output_dir: str, table: pd.DataFrame, taxonomy: pd.Series,
             metadata: Metadata) -> None:
+    ids_not_in_metadata = set(table.index) - set(metadata.ids)
+    if ids_not_in_metadata:
+        raise ValueError('Feature IDs found in the table are missing in the '
+                         f'metadata: {ids_not_in_metadata!r}.')
+
     metadata = metadata.to_dataframe()
     jsonp_files, csv_files = [], []
     collapsed_tables = _extract_to_level(taxonomy, table)


=====================================
q2_taxa/assets/barplot/src/init.js
=====================================
@@ -2,8 +2,8 @@ import { select } from 'd3';
 
 import render from './render';
 import {
-  availableColorSchemes,
   addTaxaPicker,
+  addWidthSlider,
   addColorPicker,
   addSortByPicker,
   addDownloadLinks,
@@ -12,9 +12,20 @@ import { setupData, sort } from './data';
 import plotLegend from './legend';
 
 
-export default function init(level) {
+/* Re-initializes the display.
+ *
+ * "state" is an object that should contain the following entries:
+ *
+ * level -- an integer indicating the currently selected index in the
+ *          "Taxonomic Level" dropdown (starts at 0)
+ *
+ * colorScheme -- the name of the current color scheme
+ *
+ * barWidth -- an integer indicating the currently selected bar width value
+ */
+export default function init(state) {
   /* global d */
-  const data = d[level].data;
+  const data = d[state.level].data;
 
   // DOM
   const body = select('body .container-fluid');
@@ -47,19 +58,19 @@ export default function init(level) {
     .style('font', '12px sans-serif')
     .text('Sample');
 
-  const initialColorScheme = availableColorSchemes[0].name;
-  const dataMeta = setupData(d[level], svgBar);
+  const dataMeta = setupData(d[state.level], svgBar);
   const { sortedKeysReverse, levels } = dataMeta;
 
   const initialSort = sort(data, [sortedKeysReverse[0]], ['Ascending'], [false], dataMeta);
-  const chartInfo = render(svgBar, initialColorScheme, initialSort, dataMeta);
+  const chartInfo = render(svgBar, state.colorScheme, initialSort, dataMeta, state.barWidth);
 
   plotLegend(legendCol, chartInfo);
 
   // Controls
   const ctrlRowOne = controls.append('div').attr('class', 'row');
-  addDownloadLinks(ctrlRowOne, svgBar, legendCol.select('svg'), level + 1);
-  addTaxaPicker(ctrlRowOne, levels, level + 1);
-  addColorPicker(ctrlRowOne, svgBar, legendCol, data, dataMeta);
+  addDownloadLinks(ctrlRowOne, svgBar, legendCol.select('svg'), state.level + 1);
+  addTaxaPicker(ctrlRowOne, levels, state.level + 1);
+  addColorPicker(ctrlRowOne, svgBar, legendCol, data, dataMeta, state.colorScheme);
   addSortByPicker(ctrlRowOne, svgBar, data, dataMeta);
+  addWidthSlider(ctrlRowOne, svgBar, data, dataMeta, state.barWidth);
 }


=====================================
q2_taxa/assets/barplot/src/main.js
=====================================
@@ -1,4 +1,4 @@
 import init from './init';
+import { getBarWidth, getColorScheme } from './toolbar';
 
-
-init(0);
+init({ level: 0, colorScheme: getColorScheme(), barWidth: getBarWidth() });


=====================================
q2_taxa/assets/barplot/src/render.js
=====================================
@@ -14,9 +14,9 @@ import { availableColorSchemes } from './toolbar';
 
 export const transitionDur = 500;
 
-export default function render(svg, colorScheme, xOrdering, dataMeta) {
+export default function render(svg, colorScheme, xOrdering, dataMeta, barWidth) {
   const { sortMap, sortedSampleIDs } = xOrdering;
-  const width = sortedSampleIDs.length * 10;
+  const width = sortedSampleIDs.length * barWidth;
   const height = 600;
   const margin = { top: 20, left: 60, right: 0, bottom: 50 };
   const { keys } = dataMeta;


=====================================
q2_taxa/assets/barplot/src/toolbar.js
=====================================
@@ -27,7 +27,30 @@ export const availableColorSchemes = [
   { name: 'Spectral', scheme: d3chromo.interpolateSpectral, type: 's' },
 ];
 
+export const defaultBarWidth = 10;
+
 // HELPERS
+export function getBarWidth() {
+  let barWidth = defaultBarWidth;
+  // This line derived from https://stackoverflow.com/a/20154105/10730311.
+  const slider = select('#barWidthSlider').node();
+  if (slider !== null && slider !== undefined) {
+    barWidth = slider.value;
+  }
+  return barWidth;
+}
+
+export function getColorScheme() {
+  // this is just how initialColorScheme was set in init() -- default to the
+  // first listed color scheme (currently, this is schemeAccent)
+  let scheme = availableColorSchemes[0].name;
+  const sel = select('#colorPickerSelect').node();
+  if (sel !== null && sel !== undefined) {
+    scheme = sel.value;
+  }
+  return scheme;
+}
+
 function _getSort(sel, svg, data, dataMeta) {
   const sorts = sel.selectAll('.xCtrl').nodes().map(d => d.options[d.selectedIndex].value);
   const orders = sel.selectAll('.xOrder').nodes().map(d => d.options[d.selectedIndex].value);
@@ -37,7 +60,7 @@ function _getSort(sel, svg, data, dataMeta) {
 
 function _updateSort(sel, svg, data, dataMeta) {
   const xOrdering = _getSort(sel, svg, data, dataMeta);
-  render(svg, svg.property('colorScheme'), xOrdering, dataMeta);
+  render(svg, svg.property('colorScheme'), xOrdering, dataMeta, getBarWidth());
 }
 
 function _appendSortByPicker(sel, svg, data, dataMeta) {
@@ -111,9 +134,11 @@ export function addTaxaPicker(row, levels, selectedLevel) {
   grp.append('select')
     .attr('class', 'form-control')
     .on('change', function appendTaxaPicker() {
+      const currBarWidth = getBarWidth();
+      const currColorScheme = getColorScheme();
       const container = select('.container-fluid');
       container.select('.viz.row').remove();
-      init(this.selectedIndex);
+      init({ level: this.selectedIndex, colorScheme: currColorScheme, barWidth: currBarWidth });
     })
     .selectAll('option')
     .data(levels)
@@ -125,7 +150,30 @@ export function addTaxaPicker(row, levels, selectedLevel) {
   return grp;
 }
 
-export function addColorPicker(row, svg, legendCol, data, dataMeta) {
+/* Adds a slider to let users control the width of the barplot's bars.
+ *
+ * This function was cobbled together from parts of code from
+ * addColorPicker(), addSortByPicker(), and _updateSort().
+ */
+export function addWidthSlider(row, svg, data, dataMeta, currentValue) {
+  const grp = row.append('div').attr('class', 'col-lg-2 form-group widthSlider');
+  grp.append('label').text('Bar Width');
+  grp.append('input')
+    .attr('type', 'range')
+    .attr('id', 'barWidthSlider')
+    .attr('min', '10')
+    .attr('max', '80')
+    .attr('value', currentValue)
+    .attr('class', 'form-control')
+    .style('padding', '0px')
+    .on('input', () => {
+      const xOrdering = _getSort(row, svg, data, dataMeta);
+      render(svg, svg.property('colorScheme'), xOrdering, dataMeta, getBarWidth());
+    });
+  return grp;
+}
+
+export function addColorPicker(row, svg, legendCol, data, dataMeta, currentValue) {
   const grp = row.append('div').attr('class', 'col-lg-2 form-group colorPicker');
   grp.append('label').text('Color Palette');
   grp.append('a')
@@ -138,10 +186,11 @@ export function addColorPicker(row, svg, legendCol, data, dataMeta) {
       .attr('class', 'glyphicon glyphicon-info-sign');
   const sel = grp.append('select')
     .attr('class', 'form-control')
+    .attr('id', 'colorPickerSelect')
     .on('change', function changeColorPicker() {
       const colorScheme = this.options[this.selectedIndex].value;
       const xOrdering = _getSort(row, svg, data, dataMeta);
-      const chartInfo = render(svg, colorScheme, xOrdering, dataMeta);
+      const chartInfo = render(svg, colorScheme, xOrdering, dataMeta, getBarWidth());
       plotLegend(legendCol, chartInfo);
     });
 
@@ -165,6 +214,14 @@ export function addColorPicker(row, svg, legendCol, data, dataMeta) {
     .attr('value', d => d.name)
     .text(d => d.name);
 
+  // Set the selected color scheme
+  // (useful if init() is called after the user has been playing with the
+  // visualization -- for example, when the taxonomic level is adjusted)
+  //
+  // Also, note that we have to use .property() instead of .attr() here. See
+  // https://stackoverflow.com/a/28933863/10730311 for context.
+  sel.property('value', currentValue);
+
   return grp;
 }
 


=====================================
q2_taxa/tests/test_visualizer.py
=====================================
@@ -18,21 +18,47 @@ from q2_taxa import barplot
 
 class BarplotTests(unittest.TestCase):
 
+    def setUp(self):
+        self.table = pd.DataFrame([[2.0, 2.0], [1.0, 1.0], [9.0, 8.0],
+                                  [0.0, 4.0]],
+                                  index=['A', 'B', 'C', 'D'],
+                                  columns=['feat1', 'feat2'])
+        self.taxonomy = pd.Series(['a; b; c', 'a; b; d'],
+                                  index=['feat1', 'feat2'])
+
     def test_barplot(self):
-        table = pd.DataFrame([[2.0, 2.0], [1.0, 1.0], [9.0, 8.0], [0.0, 4.0]],
-                             index=['A', 'B', 'C', 'D'],
-                             columns=['feat1', 'feat2'])
-        taxonomy = pd.Series(['a; b; c', 'a; b; d'],
-                             index=['feat1', 'feat2'])
         metadata = qiime2.Metadata(
             pd.DataFrame({'val1': ['1.0', '2.0', '3.0', '4.0']},
                          index=pd.Index(['A', 'B', 'C', 'D'], name='id')))
 
         with tempfile.TemporaryDirectory() as output_dir:
-            barplot(output_dir, table, taxonomy, metadata)
+            barplot(output_dir, self.table, self.taxonomy, metadata)
             index_fp = os.path.join(output_dir, 'index.html')
             self.assertTrue(os.path.exists(index_fp))
             self.assertTrue("src='level-1.jsonp?callback=load_data'" in
                             open(index_fp).read())
             csv_lvl3_fp = os.path.join(output_dir, 'level-3.csv')
             self.assertTrue(os.path.exists(csv_lvl3_fp))
+
+    def test_barplot_metadata_extra_id(self):
+        metadata = qiime2.Metadata(
+            pd.DataFrame({'val1': ['1.0', '2.0', '3.0', '4.0', '5.0']},
+                         index=pd.Index(['A', 'B', 'C', 'D', 'E'], name='id')))
+
+        with tempfile.TemporaryDirectory() as output_dir:
+            barplot(output_dir, self.table, self.taxonomy, metadata)
+            index_fp = os.path.join(output_dir, 'index.html')
+            self.assertTrue(os.path.exists(index_fp))
+            self.assertTrue("src='level-1.jsonp?callback=load_data'" in
+                            open(index_fp).read())
+            csv_lvl3_fp = os.path.join(output_dir, 'level-3.csv')
+            self.assertTrue(os.path.exists(csv_lvl3_fp))
+
+    def test_barplot_metadata_missing_id(self):
+        metadata = qiime2.Metadata(
+            pd.DataFrame({'val1': ['1.0', '2.0', '3.0']},
+                         index=pd.Index(['A', 'B', 'C'], name='id')))
+
+        with tempfile.TemporaryDirectory() as output_dir:
+            with self.assertRaisesRegex(ValueError, 'missing.*D'):
+                barplot(output_dir, self.table, self.taxonomy, metadata)



View it on GitLab: https://salsa.debian.org/med-team/q2-taxa/compare/2b28f2e0ddb039d262672322968b30643e120383...8ce6fc42fb9d44851033050607784b6d19323bdc

-- 
View it on GitLab: https://salsa.debian.org/med-team/q2-taxa/compare/2b28f2e0ddb039d262672322968b30643e120383...8ce6fc42fb9d44851033050607784b6d19323bdc
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20190907/f96cd3d1/attachment-0001.html>


More information about the debian-med-commit mailing list