8000 Introducing histogram* bingroup attributes by etpinard · Pull Request #3845 · plotly/plotly.js · GitHub
[go: up one dir, main page]

Skip to content

Introducing histogram* bingroup attributes #3845

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

Merged
merged 11 commits into from
May 21, 2019
Prev Previous commit
Next Next commit
adapt calcAllAutoBins for new histogramBinOpts struct
  • Loading branch information
etpinard committed May 8, 2019
commit e0d9765a7c354a51ee3545e1d9a614b327f2b0e9
71 changes: 42 additions & 29 deletions src/traces/histogram/calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var normFunctions = require('./norm_functions');
var doAvg = require('./average');
var getBinSpanLabelRound = require('./bin_label_vals');

module.exports = function calc(gd, trace) {
function calc(gd, trace) {
var pos = [];
var size = [];
var pa = Axes.getFromId(gd, trace.orientation === 'h' ? trace.yaxis : trace.xaxis);
Expand Down Expand Up @@ -193,23 +193,30 @@ module.exports = function calc(gd, trace) {
}

return cd;
};
}

/*
* calcAllAutoBins: we want all histograms on the same axes to share bin specs
* if they're grouped or stacked. If the user has explicitly specified differing
* calcAllAutoBins: we want all histograms inside the same bingroup
* (see logic in Histogram.crossTraceDefaults) to share bin specs
*
* If the user has explicitly specified differing
* bin specs, there's nothing we can do, but if possible we will try to use the
* smallest bins of any of the auto values for all histograms grouped/stacked
* together.
* smallest bins of any of the auto values for all histograms inside the same
* bingroup.
*/
function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
var binAttr = mainData + 'bins';
var fullLayout = gd._fullLayout;
var groupName = trace['_' + mainData + 'bingroup'];
var binOpts = fullLayout._histogramBinOpts[groupName];
var isOverlay = fullLayout.barmode === 'overlay';
var i, traces, tracei, calendar, pos0, autoVals, cumulativeSpec;

var cleanBound = (pa.type === 'date') ?
function(v) { return (v || v === 0) ? Lib.cleanDate(v, null, pa.calendar) : null; } :
var r2c = function(v) { return pa.r2c(v, 0, calendar); };
var c2r = function(v) { return pa.c2r(v, 0, calendar); };

var cleanBound = pa.type === 'date' ?
function(v) { return (v || v === 0) ? Lib.cleanDate(v, null, calendar) : null; } :
function(v) { return isNumeric(v) ? Number(v) : null; };

function setBound(attr, bins, newBins) {
Expand All @@ -222,28 +229,29 @@ function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
}
}

var binOpts = fullLayout._histogramBinOpts[trace._groupName];

