Skip to content

Commit 923df18

Browse files
committed
Create sizemode after fb in pull 6698
Creating sizemode and sdmultiple to allow plots with any standard deviation, and a simpler cleaner codebase. use 'showwhisker' insteadk of 'whiskerdisable' adding .png to allow unit test to pass hover annotation labels number of std deviations chosen
1 parent fe3d2d0 commit 923df18

File tree

8 files changed

+85
-52
lines changed

8 files changed

+85
-52
lines changed

src/traces/box/attributes.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,33 @@ module.exports = {
218218
'right (left) for vertical boxes and above (below) for horizontal boxes'
219219
].join(' ')
220220
},
221-
221+
sdmultiple: {
222+
valType: 'number',
223+
min: 0,
224+
editType: 'calc',
225+
dflt: 1,
226+
description: [
227+
'Scales the box size when sizemode=sd',
228+
'Allowing boxes to be drawn across any stddev range',
229+
'For example 1-stddev, 3-stddev, 5-stddev',
230+
].join(' ')
231+
},
232+
sizemode: {
233+
valType: 'enumerated',
234+
values: ['quartiles', 'sd'],
235+
editType: 'calc',
236+
dflt: 'quartiles',
237+
description: [
238+
'Sets the upper and lower bound for the boxes',
239+
'quartiles means box is drawn between Q1 and Q3',
240+
'SD means the box is drawn between Mean +- Standard Deviation',
241+
'Argument sdmultiple (default 1) to scale the box size',
242+
'So it could be drawn 1-stddev, 3-stddev etc',
243+
].join(' ')
244+
},
222245
boxmean: {
223246
valType: 'enumerated',
224-
values: [true, 'sd', '1sigma', '2sigma', '3sigma', '4sigma', '5sigma', '6sigma', false],
247+
values: [true, 'sd', false],
225248
editType: 'calc',
226249
description: [
227250
'If *true*, the mean of the box(es)\' underlying distribution is',
@@ -380,9 +403,9 @@ module.exports = {
380403
].join(' ')
381404
},
382405

383-
whiskerdisable: {
406+
showwhiskers: {
384407
valType: 'boolean',
385-
dflt: false,
408+
dflt: true,
386409
editType: 'calc',
387410
description: [
388411
'Determines whether or not whiskers are visible'

src/traces/box/calc.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ module.exports = function calc(gd, trace) {
221221
cdi.min = boxVals[0];
222222
cdi.max = boxVals[N - 1];
223223
cdi.mean = Lib.mean(boxVals, N);
224-
cdi.sd = Lib.stdev(boxVals, N, cdi.mean);
224+
cdi.sd = Lib.stdev(boxVals, N, cdi.mean) * trace.sdmultiple;
225225
cdi.med = Lib.interp(boxVals, 0.5);
226226

227227
if((N % 2) && (usesExclusive || usesInclusive)) {
@@ -286,7 +286,7 @@ module.exports = function calc(gd, trace) {
286286
q1: _(gd, 'q1:'),
287287
q3: _(gd, 'q3:'),
288288
max: _(gd, 'max:'),
289-
mean: trace.boxmean === 'sd' ? _(gd, 'mean ± σ:') : _(gd, 'mean:'),
289+
mean: (trace.boxmean === 'sd') || (trace.sizemode === 'sd') ? _(gd, 'mean ± ' + trace.sdmultiple + 'σ:') : _(gd, 'mean:'),
290290
lf: _(gd, 'lower fence:'),
291291
uf: _(gd, 'upper fence:')
292292
}

src/traces/box/defaults.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ function supplyDefaults(traceIn, traceOut, defaultColor, layout) {
4343
coerce('boxmean', boxmeanDflt);
4444

4545
coerce('whiskerwidth');
46-
coerce('whiskerdisable');
46+
coerce('showwhiskers');
47+
coerce('sizemode');
48+
coerce('sdmultiple');
4749
coerce('width');
4850
coerce('quartilemethod');
4951

src/traces/box/hover.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ function hoverOnBoxes(pointData, xval, yval, hovermode) {
140140
pointData.spikeDistance = dxy(di) * spikePseudoDistance / hoverPseudoDistance;
141141
pointData[spikePosAttr] = pAxis.c2p(di.pos, true);
142142

143-
var hasMean = trace.boxmean || (trace.meanline || {}).visible;
143+
var hasMean = trace.boxmean || (trace.sizemode === 'sd') || (trace.meanline || {}).visible;
144144
var hasFences = trace.boxpoints || trace.points;
145145

146146
// labels with equal values (e.g. when min === q1) should still be presented in the order they have when they're unequal
@@ -179,7 +179,7 @@ function hoverOnBoxes(pointData, xval, yval, hovermode) {
179179
// clicked point from a box during click-to-select
180180
pointData2.hoverOnBox = true;
181181

182-
if(attr === 'mean' && ('sd' in di) && ((trace.boxmean === 'sd') || (trace.boxmean === '1sigma') || (trace.boxmean === '2sigma') || (trace.boxmean === '3sigma') || (trace.boxmean === '4sigma') || (trace.boxmean === '5sigma') || (trace.boxmean === '6sigma'))) {
182+
if(attr === 'mean' && ('sd' in di) && ((trace.boxmean === 'sd') || (trace.sizemode === 'sd'))) {
183183
pointData2[vLetter + 'err'] = di.sd;
184184
}
185185

src/traces/box/plot.js

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ function plotBoxAndWhiskers(sel, axes, trace, t, isStatic) {
5454
var wdPos = t.wdPos || 0;
5555
var bPosPxOffset = t.bPosPxOffset || 0;
5656
var whiskerWidth = trace.whiskerwidth || 0;
57-
var whiskerDisable = trace.whiskerdisable || false;
57+
var showWhiskers = trace.showwhiskers;
5858
var notched = trace.notched || false;
5959
var nw = notched ? 1 - 2 * trace.notchwidth : 1;
6060

@@ -95,30 +95,15 @@ function plotBoxAndWhiskers(sel, axes, trace, t, isStatic) {
9595

9696
var posm0 = posAxis.l2p(lcenter - bdPos0 * nw) + bPosPxOffset;
9797
var posm1 = posAxis.l2p(lcenter + bdPos1 * nw) + bPosPxOffset;
98-
var q1 = trace.boxmean === '1sigma' ? valAxis.c2p(d.mean - 1 * d.sd, true) :
99-
trace.boxmean === '2sigma' ? valAxis.c2p(d.mean - 2 * d.sd, true) :
100-
trace.boxmean === '3sigma' ? valAxis.c2p(d.mean - 3 * d.sd, true) :
101-
trace.boxmean === '4sigma' ? valAxis.c2p(d.mean - 4 * d.sd, true) :
102-
trace.boxmean === '5sigma' ? valAxis.c2p(d.mean - 5 * d.sd, true) :
103-
trace.boxmean === '6sigma' ? valAxis.c2p(d.mean - 6 * d.sd, true) :
104-
valAxis.c2p(d.q1, true);
105-
var q3 = trace.boxmean === '1sigma' ? valAxis.c2p(d.mean + 1 * d.sd, true) :
106-
trace.boxmean === '2sigma' ? valAxis.c2p(d.mean + 2 * d.sd, true) :
107-
trace.boxmean === '3sigma' ? valAxis.c2p(d.mean + 3 * d.sd, true) :
108-
trace.boxmean === '4sigma' ? valAxis.c2p(d.mean + 4 * d.sd, true) :
109-
trace.boxmean === '5sigma' ? valAxis.c2p(d.mean + 5 * d.sd, true) :
110-
trace.boxmean === '6sigma' ? valAxis.c2p(d.mean + 6 * d.sd, true) :
111-
valAxis.c2p(d.q3, true);
98+
var q1 = trace.sizemode === 'sd' ? valAxis.c2p(d.mean - 1 * d.sd, true) :
99+
valAxis.c2p(d.q1, true);
100+
var q3 = trace.sizemode === 'sd' ? valAxis.c2p(d.mean + 1 * d.sd, true) :
101+
valAxis.c2p(d.q3, true);
112102
// make sure median isn't identical to either of the
113103
// quartiles, so we can see it
114104
var m = Lib.constrain(
115-
trace.boxmean === '1sigma' ? valAxis.c2p(d.mean, true) :
116-
trace.boxmean === '2sigma' ? valAxis.c2p(d.mean, true) :
117-
trace.boxmean === '3sigma' ? valAxis.c2p(d.mean, true) :
118-
trace.boxmean === '4sigma' ? valAxis.c2p(d.mean, true) :
119-
trace.boxmean === '5sigma' ? valAxis.c2p(d.mean, true) :
120-
trace.boxmean === '6sigma' ? valAxis.c2p(d.mean, true) :
121-
valAxis.c2p(d.med, true),
105+
trace.sizemode === 'sd' ? valAxis.c2p(d.mean, true) :
106+
valAxis.c2p(d.med, true),
122107
Math.min(q1, q3) + 1, Math.max(q1, q3) - 1
123108
);
124109

@@ -128,7 +113,7 @@ function plotBoxAndWhiskers(sel, axes, trace, t, isStatic) {
128113
// - box always has d.lf, but boxpoints can be anything
129114
// - violin has d.lf and should always use it (boxpoints is undefined)
130115
// - candlestick has only min/max
131-
var useExtremes = (d.lf === undefined) || (trace.boxpoints === false);
116+
var useExtremes = (d.lf === undefined) || (trace.boxpoints === false) || (trace.sizemode === 'sd');
132117
var lf = valAxis.c2p(useExtremes ? d.min : d.lf, true);
133118
var uf = valAxis.c2p(useExtremes ? d.max : d.uf, true);
134119
var ln = valAxis.c2p(d.ln, true);
@@ -146,7 +131,7 @@ function plotBoxAndWhiskers(sel, axes, trace, t, isStatic) {
146131
'V' + pos0 + // right edge
147132
(notched ? 'H' + un + 'L' + m + ',' + posm0 + 'L' + ln + ',' + pos0 : '') + // bottom notched edge
148133
'Z' + // end of the box
149-
(!whiskerDisable ?
134+
(showWhiskers ?
150135
'M' + q1 + ',' + posc + 'H' + lf + 'M' + q3 + ',' + posc + 'H' + uf + // whiskers
151136
(whiskerWidth === 0 ?
152137
'' : // whisker caps
@@ -170,7 +155,7 @@ function plotBoxAndWhiskers(sel, axes, trace, t, isStatic) {
170155
''
171156
) + // notched left edge
172157
'Z' + // end of the box
173-
(!whiskerDisable ?
158+
(showWhiskers ?
174159
'M' + posc + ',' + q1 + 'V' + lf + 'M' + posc + ',' + q3 + 'V' + uf + // whiskers
175160
(whiskerWidth === 0 ?
176161
'' : // whisker caps
58.4 KB
Loading

test/image/mocks/box_3sigma.json renamed to test/image/mocks/box_sizemode_sd.json

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
"boxpoints": "all",
1717
"pointpos": 0,
1818
"name": "1-sigma",
19-
"boxmean": "1sigma",
20-
"whiskerdisable": true
19+
"sizemode": "sd",
20+
"showwhiskers": false
2121
},
2222
{
2323
"y": [
@@ -35,8 +35,9 @@
3535
"pointpos": 0,
3636
"type": "box",
3737
"name": "2-sigma",
38-
"boxmean": "2sigma",
39-
"whiskerdisable": true
38+
"sdmultiple" : 2,
39+
"sizemode": "sd",
40+
"showwhiskers": false
4041
},
4142
{
4243
"y": [
@@ -54,8 +55,9 @@
5455
"boxpoints": "all",
5556
"pointpos": 0,
5657
"name": "3-sigma",
57-
"boxmean": "3sigma",
58-
"whiskerdisable": true
58+
"sdmultiple" : 3,
59+
"sizemode": "sd",
60+
"showwhiskers": false
5961
},
6062
{
6163
"y": [
@@ -72,9 +74,9 @@
7274
"type": "box",
7375
"boxpoints": "all",
7476
"pointpos": 0,
75-
"name": "4-sigma",
76-
"boxmean": "4sigma",
77-
"whiskerdisable": true
77+
"name": "1-sigma + whiskers",
78+
"sizemode": "sd",
79+
"showwhiskers": true
7880
},
7981
{
8082
"y": [
@@ -91,9 +93,10 @@
9193
"boxpoints": "all",
9294
"pointpos": 0,
9395
"type": "box",
94-
"name": "5-sigma",
95-
"boxmean": "5sigma",
96-
"whiskerdisable": true
96+
"name": "3-sigma + whiskers",
97+
"sdmultiple" : 3,
98+
"sizemode": "sd",
99+
"showwhiskers": true
97100
},
98101
{
99102
"y": [
@@ -110,9 +113,29 @@
110113
"boxpoints": "all",
111114
"pointpos": 0,
112115
"type": "box",
113-
"name": "6-sigma",
114-
"boxmean": "6sigma",
115-
"whiskerdisable": true
116+
"name": "diamond 1-sigma",
117+
"boxmean": "sd",
118+
"showwhiskers": false
119+
},
120+
{
121+
"y": [
122+
0.4995, 0.3786, 0.5188, 0.4505, 0.5805, 0.5539, 0.7341, 0.3303, 0.6202, 0.4754, 0.4814, 0.6103, 0.5157, 0.3841, 0.6166, 0.4917, 0.5646, 0.4532, 0.5983,
123+
0.5079, 0.5227, 0.5483, 0.3081, 0.5172, 0.4127, 0.3871, 0.4703, 0.5331, 0.4573, 0.6187, 0.5718, 0.4474, 0.5349, 0.4614, 0.3096, 0.4411, 0.7143, 0.5956,
124+
0.5171, 0.5515, 0.4234, 0.4589, 0.4289, 0.417, 0.4229, 0.5039, 0.4726, 0.5382, 0.261, 0.5326, 0.4472, 0.54, 0.4998, 0.5513, 0.3891, 0.4821, 0.5006,
125+
0.4362, 0.4184, 0.3632, 0.5182, 0.5229, 0.5493, 0.507, 0.4528, 0.4836, 0.5009, 0.49, 0.5757, 0.5408, 0.4246, 0.511, 0.5216, 0.3817, 0.4471, 0.4935,
126+
0.5668, 0.3187, 0.3633, 0.5964, 0.637, 0.4701, 0.4292, 0.4921, 0.439, 0.5846, 0.4502, 0.44, 0.3057, 0.4756, 0.4867, 0.502, 0.438, 0.6819, 0.2607,
127+
0.5233, 0.3291, 0.5555, 0.5397, 0.5068
128+
],
129+
"line": {
130+
"color": "#1c9099"
131+
},
132+
"boxpoints": "all",
133+
"pointpos": 0,
134+
"type": "box",
135+
"name": "diamond 3-sigma",
136+
"sdmultiple" : 3,
137+
"boxmean": "sd",
138+
"showwhiskers": false
116139
}
117140
],
118141
"layout": {

test/jasmine/tests/box_test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ describe('Test box hover:', function() {
769769
},
770770
nums: [
771771
'median: 0.55', 'min: 0', 'lower fence: 0', 'q1: 0.3', 'q3: 0.6', 'upper fence: 0.7', 'max: 0.7',
772-
'mean ± σ: 0.45 ± 0.2362908'
772+
'mean ± : 0.45 ± 0.2362908'
773773
],
774774
name: ['radishes', '', '', '', '', '', '', ''],
775775
axis: 'day 1'
@@ -927,7 +927,7 @@ describe('Test box hover:', function() {
927927
'max: 1',
928928
'lower fence: 0.3',
929929
'upper fence: 1',
930-
'mean ± σ: 0.6833333 ± 0.2409472',
930+
'mean ± : 0.6833333 ± 0.2409472',
931931
],
932932
name: ['carrots', '', '', '', '', '', '', ''],
933933
axis: 'day 2'
@@ -943,7 +943,7 @@ describe('Test box hover:', function() {
943943
'(max: 1, day 2)',
944944
'(lower fence: 0.3, day 2)',
945945
'(upper fence: 1, day 2)',
946-
'(mean ± σ: 0.6833333 ± 0.2409472, day 2)'
946+
'(mean ± : 0.6833333 ± 0.2409472, day 2)'
947947
],
948948
name: ['carrots', '', '', '', '', '', '', ''],
949949
}, {

0 commit comments

Comments
 (0)