@@ -33,7 +33,7 @@ function rand() {
33
33
var JITTERCOUNT = 5 ; // points either side of this to include
34
34
var JITTERSPREAD = 0.01 ; // fraction of IQR to count as "dense"
35
35
36
- module . exports = function plot ( gd , plotinfo , cdbox ) {
36
+ function plot ( gd , plotinfo , cdbox ) {
37
37
var fullLayout = gd . _fullLayout ;
38
38
var xa = plotinfo . xaxis ;
39
39
var ya = plotinfo . yaxis ;
@@ -78,9 +78,6 @@ module.exports = function plot(gd, plotinfo, cdbox) {
78
78
t . bPos = bPos ;
79
79
t . bdPos = bdPos ;
80
80
81
- // repeatable pseudorandom number generator
82
- seed ( ) ;
83
-
84
81
// boxes and whiskers
85
82
sel . selectAll ( 'path.box' )
86
83
. data ( Lib . identity )
@@ -121,95 +118,7 @@ module.exports = function plot(gd, plotinfo, cdbox) {
121
118
122
119
// draw points, if desired
123
120
if ( trace . boxpoints ) {
124
- sel . selectAll ( 'g.points' )
125
- // since box plot points get an extra level of nesting, each
126
- // box needs the trace styling info
127
- . data ( function ( d ) {
128
- d . forEach ( function ( v ) {
129
- v . t = t ;
130
- v . trace = trace ;
131
- } ) ;
132
- return d ;
133
- } )
134
- . enter ( ) . append ( 'g' )
135
- . attr ( 'class' , 'points' )
136
- . selectAll ( 'path' )
137
- . data ( function ( d ) {
138
- var i ;
139
-
140
- var pts = trace . boxpoints === 'all' ?
141
- d . pts :
142
- d . pts . filter ( function ( pt ) { return ( pt . v < d . lf || pt . v > d . uf ) ; } ) ;
143
-
144
- // normally use IQR, but if this is 0 or too small, use max-min
145
- var typicalSpread = Math . max ( ( d . max - d . min ) / 10 , d . q3 - d . q1 ) ;
146
- var minSpread = typicalSpread * 1e-9 ;
147
- var spreadLimit = typicalSpread * JITTERSPREAD ;
148
- var jitterFactors = [ ] ;
149
- var maxJitterFactor = 0 ;
150
- var newJitter ;
151
-
152
- // dynamic jitter
153
- if ( trace . jitter ) {
154
- if ( typicalSpread === 0 ) {
155
- // edge case of no spread at all: fall back to max jitter
156
- maxJitterFactor = 1 ;
157
- jitterFactors = new Array ( pts . length ) ;
158
- for ( i = 0 ; i < pts . length ; i ++ ) {
159
- jitterFactors [ i ] = 1 ;
160
- }
161
- } else {
162
- for ( i = 0 ; i < pts . length ; i ++ ) {
163
- var i0 = Math . max ( 0 , i - JITTERCOUNT ) ;
164
- var pmin = pts [ i0 ] . v ;
165
- var i1 = Math . min ( pts . length - 1 , i + JITTERCOUNT ) ;
166
- var pmax = pts [ i1 ] . v ;
167
-
168
- if ( trace . boxpoints !== 'all' ) {
169
- if ( pts [ i ] . v < d . lf ) pmax = Math . min ( pmax , d . lf ) ;
170
- else pmin = Math . max ( pmin , d . uf ) ;
171
- }
172
-
173
- var jitterFactor = Math . sqrt ( spreadLimit * ( i1 - i0 ) / ( pmax - pmin + minSpread ) ) || 0 ;
174
- jitterFactor = Lib . constrain ( Math . abs ( jitterFactor ) , 0 , 1 ) ;
175
-
176
- jitterFactors . push ( jitterFactor ) ;
177
- maxJitterFactor = Math . max ( jitterFactor , maxJitterFactor ) ;
178
- }
179
- }
180
- newJitter = trace . jitter * 2 / maxJitterFactor ;
181
- }
182
-
183
- // fills in 'x' and 'y' in calcdata 'pts' item
184
- for ( i = 0 ; i < pts . length ; i ++ ) {
185
- var pt = pts [ i ] ;
186
- var v = pt . v ;
187
-
188
- var jitterOffset = trace . jitter ?
189
- ( newJitter * jitterFactors [ i ] * ( rand ( ) - 0.5 ) ) :
190
- 0 ;
191
-
192
- var posPx = d . pos + bPos + bdPos * ( trace . pointpos + jitterOffset ) ;
193
-
194
- if ( trace . orientation === 'h' ) {
195
- pt . y = posPx ;
196
- pt . x = v ;
197
- } else {
198
- pt . x = posPx ;
199
- pt . y = v ;
200
- }
201
-
202
- // tag suspected outliers
203
- if ( trace . boxpoints === 'suspectedoutliers' && v < d . uo && v > d . lo ) {
204
- pt . so = true ;
205
- }
206
- }
207
-
208
- return pts ;
209
- } )
210
- . enter ( ) . append ( 'path' )
211
- . classed ( 'point' , true )
212
- . call ( Drawing . translatePoints , xa , ya ) ;
121
+ plotPoints ( sel , plotinfo , trace , t ) ;
213
122
}
214
123
215
124
// draw mean (and stdev diamond) if desired
@@ -244,4 +153,111 @@ module.exports = function plot(gd, plotinfo, cdbox) {
244
153
} ) ;
245
154
}
246
155
} ) ;
156
+ }
157
+
158
+ function plotPoints ( sel , plotinfo , trace , t ) {
159
+ var xa = plotinfo . xaxis ;
160
+ var ya = plotinfo . yaxis ;
161
+ var bdPos = t . bdPos ;
162
+ var bPos = t . bPos ;
163
+
164
+ var mode = trace . boxpoints ;
165
+
166
+ // repeatable pseudorandom number generator
167
+ seed ( ) ;
168
+
169
+ sel . selectAll ( 'g.points' )
170
+ // since box plot points get an extra level of nesting, each
171
+ // box needs the trace styling info
172
+ . data ( function ( d ) {
173
+ d . forEach ( function ( v ) {
174
+ v . t = t ;
175
+ v . trace = trace ;
176
+ } ) ;
177
+ return d ;
178
+ } )
179
+ . enter ( ) . append ( 'g' )
180
+ . attr ( 'class' , 'points' )
181
+ . selectAll ( 'path' )
182
+ . data ( function ( d ) {
183
+ var i ;
184
+
185
+ var pts = mode === 'all' ?
186
+ d . pts :
187
+ d . pts . filter ( function ( pt ) { return ( pt . v < d . lf || pt . v > d . uf ) ; } ) ;
188
+
189
+ // normally use IQR, but if this is 0 or too small, use max-min
190
+ var typicalSpread = Math . max ( ( d . max - d . min ) / 10 , d . q3 - d . q1 ) ;
191
+ var minSpread = typicalSpread * 1e-9 ;
192
+ var spreadLimit = typicalSpread * JITTERSPREAD ;
193
+ var jitterFactors = [ ] ;
194
+ var maxJitterFactor = 0 ;
195
+ var newJitter ;
196
+
197
+ // dynamic jitter
198
+ if ( trace . jitter ) {
199
+ if ( typicalSpread === 0 ) {
200
+ // edge case of no spread at all: fall back to max jitter
201
+ maxJitterFactor = 1 ;
202
+ jitterFactors = new Array ( pts . length ) ;
203
+ for ( i = 0 ; i < pts . length ; i ++ ) {
204
+ jitterFactors [ i ] = 1 ;
205
+ }
206
+ } else {
207
+ for ( i = 0 ; i < pts . length ; i ++ ) {
208
+ var i0 = Math . max ( 0 , i - JITTERCOUNT ) ;
209
+ var pmin = pts [ i0 ] . v ;
210
+ var i1 = Math . min ( pts . length - 1 , i + JITTERCOUNT ) ;
211
+ var pmax = pts [ i1 ] . v ;
212
+
213
+ if ( mode !== 'all' ) {
214
+ if ( pts [ i ] . v < d . lf ) pmax = Math . min ( pmax , d . lf ) ;
215
+ else pmin = Math . max ( pmin , d . uf ) ;
216
+ }
217
+
218
+ var jitterFactor = Math . sqrt ( spreadLimit * ( i1 - i0 ) / ( pmax - pmin + minSpread ) ) || 0 ;
219
+ jitterFactor = Lib . constrain ( Math . abs ( jitterFactor ) , 0 , 1 ) ;
220
+
221
+ jitterFactors . push ( jitterFactor ) ;
222
+ maxJitterFactor = Math . max ( jitterFactor , maxJitterFactor ) ;
223
+ }
224
+ }
225
+ newJitter = trace . jitter * 2 / maxJitterFactor ;
226
+ }
227
+
228
+ // fills in 'x' and 'y' in calcdata 'pts' item
229
+ for ( i = 0 ; i < pts . length ; i ++ ) {
230
+ var pt = pts [ i ] ;
231
+ var v = pt . v ;
232
+
233
+ var jitterOffset = trace . jitter ?
234
+ ( newJitter * jitterFactors [ i ] * ( rand ( ) - 0.5 ) ) :
235
+ 0 ;
236
+
237
+ var posPx = d . pos + bPos + bdPos * ( trace . pointpos + jitterOffset ) ;
238
+
239
+ if ( trace . orientation === 'h' ) {
240
+ pt . y = posPx ;
241
+ pt . x = v ;
242
+ } else {
243
+ pt . x = posPx ;
244
+ pt . y = v ;
245
+ }
246
+
247
+ // tag suspected outliers
248
+ if ( mode === 'suspectedoutliers' && v < d . uo && v > d . lo ) {
249
+ pt . so = true ;
250
+ }
251
+ }
252
+
253
+ return pts ;
254
+ } )
255
+ . enter ( ) . append ( 'path' )
256
+ . classed ( 'point' , true )
257
+ . call ( Drawing . translatePoints , xa , ya ) ;
258
+ }
259
+
260
+ module . exports = {
261
+ plot : plot ,
262
+ plotPoints : plotPoints
247
263
} ;
0 commit comments