// all but the first trace in this group has already been marked finished
// clear this flag, so next time we run calc we will run autobin again
if(trace._autoBinFinished) {
10000 delete trace._autoBinFinished;
} else {
traces = binOpts.traces;
var sizeFound = binOpts.sizeFound;
var allPos = [];
autoVals = traces[0]._autoBin = {};

// Note: we're including `legendonly` traces here for autobin purposes,
// so that showing & hiding from the legend won't affect bins.
// But this complicates things a bit since those traces don't `calc`,
// hence `isFirstVisible`.
var isFirstVisible = true;
for(i = 0; i < traces.length; i++) {
tracei = traces[i];

if(tracei.visible) {
pos0 = tracei._pos0 = pa.makeCalcdata(tracei, mainData);
var mainDatai = binOpts.dirs[i];
pos0 = tracei['_' + mainDatai + 'pos0'] = pa.makeCalcdata(tracei, mainDatai);

allPos = Lib.concat(allPos, pos0);
delete tracei._autoBinFinished;

if(trace.visible === true) {
if(isFirstVisible) {
isFirstVisible = false;
Expand All @@ -254,10 +262,15 @@ function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
}
}
}

calendar = traces[0][mainData + 'calendar'];
var newBinSpec = Axes.autoBin(
allPos, pa, binOpts.nbins, false, calendar, sizeFound && binOpts.size);
var newBinSpec = Axes.autoBin(allPos, pa, binOpts.nbins, false, calendar, binOpts.sizeFound && binOpts.size);

var autoBin = traces[0]._autoBin = {};
autoVals = autoBin[binOpts.dirs[0]] = {};

// TODO how does work with bingroup ????
//
// Edge case: single-valued histogram overlaying others
// Use them all together to calculate the bin size for the single-valued one
if(isOverlay && newBinSpec._dataSpan === 0 &&
Expand All @@ -274,20 +287,16 @@ function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
cumulativeSpec = tracei.cumulative;
if(cumulativeSpec.enabled && (cumulativeSpec.currentbin !== 'include')) {
if(cumulativeSpec.direction === 'decreasing') {
newBinSpec.start = pa.c2r(Axes.tickIncrement(
pa.r2c(newBinSpec.start, 0, calendar),
newBinSpec.size, true, calendar
));
newBinSpec.start = c2r(Axes.tickIncrement(
r2c(newBinSpec.start), newBinSpec.size, true, calendar));
} else {
newBinSpec.end = pa.c2r(Axes.tickIncrement(
pa.r2c(newBinSpec.end, 0, calendar),
newBinSpec.size, false, calendar
));
newBinSpec.end = c2r(Axes.tickIncrement(
r2c(newBinSpec.end), newBinSpec.size, false, calendar));
}
}

binOpts.size = newBinSpec.size;
if(!sizeFound) {
if(!binOpts.sizeFound) {
autoVals.size = newBinSpec.size;
Lib.nestedProperty(traces[0], binAttr + '.size').set(newBinSpec.size);
}
Expand All @@ -296,8 +305,8 @@ function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
setBound('end', binOpts, newBinSpec);
}

pos0 = trace._pos0;
delete trace._pos0;
pos0 = trace['_' + mainData + 'pos0'];
delete trace['_' + mainData + 'pos0'];

// Each trace can specify its own start/end, or if omitted
// we ensure they're beyond the bounds of this trace's data,
Expand Down Expand Up @@ -390,7 +399,7 @@ function handleSingleValueOverlays(gd, trace, pa, mainData, binAttr) {
// so we can use this result when we get to tracei in the normal
// course of events, mark it as done and put _pos0 back
tracei._autoBinFinished = 1;
tracei._pos0 = resulti[1];
tracei['_' + mainData + 'pos0'] = resulti[1];

if(isSingleValued) {
singleValuedTraces.push(tracei);
Expand All @@ -404,7 +413,7 @@ function handleSingleValueOverlays(gd, trace, pa, mainData, binAttr) {
// hunt through pos0 for the first valid value
var dataVals = new Array(singleValuedTraces.length);
for(i = 0; i < singleValuedTraces.length; i++) {
var pos0 = singleValuedTraces[i]._pos0;
var pos0 = singleValuedTraces[i]['_' + mainData + 'pos0'];
for(var j = 0; j < pos0.length; j++) {
if(pos0[j] !== undefined) {
dataVals[i] = pos0[j];
Expand Down Expand Up @@ -462,7 +471,6 @@ function getConnectedHistograms(gd, trace) {
return out;
}


function cdf(size, direction, currentBin) {
var i, vi, prevSum;

Expand Down Expand Up @@ -510,3 +518,8 @@ function cdf(size, direction, currentBin) {
}
}
}

module.exports = {
calc: calc,
calcAllAutoBins: calcAllAutoBins
};
2 changes: 1 addition & 1 deletion src/traces/histogram/index.js
8000
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module.exports = {
supplyDefaults: require('./defaults'),
crossTraceDefaults: require('./cross_trace_defaults'),
supplyLayoutDefaults: require('../bar/layout_defaults'),
calc: require('./calc'),
calc: require('./calc').calc,
crossTraceCalc: require('../bar/cross_trace_calc').crossTraceCalc,
plot: require('../bar/plot'),
layerName: 'barlayer',
Expand Down
2 changes: 1 addition & 1 deletion test/jasmine/tests/histogram_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ var setConvert = require('@src/plots/cartesian/set_convert');
var supplyDefaults = require('@src/traces/histogram/defaults');
var supplyDefaults2D = require('@src/traces/histogram2d/defaults');
var supplyDefaults2DC = require('@src/traces/histogram2dcontour/defaults');
var calc = require('@src/traces/histogram/calc');
var calc = require('@src/traces/histogram/calc').calc;
var getBinSpanLabelRound = require('@src/traces/histogram/bin_label_vals');

var createGraphDiv = require('../assets/create_graph_div');
Expand Down
0