From e746b088d6ff929577416706f59c2d739f850640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 18 Feb 2019 17:34:08 -0500 Subject: [PATCH] consider alignment and offset group across matching axes ... as well as across trace types (confirmed behavior) to do so: - add getAxisGroup axis_ids.js util - mv alignmentgroup and offsetgroup coerce calls to crossTraceDefaults --- src/plots/cartesian/axis_ids.js | 10 ++ src/traces/bar/attributes.js | 6 +- src/traces/bar/cross_trace_calc.js | 3 +- src/traces/bar/defaults.js | 34 ++++-- src/traces/bar/index.js | 1 + src/traces/bar/layout_defaults.js | 19 +-- src/traces/box/cross_trace_calc.js | 3 +- src/traces/box/defaults.js | 23 +++- src/traces/box/index.js | 1 + src/traces/box/layout_defaults.js | 22 +--- src/traces/histogram/cross_trace_defaults.js | 15 +-- src/traces/histogram/defaults.js | 3 - src/traces/violin/defaults.js | 3 - src/traces/violin/index.js | 1 + .../baselines/groups-over-matching-axes.png | Bin 0 -> 34906 bytes .../mocks/groups-over-matching-axes.json | 111 ++++++++++++++++++ 16 files changed, 189 insertions(+), 66 deletions(-) create mode 100644 test/image/baselines/groups-over-matching-axes.png create mode 100644 test/image/mocks/groups-over-matching-axes.json diff --git a/src/plots/cartesian/axis_ids.js b/src/plots/cartesian/axis_ids.js index 8e0bf5003d3..eb36d1bf1c2 100644 --- a/src/plots/cartesian/axis_ids.js +++ b/src/plots/cartesian/axis_ids.js @@ -114,3 +114,13 @@ exports.idSort = function(id1, id2) { if(letter1 !== letter2) return letter1 > letter2 ? 1 : -1; return +(id1.substr(1) || 1) - +(id2.substr(1) || 1); }; + +exports.getAxisGroup = function getAxisGroup(fullLayout, axId) { + var matchGroups = fullLayout._axisMatchGroups; + + for(var i = 0; i < matchGroups.length; i++) { + var group = matchGroups[i]; + if(group[axId]) return 'g' + i; + } + return axId; +}; diff --git a/src/traces/bar/attributes.js b/src/traces/bar/attributes.js index ab8bf1b00b2..5cf9003da59 100644 --- a/src/traces/bar/attributes.js +++ b/src/traces/bar/attributes.js @@ -180,7 +180,8 @@ module.exports = { dflt: '', editType: 'calc', description: [ - 'Set several traces linked to the same position axis to the same', + 'Set several traces linked to the same position axis', + 'or matching axes to the same', 'offsetgroup where bars of the same position coordinate will line up.' ].join(' ') }, @@ -190,7 +191,8 @@ module.exports = { dflt: '', editType: 'calc', description: [ - 'Set several traces linked to the same position axis to the same', + 'Set several traces linked to the same position axis', + 'or matching axes to the same', 'alignmentgroup. This controls whether bars compute their positional', 'range dependently or independently.' ].join(' ') diff --git a/src/traces/bar/cross_trace_calc.js b/src/traces/bar/cross_trace_calc.js index f4ba937e47a..916e853eec5 100644 --- a/src/traces/bar/cross_trace_calc.js +++ b/src/traces/bar/cross_trace_calc.js @@ -14,6 +14,7 @@ var BADNUM = require('../../constants/numerical').BADNUM; var Registry = require('../../registry'); var Axes = require('../../plots/cartesian/axes'); +var getAxisGroup = require('../../plots/cartesian/axis_ids').getAxisGroup; var Sieve = require('./sieve.js'); /* @@ -286,7 +287,7 @@ function setOffsetAndWidthInGroupMode(gd, pa, sieve) { var overlap = (positions.length !== distinctPositions.length); var barGroupWidth = minDiff * (1 - bargap); - var groupId = pa._id + calcTraces[0][0].trace.orientation; + var groupId = getAxisGroup(fullLayout, pa._id) + calcTraces[0][0].trace.orientation; var alignmentGroups = fullLayout._alignmentOpts[groupId] || {}; for(var i = 0; i < nTraces; i++) { diff --git a/src/traces/bar/defaults.js b/src/traces/bar/defaults.js index 1cdd29da629..b6715411524 100644 --- a/src/traces/bar/defaults.js +++ b/src/traces/bar/defaults.js @@ -14,6 +14,7 @@ var Registry = require('../../registry'); var handleXYDefaults = require('../scatter/xy_defaults'); var handleStyleDefaults = require('../bar/style_defaults'); +var getAxisGroup = require('../../plots/cartesian/axis_ids').getAxisGroup; var attributes = require('./attributes'); function supplyDefaults(traceIn, traceOut, defaultColor, layout) { @@ -76,21 +77,16 @@ function supplyDefaults(traceIn, traceOut, defaultColor, layout) { errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'y'}); errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'x', inherit: 'y'}); - handleGroupingDefaults(traceIn, traceOut, layout, coerce); - Lib.coerceSelectionMarkerOpacity(traceOut, coerce); } -function handleGroupingDefaults(traceIn, traceOut, layout, coerce) { +function handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce) { var orientation = traceOut.orientation; - // TODO make this work across matching axes too?!? - // TODO should this work per trace-type? - // one set for bar/histogram another for box/violin? - // or just one set for all trace trace types? + // N.B. grouping is done across all trace trace types that support it var posAxId = traceOut[{v: 'x', h: 'y'}[orientation] + 'axis']; - var groupId = posAxId + orientation; + var groupId = getAxisGroup(fullLayout, posAxId) + orientation; - var alignmentOpts = layout._alignmentOpts || {}; + var alignmentOpts = fullLayout._alignmentOpts || {}; var alignmentgroup = coerce('alignmentgroup'); var alignmentGroups = alignmentOpts[groupId]; @@ -123,7 +119,27 @@ function handleGroupingDefaults(traceIn, traceOut, layout, coerce) { } } +function crossTraceDefaults(fullData, fullLayout) { + var traceIn, traceOut; + + function coerce(attr) { + return Lib.coerce(traceOut._input, traceOut, attributes, attr); + } + + for(var i = 0; i < fullData.length; i++) { + traceOut = fullData[i]; + + if(traceOut.type === 'bar') { + traceIn = traceOut._input; + if(fullLayout.barmode === 'group') { + handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); + } + } + } +} + module.exports = { supplyDefaults: supplyDefaults, + crossTraceDefaults: crossTraceDefaults, handleGroupingDefaults: handleGroupingDefaults }; diff --git a/src/traces/bar/index.js b/src/traces/bar/index.js index b024c48764f..2da83f64c5b 100644 --- a/src/traces/bar/index.js +++ b/src/traces/bar/index.js @@ -13,6 +13,7 @@ var Bar = {}; Bar.attributes = require('./attributes'); Bar.layoutAttributes = require('./layout_attributes'); Bar.supplyDefaults = require('./defaults').supplyDefaults; +Bar.crossTraceDefaults = require('./defaults').crossTraceDefaults; Bar.supplyLayoutDefaults = require('./layout_defaults'); Bar.calc = require('./calc'); Bar.crossTraceCalc = require('./cross_trace_calc').crossTraceCalc; diff --git a/src/traces/bar/layout_defaults.js b/src/traces/bar/layout_defaults.js index 35ab979591b..1f688164dd0 100644 --- a/src/traces/bar/layout_defaults.js +++ b/src/traces/bar/layout_defaults.js @@ -15,8 +15,6 @@ var Lib = require('../../lib'); var layoutAttributes = require('./layout_attributes'); module.exports = function(layoutIn, layoutOut, fullData) { - var i, trace; - function coerce(attr, dflt) { return Lib.coerce(layoutIn, layoutOut, layoutAttributes, attr, dflt); } @@ -25,10 +23,9 @@ module.exports = function(layoutIn, layoutOut, fullData) { var shouldBeGapless = false; var gappedAnyway = false; var usedSubplots = {}; - var tracesWithGroupAttrs = []; - for(i = 0; i < fullData.length; i++) { - trace = fullData[i]; + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; if(Registry.traceIs(trace, 'bar') && trace.visible) hasBars = true; else continue; @@ -45,10 +42,6 @@ module.exports = function(layoutIn, layoutOut, fullData) { trace[trace.orientation === 'v' ? 'xaxis' : 'yaxis']); if(pa.type !== 'category') shouldBeGapless = true; } - - if(trace.alignmentgroup || trace.offsetgroup) { - tracesWithGroupAttrs.push(trace); - } } if(!hasBars) return; @@ -58,12 +51,4 @@ module.exports = function(layoutIn, layoutOut, fullData) { coerce('bargap', (shouldBeGapless && !gappedAnyway) ? 0 : 0.2); coerce('bargroupgap'); - - if(mode !== 'group') { - for(i = 0; i < tracesWithGroupAttrs.length; i++) { - trace = tracesWithGroupAttrs[i]; - delete trace.alignmentgroup; - delete trace.offsetgroup; - } - } }; diff --git a/src/traces/box/cross_trace_calc.js b/src/traces/box/cross_trace_calc.js index 93bca2d6f77..566c47d368a 100644 --- a/src/traces/box/cross_trace_calc.js +++ b/src/traces/box/cross_trace_calc.js @@ -10,6 +10,7 @@ var Axes = require('../../plots/cartesian/axes'); var Lib = require('../../lib'); +var getAxisGroup = require('../../plots/cartesian/axis_ids').getAxisGroup; var orientations = ['v', 'h']; @@ -104,7 +105,7 @@ function setPositionOffset(traceType, gd, boxList, posAxis) { dPos = dPos0; if(group) { - var groupId = posAxis._id + trace.orientation; + var groupId = getAxisGroup(fullLayout, posAxis._id) + trace.orientation; var alignmentGroups = fullLayout._alignmentOpts[groupId] || {}; var alignmentGroupOpts = alignmentGroups[trace.alignmentgroup] || {}; var nOffsetGroups = Object.keys(alignmentGroupOpts.offsetGroups || {}).length; diff --git a/src/traces/box/defaults.js b/src/traces/box/defaults.js index e473086afc8..b8e315cd0fc 100644 --- a/src/traces/box/defaults.js +++ b/src/traces/box/defaults.js @@ -34,7 +34,6 @@ function supplyDefaults(traceIn, traceOut, defaultColor, layout) { if(notched) coerce('notchwidth'); handlePointsDefaults(traceIn, traceOut, coerce, {prefix: 'box'}); - handleGroupingDefaults(traceIn, traceOut, layout, coerce); } function handleSampleDefaults(traceIn, traceOut, coerce, layout) { @@ -110,8 +109,30 @@ function handlePointsDefaults(traceIn, traceOut, coerce, opts) { Lib.coerceSelectionMarkerOpacity(traceOut, coerce); } +function crossTraceDefaults(fullData, fullLayout) { + var traceIn, traceOut; + + function coerce(attr) { + return Lib.coerce(traceOut._input, traceOut, attributes, attr); + } + + for(var i = 0; i < fullData.length; i++) { + traceOut = fullData[i]; + var traceType = traceOut.type; + + if(traceType === 'box' || traceType === 'violin') { + traceIn = traceOut._input; + if(fullLayout[traceType + 'mode'] === 'group') { + handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce); + } + } + } +} + module.exports = { supplyDefaults: supplyDefaults, + crossTraceDefaults: crossTraceDefaults, + handleSampleDefaults: handleSampleDefaults, handlePointsDefaults: handlePointsDefaults }; diff --git a/src/traces/box/index.js b/src/traces/box/index.js index e8ffe05cc8a..174a3d6bb36 100644 --- a/src/traces/box/index.js +++ b/src/traces/box/index.js @@ -13,6 +13,7 @@ var Box = {}; Box.attributes = require('./attributes'); Box.layoutAttributes = require('./layout_attributes'); Box.supplyDefaults = require('./defaults').supplyDefaults; +Box.crossTraceDefaults = require('./defaults').crossTraceDefaults; Box.supplyLayoutDefaults = require('./layout_defaults').supplyLayoutDefaults; Box.calc = require('./calc'); Box.crossTraceCalc = require('./cross_trace_calc').crossTraceCalc; diff --git a/src/traces/box/layout_defaults.js b/src/traces/box/layout_defaults.js index 818355aab56..6c23d343a47 100644 --- a/src/traces/box/layout_defaults.js +++ b/src/traces/box/layout_defaults.js @@ -13,36 +13,22 @@ var Lib = require('../../lib'); var layoutAttributes = require('./layout_attributes'); function _supply(layoutIn, layoutOut, fullData, coerce, traceType) { - var i, trace; - var category = traceType + 'Layout'; var hasTraceType = false; - var tracesWithGroupAttrs = []; - for(i = 0; i < fullData.length; i++) { - trace = fullData[i]; + for(var i = 0; i < fullData.length; i++) { + var trace = fullData[i]; if(Registry.traceIs(trace, category)) { hasTraceType = true; - - if(trace.alignmentgroup || trace.offsetgroup) { - tracesWithGroupAttrs.push(trace); - } + break; } } if(!hasTraceType) return; - var mode = coerce(traceType + 'mode'); + coerce(traceType + 'mode'); coerce(traceType + 'gap'); coerce(traceType + 'groupgap'); - - if(mode !== 'group') { - for(i = 0; i < tracesWithGroupAttrs.length; i++) { - trace = tracesWithGroupAttrs[i]; - delete trace.alignmentgroup; - delete trace.offsetgroup; - } - } } function supplyLayoutDefaults(layoutIn, layoutOut, fullData) { diff --git a/src/traces/histogram/cross_trace_defaults.js b/src/traces/histogram/cross_trace_defaults.js index 4df1814fc71..0a7663cc43d 100644 --- a/src/traces/histogram/cross_trace_defaults.js +++ b/src/traces/histogram/cross_trace_defaults.js @@ -6,12 +6,13 @@ * LICENSE file in the root directory of this source tree. */ - 'use strict'; var Lib = require('../../lib'); var nestedProperty = Lib.nestedProperty; +var handleGroupingDefaults = require('../bar/defaults').handleGroupingDefaults; +var getAxisGroup = require('../../plots/cartesian/axis_ids').getAxisGroup; var attributes = require('./attributes'); var BINATTRS = { @@ -65,6 +66,8 @@ module.exports = function crossTraceDefaults(fullData, fullLayout) { direction: binDirection }; } + + handleGroupingDefaults(traceOut._input, traceOut, fullLayout, coerce); } for(group in allBinOpts) { @@ -111,13 +114,3 @@ module.exports = function crossTraceDefaults(fullData, fullLayout) { } } }; - -function getAxisGroup(fullLayout, axId) { - var matchGroups = fullLayout._axisMatchGroups; - - for(var i = 0; i < matchGroups.length; i++) { - var group = matchGroups[i]; - if(group[axId]) return 'g' + i; - } - return axId; -} diff --git a/src/traces/histogram/defaults.js b/src/traces/histogram/defaults.js index 6477b73fa7c..b8e94518e72 100644 --- a/src/traces/histogram/defaults.js +++ b/src/traces/histogram/defaults.js @@ -13,7 +13,6 @@ var Lib = require('../../lib'); var Color = require('../../components/color'); var handleStyleDefaults = require('../bar/style_defaults'); -var handleGroupingDefaults = require('../bar/defaults').handleGroupingDefaults; var attributes = require('./attributes'); module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { @@ -70,6 +69,4 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout var errorBarsSupplyDefaults = Registry.getComponentMethod('errorbars', 'supplyDefaults'); errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'y'}); errorBarsSupplyDefaults(traceIn, traceOut, lineColor || Color.defaultLine, {axis: 'x', inherit: 'y'}); - - handleGroupingDefaults(traceIn, traceOut, layout, coerce); }; diff --git a/src/traces/violin/defaults.js b/src/traces/violin/defaults.js index 487577d6af5..0a0fa8d1a73 100644 --- a/src/traces/violin/defaults.js +++ b/src/traces/violin/defaults.js @@ -12,7 +12,6 @@ var Lib = require('../../lib'); var Color = require('../../components/color'); var boxDefaults = require('../box/defaults'); -var handleGroupingDefaults = require('../bar/defaults').handleGroupingDefaults; var attributes = require('./attributes'); module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout) { @@ -57,6 +56,4 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout var meanLineWidth = coerce2('meanline.width', lineWidth); var meanLineVisible = coerce('meanline.visible', Boolean(meanLineColor || meanLineWidth)); if(!meanLineVisible) traceOut.meanline = {visible: false}; - - handleGroupingDefaults(traceIn, traceOut, layout, coerce); }; diff --git a/src/traces/violin/index.js b/src/traces/violin/index.js index 9714268d519..92531e2cbf8 100644 --- a/src/traces/violin/index.js +++ b/src/traces/violin/index.js @@ -12,6 +12,7 @@ module.exports = { attributes: require('./attributes'), layoutAttributes: require('./layout_attributes'), supplyDefaults: require('./defaults'), + crossTraceDefaults: require('../box/defaults').crossTraceDefaults, supplyLayoutDefaults: require('./layout_defaults'), calc: require('./calc'), crossTraceCalc: require('./cross_trace_calc'), diff --git a/test/image/baselines/groups-over-matching-axes.png b/test/image/baselines/groups-over-matching-axes.png new file mode 100644 index 0000000000000000000000000000000000000000..635d61e7fac22271824eba1905b8459471c4ab59 GIT binary patch literal 34906 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