Skip to content

Commit 2f9fa3b

Browse files
committed
Fix width of box plots with log-scale axis
1 parent 25fe1c9 commit 2f9fa3b

File tree

6 files changed

+130
-26
lines changed

6 files changed

+130
-26
lines changed

src/plots/cartesian/autorange.js

+19-10
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ function doAutoRange(gd, ax) {
298298
* (unless one end is overridden by tozero)
299299
* tozero: (boolean) make sure to include zero if axis is linear,
300300
* and make it a tight bound if possible
301+
* vpadLinearized: (boolean) whether or not vpad (or vpadplus/vpadminus)
302+
* is linearized (for log scale axes)
301303
*
302304
* @return {object}
303305
* - min {array of objects}
@@ -320,6 +322,7 @@ function findExtremes(ax, data, opts) {
320322
var tozero = opts.tozero && (ax.type === 'linear' || ax.type === '-');
321323
var isLog = ax.type === 'log';
322324
var hasArrayOption = false;
325+
var vpadLinearized = opts.vpadLinearized || false;
323326
var i, v, di, dmin, dmax, ppadiplus, ppadiminus, vmin, vmax;
324327

325328
function makePadAccessor(item) {
@@ -371,16 +374,22 @@ function findExtremes(ax, data, opts) {
371374
if(!isNumeric(di)) return;
372375
ppadiplus = ppadplus(i);
373376
ppadiminus = ppadminus(i);
374-
vmin = di - vpadminus(i);
375-
vmax = di + vpadplus(i);
376-
// special case for log axes: if vpad makes this object span
377-
// more than an order of mag, clip it to one order. This is so
378-
// we don't have non-positive errors or absurdly large lower
379-
// range due to rounding errors
380-
if(isLog && vmin < vmax / 10) vmin = vmax / 10;
381-
382-
dmin = ax.c2l(vmin);
383-
dmax = ax.c2l(vmax);
377+
378+
if(vpadLinearized) {
379+
dmin = ax.c2l(di) - vpadminus(i);
380+
dmax = ax.c2l(di) + vpadplus(i);
381+
} else {
382+
vmin = di - vpadminus(i);
383+
vmax = di + vpadplus(i);
384+
// special case for log axes: if vpad makes this object span
385+
// more than an order of mag, clip it to one order. This is so
386+
// we don't have non-positive errors or absurdly large lower
387+
// range due to rounding errors
388+
// if(isLog && vmin < vmax / 10) vmin = vmax / 10;
389+
390+
dmin = ax.c2l(vmin);
391+
dmax = ax.c2l(vmax);
392+
}
384393

385394
if(tozero) {
386395
dmin = Math.min(0, dmin);

src/traces/box/cross_trace_calc.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function setPositionOffset(traceType, gd, boxList, posAxis) {
6060
for(i = 0; i < boxList.length; i++) {
6161
calcTrace = calcdata[boxList[i]];
6262
for(j = 0; j < calcTrace.length; j++) {
63-
pointList.push(calcTrace[j].pos);
63+
pointList.push(posAxis.c2l(calcTrace[j].pos, true));
6464
shownPts += (calcTrace[j].pts2 || []).length;
6565
}
6666
}
@@ -125,7 +125,6 @@ function setPositionOffset(traceType, gd, boxList, posAxis) {
125125
t.bPos = bPos;
126126
t.bdPos = bdPos;
127127
t.wHover = wHover;
128-
129128
// box/violin-only value-space push value
130129
var pushplus;
131130
var pushminus;
@@ -213,6 +212,7 @@ function setPositionOffset(traceType, gd, boxList, posAxis) {
213212
padded: padded,
214213
vpadminus: vpadminus,
215214
vpadplus: vpadplus,
215+
vpadLinearized: true,
216216
// N.B. SVG px-space positive/negative
217217
ppadminus: {x: ppadminus, y: ppadplus}[axLetter],
218218
ppadplus: {x: ppadplus, y: ppadminus}[axLetter],

src/traces/box/hover.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ function hoverOnBoxes(pointData, xval, yval, hovermode) {
6060
var boxDelta = t.bdPos;
6161
var boxDeltaPos, boxDeltaNeg;
6262
var posAcceptance = t.wHover;
63-
var shiftPos = function(di) { return di.pos + t.bPos - pVal; };
63+
var shiftPos = function(di) { return pAxis.c2l(di.pos) + t.bPos - pAxis.c2l(pVal); };
6464

6565
if(isViolin && trace.side !== 'both') {
6666
if(trace.side === 'positive') {

src/traces/box/plot.js

+14-13
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,16 @@ function plotBoxAndWhiskers(sel, axes, trace, t) {
8686
paths.each(function(d) {
8787
if(d.empty) return 'M0,0Z';
8888

89-
var pos = d.pos;
90-
var posc = posAxis.c2p(pos + bPos, true) + bPosPxOffset;
91-
var pos0 = posAxis.c2p(pos + bPos - bdPos0, true) + bPosPxOffset;
92-
var pos1 = posAxis.c2p(pos + bPos + bdPos1, true) + bPosPxOffset;
93-
var posw0 = posAxis.c2p(pos + bPos - wdPos, true) + bPosPxOffset;
94-
var posw1 = posAxis.c2p(pos + bPos + wdPos, true) + bPosPxOffset;
95-
var posm0 = posAxis.c2p(pos + bPos - bdPos0 * nw, true) + bPosPxOffset;
96-
var posm1 = posAxis.c2p(pos + bPos + bdPos1 * nw, true) + bPosPxOffset;
97-
var q1 = valAxis.c2p(d.q1, true);
98-
var q3 = valAxis.c2p(d.q3, true);
89+
var lcenter = posAxis.c2l(d.pos + bPos, true);
90+
var posc = posAxis.l2p(lcenter) + bPosPxOffset;
91+
var pos0 = posAxis.l2p(lcenter - bdPos0) + bPosPxOffset;
92+
var pos1 = posAxis.l2p(lcenter + bdPos1) + bPosPxOffset;
93+
var posw0 = posAxis.l2p(lcenter - wdPos) + bPosPxOffset;
94+
var posw1 = posAxis.l2p(lcenter + wdPos) + bPosPxOffset;
95+
var posm0 = posAxis.l2p(lcenter - bdPos0 * nw) + bPosPxOffset;
96+
var posm1 = posAxis.l2p(lcenter + bdPos1 * nw) + bPosPxOffset;
97+
var q1 = valAxis.l2p(d.q1, true);
98+
var q3 = valAxis.l2p(d.q3, true);
9999
// make sure median isn't identical to either of the
100100
// quartiles, so we can see it
101101
var m = Lib.constrain(
@@ -288,9 +288,10 @@ function plotBoxMean(sel, axes, trace, t) {
288288
paths.exit().remove();
289289

290290
paths.each(function(d) {
291-
var posc = posAxis.c2p(d.pos + bPos, true) + bPosPxOffset;
292-
var pos0 = posAxis.c2p(d.pos + bPos - bdPos0, true) + bPosPxOffset;
293-
var pos1 = posAxis.c2p(d.pos + bPos + bdPos1, true) + bPosPxOffset;
291+
var lcenter = posAxis.c2l(d.pos + bPos, true);
292+
var posc = posAxis.l2p(lcenter) + bPosPxOffset;
293+
var pos0 = posAxis.l2p(lcenter - bdPos0) + bPosPxOffset;
294+
var pos1 = posAxis.l2p(lcenter + bdPos1) + bPosPxOffset;
294295
var m = valAxis.c2p(d.mean, true);
295296
var sl = valAxis.c2p(d.mean - d.sd, true);
296297
var sh = valAxis.c2p(d.mean + d.sd, true);
15.9 KB
Loading

test/image/mocks/box_log_scale.json

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
{
2+
"data": [
3+
{
4+
"y": [
5+
1.0,
6+
1.1,
7+
1.0,
8+
0.9,
9+
1.2,
10+
2.0,
11+
1.5,
12+
2.3,
13+
1.7,
14+
2.2,
15+
1.0,
16+
1.1,
17+
1.2,
18+
0.9,
19+
1.1
20+
],
21+
"x": [
22+
1,
23+
1,
24+
1,
25+
1,
26+
1,
27+
10,
28+
10,
29+
10,
30+
10,
31+
10,
32+
100,
33+
100,
34+
100,
35+
100,
36+
100
37+
],
38+
"type": "box"
39+
},
40+
{
41+
"y": [
42+
2.2,
43+
2.3,
44+
2.0,
45+
2.5,
46+
2.1,
47+
0.1,
48+
0.5,
49+
0.8,
50+
0.3,
51+
0.3,
52+
1.1,
53+
1.2,
54+
0.9,
55+
1.0,
56+
1.0,
57+
2.4,
58+
2.0,
59+
1.5,
60+
1.6,
61+
1.9
62+
],
63+
"x": [
64+
1,
65+
1,
66+
1,
67+
1,
68+
1,
69+
10,
70+
10,
71+
10,
72+
10,
73+
10,
74+
50,
75+
50,
76+
50,
77+
50,
78+
50,
79+
100,
80+
100,
81+
100,
82+
100,
83+
100
84+
],
85+
"type": "box",
86+
"boxmean": true
87+
}
88+
],
89+
"layout": {
90+
"xaxis": {
91+
"type": "log"
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)