Skip to content

make offsetgroup work with barmode 'stacked' and 'relative' for bar traces #7247

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a3fbabf
For bar traces make offsetgroup work with barmode 'stacked' and 'rela…
my-tien Jun 1, 2024
16cb035
Fix handleGroupingDefaults calls outside of bar/defaults.js
my-tien Jun 3, 2024
3f3a30e
Fix linter error on missing newline at EOF
my-tien Jun 3, 2024
bdce78a
Fix offset calculation and stacking for barpolar
my-tien Jun 4, 2024
c0d3216
Fix angularaxis check in setOffsetAndWidth
my-tien Jun 5, 2024
9ae2c10
consider modes of other traces as well (scattermode, funnelmode,... )
my-tien Jun 5, 2024
eb101ff
Don't use poffset for sieve.put, use trace._offsetIndex instead.
my-tien Jun 5, 2024
641a544
Fix logic for adding a gap between bars
my-tien Jun 5, 2024
8f020f6
baseline image for zzz_bar_relative_offsetgroup
my-tien Jun 5, 2024
a4fde80
Fix sieve for offsetgroups
my-tien Jun 6, 2024
48c469e
Fix for failing baseline test waterfall_funnel_template_date
my-tien Jun 6, 2024
31bb43a
Pass missing barmode param for histogram
my-tien Jun 6, 2024
81450bd
Ensure offsetIndex and offsetgroup are not undefined
my-tien Jun 6, 2024
3817206
Track alignmentgroups in fullLayout._alignmentOpts by trace type
my-tien Jun 7, 2024
3ec003d
Make offsetgroup work for boxmode overlay as well
my-tien Jun 7, 2024
3830b94
Documentation for setOffsetAndWidth and fix for sieve documentations
my-tien Jun 7, 2024
5faf455
Revert "Make offsetgroup work for boxmode overlay as well"
my-tien Aug 28, 2024
ea23867
Revert "Track alignmentgroups in fullLayout._alignmentOpts by trace t…
my-tien Aug 28, 2024
28b81a1
Ignore offsetgroup and alignmentgroup for those trace types that don'…
my-tien Aug 28, 2024
9601710
Update funnel test after adding support for alignmentgroup and offset…
my-tien Sep 2, 2024
e6445ba
Update bar test after adding support for alignmentgroup and offsetgro…
my-tien Sep 2, 2024
d291aad
Update baseline images for legendgroup_bar-stack and funnel_attrs
my-tien Sep 4, 2024
3ce0778
Adds draftlog.
stephprobst Oct 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
For bar traces make offsetgroup work with barmode 'stacked' and 'rela…
…tive'
  • Loading branch information
my-tien authored and stephprobst committed Oct 22, 2024
commit a3fbabfa9183ce702b9a4b145e8dba8e2116d7f6
56 changes: 10 additions & 46 deletions src/traces/bar/cross_trace_calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function setGroupPositions(gd, pa, sa, calcTraces, opts) {

switch(opts.mode) {
case 'overlay':
setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts);
setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces, opts);
break;

case 'group':
Expand All @@ -94,7 +94,7 @@ function setGroupPositions(gd, pa, sa, calcTraces, opts) {
setGroupPositionsInGroupMode(gd, pa, sa, included, opts);
}
if(excluded.length) {
setGroupPositionsInOverlayMode(pa, sa, excluded, opts);
setGroupPositionsInOverlayMode(gd, pa, sa, excluded, opts);
}
break;

Expand All @@ -119,7 +119,7 @@ function setGroupPositions(gd, pa, sa, calcTraces, opts) {
setGroupPositionsInStackOrRelativeMode(gd, pa, sa, included, opts);
}
if(excluded.length) {
setGroupPositionsInOverlayMode(pa, sa, excluded, opts);
setGroupPositionsInOverlayMode(gd, pa, sa, excluded, opts);
}
break;
}
Expand Down Expand Up @@ -217,7 +217,7 @@ function initBase(sa, calcTraces) {
}
}

function setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts) {
function setGroupPositionsInOverlayMode(gd, pa, sa, calcTraces, opts) {
// update position axis and set bar offsets and widths
for(var i = 0; i < calcTraces.length; i++) {
var calcTrace = calcTraces[i];
Expand All @@ -229,7 +229,7 @@ function setGroupPositionsInOverlayMode(pa, sa, calcTraces, opts) {
});

// set bar offsets and widths, and update position axis
setOffsetAndWidth(pa, sieve, opts);
setOffsetAndWidth(gd, pa, sieve, opts);

// set bar bases and sizes, and update size axis
//
Expand All @@ -253,7 +253,7 @@ function setGroupPositionsInGroupMode(gd, pa, sa, calcTraces, opts) {
});

// set bar offsets and widths, and update position axis
setOffsetAndWidthInGroupMode(gd, pa, sieve, opts);
setOffsetAndWidth(gd, pa, sieve, opts);

// relative-stack bars within the same trace that would otherwise
// be hidden
Expand All @@ -276,7 +276,7 @@ function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces, opts) {
});

// set bar offsets and widths, and update position axis
setOffsetAndWidth(pa, sieve, opts);
setOffsetAndWidth(gd, pa, sieve, opts);

// set bar bases and sizes, and update size axis
stackBars(sa, sieve, opts);
Expand All @@ -300,43 +300,7 @@ function setGroupPositionsInStackOrRelativeMode(gd, pa, sa, calcTraces, opts) {
if(opts.norm) normalizeBars(sa, sieve, opts);
}

