Skip to content

Commit 536ce48

Browse files
committed
new histogram autobin algo
1 parent a8e4802 commit 536ce48

22 files changed

+694
-412
lines changed

src/plot_api/helpers.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,19 @@ exports.cleanData = function(data) {
386386
// sanitize rgb(fractions) and rgba(fractions) that old tinycolor
387387
// supported, but new tinycolor does not because they're not valid css
388388
Color.clean(trace);
389+
390+
// remove obsolete autobin(x|y) attributes, but only if true
391+
// if false, this needs to happen in Histogram.calc because it
392+
// can be a one-time autobin so we need to know the results before
393+
// we can push them back into the trace.
394+
if(trace.autobinx) {
395+
delete trace.autobinx;
396+
delete trace.xbins;
397+
}
398+
if(trace.autobiny) {
399+
delete trace.autobiny;
400+
delete trace.ybins;
401+
}
389402
}
390403
};
391404

src/plot_api/plot_api.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,6 +1434,18 @@ function _restyle(gd, aobj, traces) {
14341434
}
14351435
}
14361436

1437+
function allBins(binAttr) {
1438+
return function(j) {
1439+
return fullData[j][binAttr];
1440+
};
1441+
}
1442+
1443+
function arrayBins(binAttr) {
1444+
return function(vij, j) {
1445+
return vij === false ? fullData[traces[j]][binAttr] : null;
1446+
};
1447+
}
1448+
14371449
// now make the changes to gd.data (and occasionally gd.layout)
14381450
// and figure out what kind of graphics update we need to do
14391451
for(var ai in aobj) {
@@ -1449,6 +1461,17 @@ function _restyle(gd, aobj, traces) {
14491461
newVal,
14501462
valObject;
14511463

1464+
// Backward compatibility shim for turning histogram autobin on,
1465+
// or freezing previous autobinned values.
1466+
// Replace obsolete `autobin(x|y): true` with `(x|y)bins: null`
1467+
// and `autobin(x|y): false` with the `(x|y)bins` in `fullData`
1468+
if(ai === 'autobinx' || ai === 'autobiny') {
1469+
ai = ai.charAt(ai.length - 1) + 'bins';
1470+
if(Array.isArray(vi)) vi = vi.map(arrayBins(ai));
1471+
else if(vi === false) vi = traces.map(allBins(ai));
1472+
else vi = null;
1473+
}
1474+
14521475
redoit[ai] = vi;
14531476

14541477
if(ai.substr(0, 6) === 'LAYOUT') {
@@ -1609,8 +1632,12 @@ function _restyle(gd, aobj, traces) {
16091632
}
16101633
}
16111634

1612-
// major enough changes deserve autoscale, autobin, and
1635+
// Major enough changes deserve autoscale and
16131636
// non-reversed axes so people don't get confused
1637+
//
1638+
// Note: autobin (or its new analog bin clearing) is not included here
1639+
// since we're not pushing bins back to gd.data, so if we have bin
1640+
// info it was explicitly provided by the user.
16141641
if(['orientation', 'type'].indexOf(ai) !== -1) {
16151642
axlist = [];
16161643
for(i = 0; i < traces.length; i++) {
@@ -1619,10 +1646,6 @@ function _restyle(gd, aobj, traces) {
16191646
if(Registry.traceIs(trace, 'cartesian')) {
16201647
addToAxlist(trace.xaxis || 'x');
16211648
addToAxlist(trace.yaxis || 'y');
1622-
1623-
if(ai === 'type') {
1624-
doextra(['autobinx', 'autobiny'], true, i);
1625-
}
16261649
}
16271650
}
16281651

src/plots/plots.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -428,13 +428,6 @@ plots.supplyDefaults = function(gd, opts) {
428428
// attach helper method to check whether a plot type is present on graph
429429
newFullLayout._has = plots._hasPlotType.bind(newFullLayout);
430430

431-
// special cases that introduce interactions between traces
432-
var _modules = newFullLayout._visibleModules;
433-
for(i = 0; i < _modules.length; i++) {
434-
var _module = _modules[i];
435-
if(_module.cleanData) _module.cleanData(newFullData);
436-
}
437-
438431
if(oldFullData.length === newFullData.length) {
439432
for(i = 0; i < newFullData.length; i++) {
440433
relinkPrivateKeys(newFullData[i], oldFullData[i]);
@@ -444,6 +437,20 @@ plots.supplyDefaults = function(gd, opts) {
444437
// finally, fill in the pieces of layout that may need to look at data
445438
plots.supplyLayoutModuleDefaults(newLayout, newFullLayout, newFullData, gd._transitionData);
446439

440+
// Special cases that introduce interactions between traces.
441+
// This is after relinkPrivateKeys so we can use those in cleanData
442+
// and after layout module defaults, so we can use eg barmode
443+
var _modules = newFullLayout._visibleModules;
444+
var cleanDataFuncs = [];
445+
for(i = 0; i < _modules.length; i++) {
446+
var _module = _modules[i];
447+
// some trace types share cleanData (ie histogram2d, histogram2dcontour)
448+
if(_module.cleanData) Lib.pushUnique(cleanDataFuncs, _module.cleanData);
449+
}
450+
for(i = 0; i < cleanDataFuncs.length; i++) {
451+
cleanDataFuncs[i](newFullData, newFullLayout);
452+
}
453+
447454
// turn on flag to optimize large splom-only graphs
448455
// mostly by omitting SVG layers during Cartesian.drawFramework
449456
newFullLayout._hasOnlyLargeSploms = (

src/traces/bar/layout_defaults.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ module.exports = function(layoutIn, layoutOut, fullData) {
2828

2929
for(var i = 0; i < fullData.length; i++) {
3030
var trace = fullData[i];
31-
if(Registry.traceIs(trace, 'bar')) hasBars = true;
31+
if(Registry.traceIs(trace, 'bar') && trace.visible) hasBars = true;
3232
else continue;
3333

3434
// if we have at least 2 grouped bar traces on the same subplot,

src/traces/histogram/attributes.js

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -125,24 +125,6 @@ module.exports = {
125125
},
126126
editType: 'calc'
127127
},
128-
129-
autobinx: {
130-
valType: 'boolean',
131-
dflt: null,
132-
role: 'style',
133-
editType: 'calc',
134-
impliedEdits: {
135-
'xbins.start': undefined,
136-
'xbins.end': undefined,
137-
'xbins.size': undefined
138-
},
139-
description: [
140-
'Determines whether or not the x axis bin attributes are picked',
141-
'by an algorithm. Note that this should be set to false if you',
142-
'want to manually set the number of bins using the attributes in',
143-
'xbins.'
144-
].join(' ')
145-
},
146128
nbinsx: {
147129
valType: 'integer',
148130
min: 0,
@@ -152,28 +134,12 @@ module.exports = {
152134
description: [
153135
'Specifies the maximum number of desired bins. This value will be used',
154136
'in an algorithm that will decide the optimal bin size such that the',
155-
'histogram best visualizes the distribution of the data.'
137+
'histogram best visualizes the distribution of the data.',
138+
'Ignored if `xbins.size` is provided.'
156139
].join(' ')
157140
},
158141
xbins: makeBinsAttr('x'),
159142

160-
autobiny: {
161-
valType: 'boolean',
162-
dflt: null,
163-
role: 'style',
164-
editType: 'calc',
165-
impliedEdits: {
166-
'ybins.start': undefined,
167-
'ybins.end': undefined,
168-
'ybins.size': undefined
169-
},
170-
description: [
171-
'Determines whether or not the y axis bin attributes are picked',
172-
'by an algorithm. Note that this should be set to false if you',
173-
'want to manually set the number of bins using the attributes in',
174-
'ybins.'
175-
].join(' ')
176-
},
177143
nbinsy: {
178144
valType: 'integer',
179145
min: 0,
@@ -183,7 +149,8 @@ module.exports = {
183149
description: [
184150
'Specifies the maximum number of desired bins. This value will be used',
185151
'in an algorithm that will decide the optimal bin size such that the',
186-
'histogram best visualizes the distribution of the data.'
152+
'histogram best visualizes the distribution of the data.',
153+
'Ignored if `ybins.size` is provided.'
187154
].join(' ')
188155
},
189156
ybins: makeBinsAttr('y'),
@@ -194,51 +161,69 @@ module.exports = {
194161
unselected: barAttrs.unselected,
195162

196163
_deprecated: {
197-
bardir: barAttrs._deprecated.bardir
164+
bardir: barAttrs._deprecated.bardir,
165+
autobinx: {
166+
valType: 'boolean',
167+
dflt: null,
168+
role: 'style',
169+
editType: 'calc',
170+
impliedEdits: {
171+
'xbins.start': undefined,
172+
'xbins.end': undefined,
173+
'xbins.size': undefined
174+
},
175+
description: [
176+
'Obsolete: since v1.42 each bin',
177+
'attribute is auto-determined separately.'
178+
].join(' ')
179+
},
180+
autobiny: {
181+
valType: 'boolean',
182+
dflt: null,
183+
role: 'style',
184+
editType: 'calc',
185+
impliedEdits: {
186+
'ybins.start': undefined,
187+
'ybins.end': undefined,
188+
'ybins.size': undefined
189+
},
190+
description: [
191+
'Obsolete: since v1.42 each bin',
192+
'attribute is auto-determined separately.'
193+
].join(' ')
194+
}
198195
}
199196
};
200197

201198
function makeBinsAttr(axLetter) {
202-
var impliedEdits = {};
203-
impliedEdits['autobin' + axLetter] = false;
204-
var impliedEditsInner = {};
205-
impliedEditsInner['^autobin' + axLetter] = false;
206-
207199
return {
208200
start: {
209201
valType: 'any', // for date axes
210-
dflt: null,
211202
role: 'style',
212203
editType: 'calc',
213-
impliedEdits: impliedEditsInner,
214204
description: [
215205
'Sets the starting value for the', axLetter,
216206
'axis bins.'
217207
].join(' ')
218208
},
219209
end: {
220210
valType: 'any', // for date axes
221-
dflt: null,
222211
role: 'style',
223212
editType: 'calc',
224-
impliedEdits: impliedEditsInner,
225213
description: [
226214
'Sets the end value for the', axLetter,
227215
'axis bins.'
228216
].join(' ')
229217
},
230218
size: {
231219
valType: 'any', // for date axes
232-
dflt: null,
233220
role: 'style',
234221
editType: 'calc',
235-
impliedEdits: impliedEditsInner,
236222
description: [
237223
'Sets the step in-between value each', axLetter,
238224
'axis bin.'
239225
].join(' ')
240226
},
241-
editType: 'calc',
242-
impliedEdits: impliedEdits
227+
editType: 'calc'
243228
};
244229
}

src/traces/histogram/bin_defaults.js

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)