Skip to content

Commit efa1275

Browse files
authoredFeb 27, 2018
Merge pull request #2413 from plotly/hist-fix
Fix yet another histogram edge case
2 parents e0e3ee1 + 619b26d commit efa1275

File tree

5 files changed

+54
-34
lines changed

5 files changed

+54
-34
lines changed
 

‎src/plots/cartesian/axes.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ axes.autoBin = function(data, ax, nbins, is2d, calendar) {
568568
start: dataMin - 0.5,
569569
end: dataMax + 0.5,
570570
size: 1,
571-
_count: dataMax - dataMin + 1
571+
_dataSpan: dataMax - dataMin,
572572
};
573573
}
574574

@@ -648,7 +648,7 @@ axes.autoBin = function(data, ax, nbins, is2d, calendar) {
648648
start: ax.c2r(binStart, 0, calendar),
649649
end: ax.c2r(binEnd, 0, calendar),
650650
size: dummyAx.dtick,
651-
_count: bincount
651+
_dataSpan: dataMax - dataMin
652652
};
653653
};
654654

‎src/traces/histogram/calc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ function calcAllAutoBins(gd, trace, pa, mainData, _overlayEdgeCase) {
253253

254254
// Edge case: single-valued histogram overlaying others
255255
// Use them all together to calculate the bin size for the single-valued one
256-
if(isOverlay && binSpec._count === 1 && pa.type !== 'category') {
256+
if(isOverlay && binSpec._dataSpan === 0 && pa.type !== 'category') {
257257
// Several single-valued histograms! Stop infinite recursion,
258258
// just return an extra flag that tells handleSingleValueOverlays
259259
// to sort out this trace too

‎test/jasmine/tests/axes_test.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -2369,7 +2369,7 @@ describe('Test axes', function() {
23692369
start: -0.5,
23702370
end: 2.5,
23712371
size: 1,
2372-
_count: 3
2372+
_dataSpan: 2
23732373
});
23742374
});
23752375

@@ -2383,7 +2383,7 @@ describe('Test axes', function() {
23832383
start: undefined,
23842384
end: undefined,
23852385
size: 2,
2386-
_count: NaN
2386+
_dataSpan: NaN
23872387
});
23882388
});
23892389

@@ -2397,7 +2397,7 @@ describe('Test axes', function() {
23972397
start: undefined,
23982398
end: undefined,
23992399
size: 2,
2400-
_count: NaN
2400+
_dataSpan: NaN
24012401
});
24022402
});
24032403

@@ -2411,7 +2411,7 @@ describe('Test axes', function() {
24112411
start: undefined,
24122412
end: undefined,
24132413
size: 2,
2414-
_count: NaN
2414+
_dataSpan: NaN
24152415
});
24162416
});
24172417

@@ -2425,7 +2425,7 @@ describe('Test axes', function() {
24252425
start: 0.5,
24262426
end: 4.5,
24272427
size: 1,
2428-
_count: 4
2428+
_dataSpan: 3
24292429
});
24302430
});
24312431

@@ -2443,7 +2443,7 @@ describe('Test axes', function() {
24432443
start: -0.5,
24442444
end: 5.5,
24452445
size: 2,
2446-
_count: 3
2446+
_dataSpan: 3
24472447
});
24482448
});
24492449
});

‎test/jasmine/tests/histogram2d_test.js