function setOffsetAndWidth(pa, sieve, opts) {
var minDiff = sieve.minDiff;
var calcTraces = sieve.traces;

// set bar offsets and widths
var barGroupWidth = minDiff * (1 - opts.gap);
var barWidthPlusGap = barGroupWidth;
var barWidth = barWidthPlusGap * (1 - (opts.groupgap || 0));

// computer bar group center and bar offset
var offsetFromCenter = -barWidth / 2;

for(var i = 0; i < calcTraces.length; i++) {
var calcTrace = calcTraces[i];
var t = calcTrace[0].t;

// store bar width and offset for this trace
t.barwidth = barWidth;
t.poffset = offsetFromCenter;
t.bargroupwidth = barGroupWidth;
t.bardelta = minDiff;
}

// stack bars that only differ by rounding
sieve.binWidth = calcTraces[0][0].t.barwidth / 100;

// if defined, apply trace offset and width
applyAttributes(sieve);

// store the bar center in each calcdata item
setBarCenterAndWidth(pa, sieve);

// update position axes
updatePositionAxis(pa, sieve);
}

function setOffsetAndWidthInGroupMode(gd, pa, sieve, opts) {
function setOffsetAndWidth(gd, pa, sieve, opts) {
var fullLayout = gd._fullLayout;
var positions = sieve.positions;
var distinctPositions = sieve.distinctPositions;
Expand Down Expand Up @@ -615,6 +579,7 @@ function stackBars(sa, sieve, opts) {

isFunnel = (fullTrace.type === 'funnel');

var offset = calcTrace[0].t.poffset;
var pts = [];

for(j = 0; j < calcTrace.length; j++) {
Expand All @@ -629,8 +594,7 @@ function stackBars(sa, sieve, opts) {
value = bar.s + bar.b;
}

var base = sieve.put(bar.p, value);

var base = sieve.put(bar.p + offset, value);
var top = base + value;

// store the bar base and top in each calcdata item
Expand Down
4 changes: 1 addition & 3 deletions src/traces/bar/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,7 @@ function crossTraceDefaults(fullData, fullLayout) {
traceOut.marker.cornerradius = validateCornerradius(r);
}

if(fullLayout.barmode === 'group') {
handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce);
}
handleGroupingDefaults(fullLayout.barmode, traceIn, traceOut, fullLayout, coerce);
}
}
}
Expand Down
12 changes: 10 additions & 2 deletions src/traces/bar/layout_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports = function(layoutIn, layoutOut, fullData) {
var usedSubplots = {};

var mode = coerce('barmode');
var isGroup = mode === 'group';

for(var i = 0; i < fullData.length; i++) {
var trace = fullData[i];
Expand All @@ -27,10 +28,17 @@ module.exports = function(layoutIn, layoutOut, fullData) {

// if we have at least 2 grouped bar traces on the same subplot,
// we should default to a gap anyway, even if the data is histograms
if(mode === 'group') {
var subploti = trace.xaxis + trace.yaxis;
var subploti = trace.xaxis + trace.yaxis;
if(isGroup) {
// with barmode group, bars are grouped next to each other when sharing the same axes
if(usedSubplots[subploti]) gappedAnyway = true;
usedSubplots[subploti] = true;
} else {
// with other barmodes bars are grouped next to each other when sharing the same axes
// and using different offsetgroups
subploti += trace._input.offsetgroup;
if(!usedSubplots[subploti]) gappedAnyway = true;
usedSubplots[subploti] = true;
}

if(trace.visible && trace.type === 'histogram') {
Expand Down
7 changes: 4 additions & 3 deletions src/traces/scatter/grouping_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

var getAxisGroup = require('../../plots/cartesian/constraints').getAxisGroup;

module.exports = function handleGroupingDefaults(traceIn, traceOut, fullLayout, coerce) {
module.exports = function handleGroupingDefaults(barmode, traceIn, traceOut, fullLayout, coerce) {
var orientation = traceOut.orientation;
// N.B. grouping is done across all trace types that support it
var posAxId = traceOut[{v: 'x', h: 'y'}[orientation] + 'axis'];
Expand All @@ -29,8 +29,9 @@ module.exports = function handleGroupingDefaults(traceIn, traceOut, fullLayout,
var offsetgroup = coerce('offsetgroup');
var offsetGroups = alignmentGroupOpts.offsetGroups;
var offsetGroupOpts = offsetGroups[offsetgroup];

if(offsetgroup) {
// in barmode 'group', traces without offsetgroup receive their own offsetgroup
// in other barmodes, traces without offsetgroup are assigned to the same offset group
if(barmode !== 'group' || offsetgroup) {
if(!offsetGroupOpts) {
offsetGroupOpts = offsetGroups[offsetgroup] = {
offsetIndex: Object.keys(offsetGroups).length
Expand Down
48 changes: 48 additions & 0 deletions test/image/mocks/zzz_bar_relative_offsetgroup.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"data": [
{
"type": "bar",
"x": [ "A", "B", "C"],
"y": [ 10, 10, 10 ],
"offsetgroup": 1,
"hovertext": "offsetgroup: 1"
},
{
"type": "bar",
"x": [ "A", "B", "C"],
"y": [ 20, 20, 20 ],
"offsetgroup": 1,
"hovertext": "offsetgroup: 1"
},
{
"type": "bar",
"x": [ "A", "B", "C"],
"y": [ 30, 30, 30 ],
"offsetgroup": 2,
"hovertext": "offsetgroup: 2"
},
{
"type": "bar",
"x": [ "A", "B", "C"],
"y": [ 40, 40, 40 ],
"offsetgroup": 2,
"hovertext": "offsetgroup: 2"
},
{
"type": "bar",
"x": [ "A", "B", "C"],
"y": [ -50, 50, 50 ],
"offsetgroup": 2,
"hovertext": "offsetgroup: 2"
}
],
"layout": {
"width": 600,
"showlegend": false,
"barmode": "relative",
"title": {
"text": "Separately stacked bars with barmode 'relative'"
}
}
}