Skip to content

Commit 8f8add1

Browse files
committed
🌴 histogram2d calc
1 parent 1b356d2 commit 8f8add1

File tree

1 file changed

+67
-71
lines changed

1 file changed

+67
-71
lines changed

src/traces/histogram2d/calc.js

Lines changed: 67 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -32,47 +32,13 @@ module.exports = function calc(gd, trace) {
3232

3333
var i, n, m;
3434

35-
cleanBins(trace, xa, 'x');
36-
cleanBins(trace, ya, 'y');
37-
3835
var serieslen = Math.min(x.length, y.length);
3936
if(x.length > serieslen) x.splice(serieslen, x.length - serieslen);
4037
if(y.length > serieslen) y.splice(serieslen, y.length - serieslen);
4138

42-
4339
// calculate the bins
44-
if(trace.autobinx || !trace.xbins ||
45-
trace.xbins.start === null || trace.xbins.end === null) {
46-
trace.xbins = Axes.autoBin(x, xa, trace.nbinsx, '2d', xcalendar);
47-
if(trace.type === 'histogram2dcontour') {
48-
// the "true" last argument reverses the tick direction (which we can't
49-
// just do with a minus sign because of month bins)
50-
trace.xbins.start = xc2r(Axes.tickIncrement(
51-
xr2c(trace.xbins.start), trace.xbins.size, true, xcalendar));
52-
trace.xbins.end = xc2r(Axes.tickIncrement(
53-
xr2c(trace.xbins.end), trace.xbins.size, false, xcalendar));
54-
}
55-
56-
// copy bin info back to the source data.
57-
trace._input.xbins = trace.xbins;
58-
// note that it's possible to get here with an explicit autobin: false
59-
// if the bins were not specified.
60-
// in that case this will remain in the trace, so that future updates
61-
// which would change the autobinning will not do so.
62-
trace._input.autobinx = trace.autobinx;
63-
}
64-
if(trace.autobiny || !trace.ybins ||
65-
trace.ybins.start === null || trace.ybins.end === null) {
66-
trace.ybins = Axes.autoBin(y, ya, trace.nbinsy, '2d', ycalendar);
67-
if(trace.type === 'histogram2dcontour') {
68-
trace.ybins.start = yc2r(Axes.tickIncrement(
69-
yr2c(trace.ybins.start), trace.ybins.size, true, ycalendar));
70-
trace.ybins.end = yc2r(Axes.tickIncrement(
71-
yr2c(trace.ybins.end), trace.ybins.size, false, ycalendar));
72-
}
73-
trace._input.ybins = trace.ybins;
74-
trace._input.autobiny = trace.autobiny;
75-
}
40+
cleanAndAutobin(trace, 'x', x, xa, xr2c, xc2r, xcalendar);
41+
cleanAndAutobin(trace, 'y', y, ya, yr2c, yc2r, ycalendar);
7642

7743
// make the empty bin array & scale the map
7844
var z = [];
@@ -110,12 +76,12 @@ module.exports = function calc(gd, trace) {
11076
}
11177

11278
// decrease end a little in case of rounding errors
113-
var binspec = trace.xbins,
114-
binStart = xr2c(binspec.start),
115-
binEnd = xr2c(binspec.end) +
116-
(binStart - Axes.tickIncrement(binStart, binspec.size, false, xcalendar)) / 1e6;
79+
var binSpec = trace.xbins,
80+
binStart = xr2c(binSpec.start),
81+
binEnd = xr2c(binSpec.end) +
82+
(binStart - Axes.tickIncrement(binStart, binSpec.size, false, xcalendar)) / 1e6;
11783

118-
for(i = binStart; i < binEnd; i = Axes.tickIncrement(i, binspec.size, false, xcalendar)) {
84+
for(i = binStart; i < binEnd; i = Axes.tickIncrement(i, binSpec.size, false, xcalendar)) {
11985
onecol.push(sizeinit);
12086
if(nonuniformBinsX) xbins.push(i);
12187
if(doavg) zerocol.push(0);
@@ -127,15 +93,15 @@ module.exports = function calc(gd, trace) {
12793
var dx = (i - x0c) / nx;
12894
var x0 = xc2r(x0c + dx / 2);
12995

130-
binspec = trace.ybins;
131-
binStart = yr2c(binspec.start);
132-
binEnd = yr2c(binspec.end) +
133-
(binStart - Axes.tickIncrement(binStart, binspec.size, false, ycalendar)) / 1e6;
96+
binSpec = trace.ybins;
97+
binStart = yr2c(binSpec.start);
98+
binEnd = yr2c(binSpec.end) +
99+
(binStart - Axes.tickIncrement(binStart, binSpec.size, false, ycalendar)) / 1e6;
134100

135-
for(i = binStart; i < binEnd; i = Axes.tickIncrement(i, binspec.size, false, ycalendar)) {
136-
z.push(onecol.concat());
101+
for(i = binStart; i < binEnd; i = Axes.tickIncrement(i, binSpec.size, false, ycalendar)) {
102+
z.push(onecol.slice());
137103
if(nonuniformBinsY) ybins.push(i);
138-
if(doavg) counts.push(zerocol.concat());
104+
if(doavg) counts.push(zerocol.slice());
139105
}
140106
if(nonuniformBinsY) ybins.push(i);
141107

@@ -145,33 +111,14 @@ module.exports = function calc(gd, trace) {
145111
var y0 = yc2r(y0c + dy / 2);
146112

147113
if(densitynorm) {
148-
xinc = onecol.map(function(v, i) {
149-
if(nonuniformBinsX) return 1 / (xbins[i + 1] - xbins[i]);
150-
return 1 / dx;
151-
});
152-
yinc = z.map(function(v, i) {
153-
if(nonuniformBinsY) return 1 / (ybins[i + 1] - ybins[i]);
154-
return 1 / dy;
155-
});
114+
xinc = makeIncrements(onecol.length, xbins, dx, nonuniformBinsX);
115+
yinc = makeIncrements(z.length, ybins, dy, nonuniformBinsY);
156116
}
157117

158118
// for date axes we need bin bounds to be calcdata. For nonuniform bins
159119
// we already have this, but uniform with start/end/size they're still strings.
160-
if(!nonuniformBinsX && xa.type === 'date') {
161-
xbins = {
162-
start: xr2c(xbins.start),
163-
end: xr2c(xbins.end),
164-
size: xbins.size
165-
};
166-
}
167-
if(!nonuniformBinsY && ya.type === 'date') {
168-
ybins = {
169-
start: yr2c(ybins.start),
170-
end: yr2c(ybins.end),
171-
size: ybins.size
172-
};
173-
}
174-
120+
if(!nonuniformBinsX && xa.type === 'date') xbins = binsToCalc(xr2c, xbins);
121+
if(!nonuniformBinsY && ya.type === 'date') ybins = binsToCalc(yr2c, ybins);
175122

176123
// put data into bins
177124
for(i = 0; i < serieslen; i++) {
@@ -199,3 +146,52 @@ module.exports = function calc(gd, trace) {
199146
z: z
200147
};
201148
};
149+
150+
function cleanAndAutobin(trace, axLetter, data, ax, r2c, c2r, calendar) {
151+
var binSpecAttr = axLetter + 'bins';
152+
var autoBinAttr = 'autobin' + axLetter;
153+
var binSpec = trace[binSpecAttr];
154+
155+
cleanBins(trace, ax, axLetter);
156+
157+
if(trace[autoBinAttr] || !binSpec || binSpec.start === null || binSpec.end === null) {
158+
binSpec = Axes.autoBin(data, ax, trace['nbins' + axLetter], '2d', calendar);
159+
if(trace.type === 'histogram2dcontour') {
160+
// the "true" last argument reverses the tick direction (which we can't
161+
// just do with a minus sign because of month bins)
162+
binSpec.start = c2r(Axes.tickIncrement(
163+
r2c(binSpec.start), binSpec.size, true, calendar));
164+
binSpec.end = c2r(Axes.tickIncrement(
165+
r2c(binSpec.end), binSpec.size, false, calendar));
166+
}
167+
168+
// copy bin info back to the source data.
169+
trace._input[binSpecAttr] = trace[binSpecAttr] = binSpec;
170+
// note that it's possible to get here with an explicit autobin: false
171+
// if the bins were not specified.
172+
// in that case this will remain in the trace, so that future updates
173+
// which would change the autobinning will not do so.
174+
trace._input[autoBinAttr] = trace[autoBinAttr];
175+
}
176+
}
177+
178+
function makeIncrements(len, bins, dv, nonuniform) {
179+
var out = new Array(len);
180+
var i;
181+
if(nonuniform) {
182+
for(i = 0; i < len; i++) out[i] = 1 / (bins[i + 1] - bins[i]);
183+
}
184+
else {
185+
var inc = 1 / dv;
186+
for(i = 0; i < len; i++) out[i] = inc;
187+
}
188+
return out;
189+
}
190+
191+
function binsToCalc(r2c, bins) {
192+
return {
193+
start: r2c(bins.start),
194+
end: r2c(bins.end),
195+
size: bins.size
196+
};
197+
}

0 commit comments

Comments
 (0)