+16-16
Original file line numberDiff line numberDiff line change
@@ -191,42 +191,42 @@ describe('Test histogram2d', function() {
191191
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4,
192192
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4];
193193
Plotly.newPlot(gd, [{type: 'histogram2d', x: x1, y: y1}]);
194-
expect(gd._fullData[0].xbins).toEqual({start: 0.5, end: 4.5, size: 1, _count: 4});
195-
expect(gd._fullData[0].ybins).toEqual({start: 0.5, end: 4.5, size: 1, _count: 4});
194+
expect(gd._fullData[0].xbins).toEqual({start: 0.5, end: 4.5, size: 1, _dataSpan: 3});
195+
expect(gd._fullData[0].ybins).toEqual({start: 0.5, end: 4.5, size: 1, _dataSpan: 3});
196196
expect(gd._fullData[0].autobinx).toBe(true);
197197
expect(gd._fullData[0].autobiny).toBe(true);
198198

199199
// same range but fewer samples increases sizes
200200
Plotly.restyle(gd, {x: [[1, 3, 4]], y: [[1, 2, 4]]});
201-
expect(gd._fullData[0].xbins).toEqual({start: -0.5, end: 5.5, size: 2, _count: 3});
202-
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 5.5, size: 2, _count: 3});
201+
expect(gd._fullData[0].xbins).toEqual({start: -0.5, end: 5.5, size: 2, _dataSpan: 3});
202+
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 5.5, size: 2, _dataSpan: 3});
203203
expect(gd._fullData[0].autobinx).toBe(true);
204204
expect(gd._fullData[0].autobiny).toBe(true);
205205

206206
// larger range
207207
Plotly.restyle(gd, {x: [[10, 30, 40]], y: [[10, 20, 40]]});
208-
expect(gd._fullData[0].xbins).toEqual({start: -0.5, end: 59.5, size: 20, _count: 3});
209-
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 59.5, size: 20, _count: 3});
208+
expect(gd._fullData[0].xbins).toEqual({start: -0.5, end: 59.5, size: 20, _dataSpan: 30});
209+
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 59.5, size: 20, _dataSpan: 30});
210210
expect(gd._fullData[0].autobinx).toBe(true);
211211
expect(gd._fullData[0].autobiny).toBe(true);
212212

213213
// explicit changes to bin settings
214214
Plotly.restyle(gd, 'xbins.start', 12);
215-
expect(gd._fullData[0].xbins).toEqual({start: 12, end: 59.5, size: 20, _count: 3});
216-
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 59.5, size: 20, _count: 3});
215+
expect(gd._fullData[0].xbins).toEqual({start: 12, end: 59.5, size: 20, _dataSpan: 30});
216+
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 59.5, size: 20, _dataSpan: 30});
217217
expect(gd._fullData[0].autobinx).toBe(false);
218218
expect(gd._fullData[0].autobiny).toBe(true);
219219

220220
Plotly.restyle(gd, {'ybins.end': 12, 'ybins.size': 3});
221-
expect(gd._fullData[0].xbins).toEqual({start: 12, end: 59.5, size: 20, _count: 3});
222-
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 12, size: 3, _count: 3});
221+
expect(gd._fullData[0].xbins).toEqual({start: 12, end: 59.5, size: 20, _dataSpan: 30});
222+
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 12, size: 3, _dataSpan: 30});
223223
expect(gd._fullData[0].autobinx).toBe(false);
224224
expect(gd._fullData[0].autobiny).toBe(false);
225225

