Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix two bugs related to changing taxonomic level in the barplot #126

Merged
merged 11 commits into from
Jul 26, 2019
29 changes: 19 additions & 10 deletions q2_taxa/assets/barplot/src/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { select } from 'd3';

import render from './render';
import {
availableColorSchemes,
addTaxaPicker,
addWidthSlider,
addColorPicker,
Expand All @@ -13,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');
Expand Down Expand Up @@ -48,20 +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);
addWidthSlider(ctrlRowOne, svgBar, data, dataMeta, state.barWidth);
}
4 changes: 2 additions & 2 deletions q2_taxa/assets/barplot/src/main.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import init from './init';
import { getBarWidth, getColorScheme } from './toolbar';


init(0);
init({ level: 0, colorScheme: getColorScheme(), barWidth: getBarWidth() });
10 changes: 1 addition & 9 deletions q2_taxa/assets/barplot/src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,16 @@ import {
axisBottom,
axisLeft,
format,
select,
} from 'd3';

import { setupXAxis, setupYAxis } from './axis';
import plotBars from './bar';
import { availableColorSchemes } from './toolbar';

export const transitionDur = 500;
export const defaultBarWidth = 10;

export default function render(svg, colorScheme, xOrdering, dataMeta) {
export default function render(svg, colorScheme, xOrdering, dataMeta, barWidth) {
const { sortMap, sortedSampleIDs } = xOrdering;
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;
}
const width = sortedSampleIDs.length * barWidth;
const height = 600;
const margin = { top: 20, left: 60, right: 0, bottom: 50 };
Expand Down
52 changes: 42 additions & 10 deletions q2_taxa/assets/barplot/src/toolbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { select } from 'd3';
import * as d3chromo from 'd3-scale-chromatic';

import init from './init';
// We have to do the imports this way to accommodate for render() being a
// "default export." See https://stackoverflow.com/a/33611943/10730311.
import render, { defaultBarWidth } from './render';
import render from './render';
import { sort } from './data';
import plotLegend from './legend';

Expand All @@ -29,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);
Expand All @@ -39,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) {
Expand Down Expand Up @@ -113,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)
Expand All @@ -132,25 +155,25 @@ export function addTaxaPicker(row, levels, selectedLevel) {
* This function was cobbled together from parts of code from
* addColorPicker(), addSortByPicker(), and _updateSort().
*/
export function addWidthSlider(row, svg, data, dataMeta) {
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', defaultBarWidth)
.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);
render(svg, svg.property('colorScheme'), xOrdering, dataMeta, getBarWidth());
});
return grp;
}

export function addColorPicker(row, svg, legendCol, data, dataMeta) {
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')
Expand All @@ -163,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);
});

Expand All @@ -190,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;
}

Expand Down