Skip to content

Commit 0b7cde1

Browse files
authored
Merge pull request #3935 from plotly/single-value-overlay-histogram
More single-value overlaid histogram fixes
2 parents 34af401 + 9faab6c commit 0b7cde1

File tree

2 files changed

+80
-10
lines changed

2 files changed

+80
-10
lines changed

src/traces/histogram/calc.js

+17-10
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,6 @@ function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
291291
}
292292
}
293293

294-
// TODO how does work with bingroup ????
295-
// - https://github.com/plotly/plotly.js/issues/3881
296-
//
297294
// Edge case: single-valued histogram overlaying others
298295
// Use them all together to calculate the bin size for the single-valued one
299296
if(isOverlay && !Registry.traceIs(trace, '2dMap') && newBinSpec._dataSpan === 0 &&
@@ -398,22 +395,27 @@ function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
398395
* Returns the binSpec for the trace that sparked all this
399396
*/
400397
function handleSingleValueOverlays(gd, trace, pa, mainData, binAttr) {
398+
var fullLayout = gd._fullLayout;
401399
var overlaidTraceGroup = getConnectedHistograms(gd, trace);
402400
var pastThisTrace = false;
403401
var minSize = Infinity;
404402
var singleValuedTraces = [trace];
405-
var i, tracei;
403+
var i, tracei, binOpts;
406404

407405
// first collect all the:
408406
// - min bin size from all multi-valued traces
409407
// - single-valued traces
410408
for(i = 0; i < overlaidTraceGroup.length; i++) {
411409
tracei = overlaidTraceGroup[i];
412-
if(tracei === trace) pastThisTrace = true;
413-
else if(!pastThisTrace) {
414-
// This trace has already had its autobins calculated
415-
// (so must not have been single-valued).
416-
minSize = Math.min(minSize, tracei[binAttr].size);
410+
411+
if(tracei === trace) {
412+
pastThisTrace = true;
413+
} else if(!pastThisTrace) {
414+
// This trace has already had its autobins calculated, so either:
415+
// - it is part of a bingroup
416+
// - it is NOT a single-valued trace
417+
binOpts = fullLayout._histogramBinOpts[tracei['_' + mainData + 'bingroup']];
418+
minSize = Math.min(minSize, binOpts.size || tracei[binAttr].size);
417419
} else {
418420
var resulti = calcAllAutoBins(gd, tracei, pa, mainData, true);
419421
var binSpeci = resulti[0];
@@ -456,11 +458,16 @@ function handleSingleValueOverlays(gd, trace, pa, mainData, binAttr) {
456458
tracei = singleValuedTraces[i];
457459
var calendar = tracei[mainData + 'calendar'];
458460

459-
tracei._input[binAttr] = tracei[binAttr] = {
461+
var newBins = {
460462
start: pa.c2r(dataVals[i] - minSize / 2, 0, calendar),
461463
end: pa.c2r(dataVals[i] + minSize / 2, 0, calendar),
462464
size: minSize
463465
};
466+
467+
tracei._input[binAttr] = tracei[binAttr] = newBins;
468+
469+
binOpts = fullLayout._histogramBinOpts[tracei['_' + mainData + 'bingroup']];
470+
if(binOpts) Lib.extendFlat(binOpts, newBins);
464471
}
465472

466473
return trace[binAttr];

test/jasmine/tests/histogram_test.js

+63
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var Plotly = require('@lib/index');
2+
var Plots = require('@src/plots/plots');
23
var Lib = require('@src/lib');
34
var setConvert = require('@src/plots/cartesian/set_convert');
45

@@ -693,6 +694,14 @@ describe('Test histogram', function() {
693694
]);
694695
});
695696

697+
it('handles multiple single-valued overlaid autobinned traces', function() {
698+
var out = _calc({x: [1]}, [{x: [1]}], {barmode: 'overlay'}, true);
699+
700+
expect(out).toEqual([
701+
{p: 1, s: 1, b: 0, pts: [0], ph1: 1, ph0: 1, width1: 1, i: 0}
702+
]);
703+
});
704+
696705
it('handles multiple single-valued overlaid autobinned traces with different values', function() {
697706
var out = _calc({x: [null, 13, '', 13]}, [
698707
{x: [5]},
@@ -752,6 +761,60 @@ describe('Test histogram', function() {
752761
]);
753762
});
754763

764+
// from issue #3881
765+
it('handle single-value edge case 1', function() {
766+
var gd = {
767+
data: [
768+
{uid: 'a', type: 'histogram', y: [1]},
769+
{uid: 'b', type: 'histogram', y: [2]},
770+
771+
{uid: 'c', type: 'histogram', y: [1], xaxis: 'x2'},
772+
{uid: 'd', type: 'histogram', y: [3], xaxis: 'x2'},
773+
774+
{uid: 'e', type: 'histogram', y: [3]},
775+
{uid: 'f', type: 'histogram', y: [2], xaxis: 'x2'},
776+
777+
{uid: 'g', type: 'histogram', x: [1]},
778+
{uid: 'h', type: 'histogram', x: [2], yaxis: 'y2'},
779+
{uid: 'i', type: 'histogram', x: [2]}
780+
],
781+
layout: {barmode: 'overlay'}
782+
};
783+
supplyAllDefaults(gd);
784+
Plots.doCalcdata(gd);
785+
786+
var allBinOpts = gd._fullLayout._histogramBinOpts;
787+
var groups = Object.keys(allBinOpts);
788+
expect(groups).toEqual(
789+
['a__y', 'b__y', 'c__y', 'd__y', 'e__y', 'f__y', 'g__x', 'h__x', 'i__x'],
790+
'bin groups'
791+
);
792+
});
793+
794+
// from issue #3881
795+
it('handle single-value edge case 2', function() {
796+
var gd = {
797+
data: [
798+
{bingroup: '1', type: 'histogram', y: [1]},
799+
{uid: 'b', type: 'histogram', y: [2]},
800+
{bingroup: '2', type: 'histogram', y: [1], xaxis: 'x2'},
801+
{bingroup: '1', type: 'histogram', y: [3], xaxis: 'x2'},
802+
{bingroup: '2', type: 'histogram', y: [3]},
803+
{uid: 'f', type: 'histogram', y: [2], xaxis: 'x2'},
804+
{bingroup: '3', type: 'histogram', x: [1]},
805+
{bingroup: '1', type: 'histogram', x: [2], yaxis: 'y2'},
806+
{bingroup: '3', type: 'histogram', x: [2]}
807+
],
808+
layout: {barmode: 'overlay'}
809+
};
810+
supplyAllDefaults(gd);
811+
Plots.doCalcdata(gd);
812+
813+
var allBinOpts = gd._fullLayout._histogramBinOpts;
814+
var groups = Object.keys(allBinOpts);
815+
expect(groups).toEqual(['1', '2', '3', 'b__y', 'f__y'], 'bin groups');
816+
});
817+
755818
function calcPositions(opts, extraTraces, prepend) {
756819
return _calc(opts, extraTraces, {}, prepend).map(function(v) { return v.p; });
757820
}

0 commit comments

Comments
 (0)