226226
// restart autobin
227227
Plotly.restyle(gd, {autobinx: true, autobiny: true});
228-
expect(gd._fullData[0].xbins).toEqual({start: -0.5, end: 59.5, size: 20, _count: 3});
229-
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 59.5, size: 20, _count: 3});
228+
expect(gd._fullData[0].xbins).toEqual({start: -0.5, end: 59.5, size: 20, _dataSpan: 30});
229+
expect(gd._fullData[0].ybins).toEqual({start: -0.5, end: 59.5, size: 20, _dataSpan: 30});
230230
expect(gd._fullData[0].autobinx).toBe(true);
231231
expect(gd._fullData[0].autobiny).toBe(true);
232232
});
@@ -239,15 +239,15 @@ describe('Test histogram2d', function() {
239239
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4,
240240
1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4];
241241
Plotly.newPlot(gd, [{type: 'histogram2d', x: x1, y: y1, autobinx: false, autobiny: false}]);
242-
expect(gd._fullData[0].xbins).toEqual({start: 0.5, end: 4.5, size: 1, _count: 4});
243-
expect(gd._fullData[0].ybins).toEqual({start: 0.5, end: 4.5, size: 1, _count: 4});
242+
expect(gd._fullData[0].xbins).toEqual({start: 0.5, end: 4.5, size: 1, _dataSpan: 3});
243+
expect(gd._fullData[0].ybins).toEqual({start: 0.5, end: 4.5, size: 1, _dataSpan: 3});
244244
expect(gd._fullData[0].autobinx).toBe(false);
245245
expect(gd._fullData[0].autobiny).toBe(false);
246246

247247
// with autobin false this will no longer update the bins.
248248
Plotly.restyle(gd, {x: [[1, 3, 4]], y: [[1, 2, 4]]});
249-
expect(gd._fullData[0].xbins).toEqual({start: 0.5, end: 4.5, size: 1, _count: 4});
250-
expect(gd._fullData[0].ybins).toEqual({start: 0.5, end: 4.5, size: 1, _count: 4});
249+
expect(gd._fullData[0].xbins).toEqual({start: 0.5, end: 4.5, size: 1, _dataSpan: 3});
250+
expect(gd._fullData[0].ybins).toEqual({start: 0.5, end: 4.5, size: 1, _dataSpan: 3});
251251
expect(gd._fullData[0].autobinx).toBe(false);
252252
expect(gd._fullData[0].autobiny).toBe(false);
253253
});

‎test/jasmine/tests/histogram_test.js

+29-9
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ describe('Test histogram', function() {
182182

183183
var out = calc(gd, fullTrace);
184184
delete out[0].trace;
185+
186+
// this is dumb - but some of the `p0` values are `-0` which doesn't match `0`
187+
// even though -0 === 0
188+
out.forEach(function(cdi) {
189+
for(var key in cdi) {
190+
if(cdi[key] === 0) cdi[key] = 0;
191+
}
192+
});
193+
185194
return out;
186195
}
187196

@@ -238,14 +247,6 @@ describe('Test histogram', function() {
238247
nbinsx: 4
239248
});
240249

241-
// this is dumb - but some of the `p0` values are `-0` which doesn't match `0`
242-
// even though -0 === 0
243-
out.forEach(function(cdi) {
244-
Object.keys(cdi).forEach(function(key) {
245-
if(cdi[key] === 0) cdi[key] = 0;
246-
});
247-
});
248-
249250
expect(out).toEqual([
250251
// dec 31 12:00 -> jan 31 12:00, middle is jan 16
251252
{i: 0, b: 0, p: Date.UTC(1970, 0, 16), s: 2, pts: [0, 1], p0: Date.UTC(1970, 0, 1), p1: Date.UTC(1970, 0, 31)},
@@ -365,6 +366,25 @@ describe('Test histogram', function() {
365366
]);
366367
});
367368

369+
it('can tell the difference between single-bin and single-value histograms', function() {
370+
var out = _calc({x: [1, 4]}, [], {barmode: 'overlay'});
371+
372+
expect(out).toEqual([
373+
{i: 0, b: 0, p: 2, s: 2, width1: 5, pts: [0, 1], p0: 0, p1: 4}
374+
]);
375+
376+
// real single-valued trace inherits bar width from the simply single-bin trace
377+
out = _calc({x: [5]}, [
378+
{x: [1, 4]}
379+
], {
380+
barmode: 'overlay'
381+
});
382+
383+
expect(out).toEqual([
384+
{i: 0, b: 0, p: 5, s: 1, width1: 5, pts: [0], p0: 5, p1: 5}
385+
]);
386+
});
387+
368388
function calcPositions(opts, extraTraces) {
369389
return _calc(opts, extraTraces).map(function(v) { return v.p; });
370390
}
@@ -652,7 +672,7 @@ describe('Test histogram', function() {
652672
.then(done);
653673
});
654674

655-
it('give the right bar width for single-bin histograms', function(done) {
675+
it('gives the right bar width for single-value histograms', function(done) {
656676
Plotly.newPlot(gd, [{
657677
type: 'histogram',
658678
x: [3, 3, 3],

0 commit comments

Comments
 (0)
Please sign in to comment.