[med-svn] [Git][med-team/q2-taxa][upstream] New upstream version 2019.7.0
Liubov Chuprikova
gitlab at salsa.debian.org
Sat Sep 7 13:40:40 BST 2019
Liubov Chuprikova pushed to branch upstream at Debian Med / q2-taxa
Commits:
7dcaa182 by Liubov Chuprikova at 2019-09-07T12:38:55Z
New upstream version 2019.7.0
- - - - -
7 changed files:
- 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:
=====================================
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/commit/7dcaa18249458a0daad64575294555317d24d3be
--
View it on GitLab: https://salsa.debian.org/med-team/q2-taxa/commit/7dcaa18249458a0daad64575294555317d24d3be
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/77c964e3/attachment-0001.html>
More information about the debian-med-commit
mailing list