@@ -186,6 +186,280 @@ describe('Test histogram', function() {
186186 } ) ;
187187 } ) ;
188188
189+ describe ( 'cross-trace bingroup logic:' , function ( ) {
190+ var gd ;
191+
192+ beforeEach ( function ( ) {
193+ spyOn ( Lib , 'warn' ) ;
194+ } ) ;
195+
196+ function _assert ( msg , exp , warnMsg ) {
197+ var allBinOpts = gd . _fullLayout . _histogramBinOpts ;
198+ var groups = Object . keys ( allBinOpts ) ;
199+
200+ expect ( groups . length ) . toBe ( exp . length , 'same # of bin groups| ' + msg ) ;
201+
202+ var eGroups = exp . map ( function ( expi ) { return expi [ 0 ] ; } ) ;
203+ expect ( groups ) . toEqual ( eGroups , 'same bin groups| ' + msg ) ;
204+
205+ exp . forEach ( function ( expi ) {
206+ var k = expi [ 0 ] ;
207+ var binOpts = allBinOpts [ k ] ;
208+
209+ if ( ! binOpts ) {
210+ return fail ( 'bingroup ' + k + ' does NOT exist| ' + msg ) ;
211+ }
212+
213+ var traces = binOpts . traces || [ ] ;
214+
215+ if ( ! traces . length ) {
216+ return fail ( 'traces list for bingroup ' + k + ' is empty| ' + msg ) ;
217+ }
218+
219+ expect ( traces . length ) . toBe ( expi [ 1 ] . length , 'same # of tracked traces|' + msg ) ;
220+
221+ traces . forEach ( function ( t , i ) {
222+ expect ( t . index )
223+ . toBe ( expi [ 1 ] [ i ] , 'tracks same traces[' + i + ']|' + msg ) ;
224+ expect ( t [ '_' + binOpts . dirs [ i ] + 'bingroup' ] )
225+ . toBe ( k , '_(x|y)bingroup key in trace' + i + '| ' + msg ) ;
226+ } ) ;
227+ } ) ;
228+
229+ if ( warnMsg ) {
230+ expect ( Lib . warn ) . toHaveBeenCalledWith ( warnMsg ) ;
231+ } else {
232+ expect ( Lib . warn ) . toHaveBeenCalledTimes ( 0 ) ;
233+ }
234+ }
235+
236+ it ( 'should group traces w/ same axes and w/ same orientation' , function ( ) {
237+ var barModes = [ 'group' , 'stack' ] ;
238+
239+ barModes . forEach ( function ( mode ) {
240+ gd = {
241+ data : [
242+ { type : 'histogram' , y : [ 1 ] } ,
243+ { type : 'histogram' , y : [ 2 ] } ,
244+
245+ { type : 'histogram' , y : [ 1 ] , xaxis : 'x2' } ,
246+ { type : 'histogram' , y : [ 3 ] , xaxis : 'x2' } ,
247+
248+ { type : 'histogram' , y : [ 3 ] } ,
249+ { type : 'histogram' , y : [ 2 ] , xaxis : 'x2' } ,
250+
251+ { type : 'histogram' , x : [ 1 ] } ,
252+ { uid : 'solo' , type : 'histogram' , x : [ 2 ] , yaxis : 'y2' } ,
253+ { type : 'histogram' , x : [ 2 ] }
254+ ] ,
255+ layout : { barmode : mode }
256+ } ;
257+ supplyAllDefaults ( gd ) ;
258+ _assert ( 'under barmode:' + mode , [
259+ [ 'xyy' , [ 0 , 1 , 4 ] ] ,
260+ [ 'x2yy' , [ 2 , 3 , 5 ] ] ,
261+ [ 'xyx' , [ 6 , 8 ] ] ,
262+ [ 'solo__x' , [ 7 ] ]
263+ ] ) ;
264+ } ) ;
265+ } ) ;
266+
267+ it ( 'should group traces on matching axes and w/ same orientation' , function ( ) {
268+ var barModes = [ 'group' , 'stack' ] ;
269+
270+ barModes . forEach ( function ( mode ) {
271+ gd = {
272+ data : [
273+ { type : 'histogram' , y : [ 1 ] } ,
274+ { type : 'histogram' , y : [ 2 ] , xaxis : 'x2' } ,
275+ { type : 'histogram' , x : [ 1 ] , yaxis : 'y2' } ,
276+ { type : 'histogram' , x : [ 2 ] , yaxis : 'y2' } ,
277+ ] ,
278+ layout : {
279+ barmode : mode ,
280+ xaxis2 : { matches : 'x' } ,
281+ yaxis2 : { matches : 'x' }
282+ }
283+ } ;
284+ supplyAllDefaults ( gd ) ;
285+ _assert ( 'under barmode:' + mode , [
286+ [ 'g0yy' , [ 0 , 1 ] ] ,
287+ [ 'g0g0x' , [ 2 , 3 ] ]
288+ ] ) ;
289+ } ) ;
290+ } ) ;
291+
292+ it ( 'should not group traces by default under barmode:overlay ' , function ( ) {
293+ gd = {
294+ data : [
295+ { uid : 'a' , type : 'histogram' , y : [ 1 ] } ,
296+ { uid : 'b' , type : 'histogram' , y : [ 2 ] } ,
297+
298+ { uid : 'c' , type : 'histogram' , y : [ 1 ] , xaxis : 'x2' } ,
299+ { uid : 'd' , type : 'histogram' , y : [ 3 ] , xaxis : 'x2' } ,
300+
301+ { uid : 'e' , type : 'histogram' , y : [ 3 ] } ,
302+ { uid : 'f' , type : 'histogram' , y : [ 2 ] , xaxis : 'x2' } ,
303+
304+ { uid : 'g' , type : 'histogram' , x : [ 1 ] } ,
305+ { uid : 'h' , type : 'histogram' , x : [ 2 ] , yaxis : 'y2' } ,
306+ { uid : 'i' , type : 'histogram' , x : [ 2 ] }
307+ ] ,
308+ layout : { barmode : 'overlay' }
309+ } ;
310+ supplyAllDefaults ( gd ) ;
311+ _assert ( '' , [
312+ [ 'a__y' , [ 0 ] ] , [ 'b__y' , [ 1 ] ] , [ 'c__y' , [ 2 ] ] ,
313+ [ 'd__y' , [ 3 ] ] , [ 'e__y' , [ 4 ] ] , [ 'f__y' , [ 5 ] ] ,
314+ [ 'g__x' , [ 6 ] ] , [ 'h__x' , [ 7 ] ] , [ 'i__x' , [ 8 ] ]
315+ ] ) ;
316+ } ) ;
317+
318+ it ( 'should not group histogram2d* traces by default' , function ( ) {
319+ gd = {
320+ data : [
321+ { uid : 'a' , type : 'histogram2d' , x : [ 1 ] , y : [ 1 ] } ,
322+ { uid : 'b' , type : 'histogram2d' , x : [ 2 ] , y : [ 2 ] } ,
323+ { uid : 'c' , type : 'histogram2dcontour' , x : [ 1 ] , y : [ 1 ] , xaxis : 'x2' , yaxis : 'y2' } ,
324+ { uid : 'd' , type : 'histogram2dcontour' , x : [ 2 ] , y : [ 2 ] , xaxis : 'x2' , yaxis : 'y2' } ,
325+ ] ,
326+ layout : { }
327+ } ;
328+ supplyAllDefaults ( gd ) ;
329+ _assert ( 'N.B. one bingroup for x, one bingroup for y for each trace' , [
330+ [ 'a__x' , [ 0 ] ] , [ 'a__y' , [ 0 ] ] ,
331+ [ 'b__x' , [ 1 ] ] , [ 'b__y' , [ 1 ] ] ,
332+ [ 'c__x' , [ 2 ] ] , [ 'c__y' , [ 2 ] ] ,
333+ [ 'd__x' , [ 3 ] ] , [ 'd__y' , [ 3 ] ]
334+ ] ) ;
335+ } ) ;
336+
337+ it ( 'should be able to group traces by *bingroup* under barmode:overlay ' , function ( ) {
338+ gd = {
339+ data : [
340+ { bingroup : '1' , type : 'histogram' , y : [ 1 ] } ,
341+ { uid : 'b' , type : 'histogram' , y : [ 2 ] } ,
342+ { bingroup : '2' , type : 'histogram' , y : [ 1 ] , xaxis : 'x2' } ,
343+ { bingroup : '1' , type : 'histogram' , y : [ 3 ] , xaxis : 'x2' } ,
344+ { bingroup : '2' , type : 'histogram' , y : [ 3 ] } ,
345+ { uid : 'f' , type : 'histogram' , y : [ 2 ] , xaxis : 'x2' } ,
346+ { bingroup : '3' , type : 'histogram' , x : [ 1 ] } ,
347+ { bingroup : '1' , type : 'histogram' , x : [ 2 ] , yaxis : 'y2' } ,
348+ { bingroup : '3' , type : 'histogram' , x : [ 2 ] }
349+ ] ,
350+ layout : { barmode : 'overlay' }
351+ } ;
352+ supplyAllDefaults ( gd ) ;
353+ _assert ( '' , [
354+ [ '1' , [ 0 , 3 , 7 ] ] ,
355+ [ '2' , [ 2 , 4 ] ] ,
356+ [ '3' , [ 6 , 8 ] ] ,
357+ [ 'b__y' , [ 1 ] ] ,
358+ [ 'f__y' , [ 5 ] ]
359+ ] ) ;
360+ } ) ;
361+
362+ it ( 'should be able to group histogram2d traces by *bingroup*' , function ( ) {
363+ gd = {
364+ data : [
365+ { uid : 'a' , type : 'histogram2d' , x : [ 1 ] , y : [ 1 ] } ,
366+ { uid : 'b' , type : 'histogram2d' , x : [ 1 ] , y : [ 1 ] } ,
367+ { bingroup : '1' , type : 'histogram2d' , x : [ 1 ] , y : [ 1 ] } ,
368+ { bingroup : '1' , type : 'histogram2d' , x : [ 1 ] , y : [ 1 ] } ,
369+ { uid : 'e' , type : 'histogram2d' , x : [ 1 ] , y : [ 1 ] } ,
370+ ]
371+ } ;
372+ supplyAllDefaults ( gd ) ;
373+ _assert ( '' , [
374+ [ 'a__x' , [ 0 ] ] , [ 'a__y' , [ 0 ] ] ,
375+ [ 'b__x' , [ 1 ] ] , [ 'b__y' , [ 1 ] ] ,
376+ [ '1__x' , [ 2 , 3 ] ] , [ '1__y' , [ 2 , 3 ] ] ,
377+ [ 'e__x' , [ 4 ] ] , [ 'e__y' , [ 4 ] ]
378+ ] ) ;
379+ } ) ;
380+
381+ // TODO figure out what to do in this case!
382+ it ( 'should be able to group histogram and histogram2d* traces together' , function ( ) {
383+ gd = {
384+ data : [
385+ { bingroup : '1' , type : 'histogram' , y : [ 1 ] } ,
386+ { bingroup : '1' , type : 'histogram' , y : [ 3 ] , xaxis : 'x2' } ,
387+ { bingroup : '1' , type : 'histogram2d' , x : [ 1 ] , y : [ 3 ] } ,
388+ { bingroup : '1' , type : 'histogram2dcontour' , x : [ 1 ] , y : [ 3 ] }
389+ ] ,
390+ layout : { barmode : 'overlay' }
391+ } ;
392+ supplyAllDefaults ( gd ) ;
393+ _assert ( 'N.B. histogram2d* indices show up twice, once for x-bins, once for y-bins' , [
394+ [ '1' , [ 0 , 1 ] ] ,
395+ [ '1__x' , [ 2 , 3 ] ] ,
396+ [ '1__y' , [ 2 , 3 ] ]
397+ ] ) ;
398+ } ) ;
399+
400+ it ( 'should not group traces across axes of different types' , function ( ) {
401+ gd = {
402+ data : [
403+ { uid : 'a' , bingroup : '1' , type : 'histogram' , y : [ 1 ] } ,
404+ { uid : 'b' , bingroup : '1' , type : 'histogram' , y : [ 'cats' ] , yaxis : 'y2' } ,
405+ ] ,
406+ layout : { barmode : 'overlay' }
407+ } ;
408+ supplyAllDefaults ( gd ) ;
409+
410+ _assert ( '' , [
411+ [ '1' , [ 0 ] ] ,
412+ [ 'b__y' , [ 1 ] ]
413+ ] ,
414+ 'Attempted to group the bins of trace 1 set on a type:category axis ' +
415+ 'with bins on type:linear axis.'
416+ ) ;
417+ } ) ;
418+
419+ it ( 'should force traces that "have to match" to have same bingroup (stack case)' , function ( ) {
420+ gd = {
421+ data : [
422+ // these 3 traces "have to match"
423+ { bingroup : '1' , type : 'histogram' , y : [ 1 ] } ,
424+ { type : 'histogram' , y : [ 1 ] } ,
425+ { bingroup : '2' , type : 'histogram' , y : [ 2 ] }
426+ ] ,
427+ layout : { barmode : 'stack' }
428+ } ;
429+ supplyAllDefaults ( gd ) ;
430+
431+ _assert ( 'used first valid bingroup to identify bin opts' , [
432+ [ '1' , [ 0 , 1 , 2 ] ]
433+ ] ,
434+ 'Trace 2 must match within bingroup 1.' +
435+ ' Ignoring its bingroup: 2 setting.'
436+ ) ;
437+ } ) ;
438+
439+ it ( 'traces that "have to match" can be grouped with traces that do not have to match using *bingroup*' , function ( ) {
440+ gd = {
441+ data : [
442+ // these 2 traces "have to match"
443+ { bingroup : '1' , type : 'histogram' , y : [ 1 ] } ,
444+ { type : 'histogram' , y : [ 1 ] } ,
445+ // this one does not have to match with the above two,
446+ // (it's on another subplot), but it can be grouped
447+ { bingroup : '1' , type : 'histogram' , y : [ 2 ] , xaxis : 'x2' , yaxis : 'y2' } ,
448+ // this one does not have to match either
449+ // (it's a histogram2d* traces), but it can be grouped
450+ // TODO should this be just "bingroup"???
451+ { xbingroup : '1' , ybingroup : '1' , type : 'histogram2d' , x : [ 3 ] , y : [ 3 ] }
452+ ] ,
453+ layout : { }
454+ } ;
455+ supplyAllDefaults ( gd ) ;
456+
457+ _assert ( '' , [
458+ // N.B ordering in *binOpts.traces* does not matter
459+ [ '1' , [ 0 , 1 , 3 , 3 , 2 ] ]
460+ ] ) ;
461+ } ) ;
462+ } ) ;
189463
190464 describe ( 'calc' , function ( ) {
191465 function _calc ( opts , extraTraces , layout , prependExtras ) {
0 commit comments