Skip to content

Commit f28caae

Browse files
authored
Merge pull request #2917 from plotly/heatmap-ordering-bug
Heatmap ordering bug
2 parents f996446 + d295d36 commit f28caae

File tree

22 files changed

+705
-684
lines changed

22 files changed

+705
-684
lines changed

src/lib/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ lib.clearThrottle = throttleModule.clear;
118118

119119
lib.getGraphDiv = require('./get_graph_div');
120120

121+
lib.makeTraceGroups = require('./make_trace_groups');
122+
121123
lib._ = require('./localize');
122124

123125
lib.notifier = require('./notifier');

src/lib/make_trace_groups.js

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Copyright 2012-2018, Plotly, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the MIT license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
10+
'use strict';
11+
12+
/**
13+
* General helper to manage trace groups based on calcdata
14+
*
15+
* @param {d3.selection} traceLayer: a selection containing a single group
16+
* to draw these traces into
17+
* @param {array} cdModule: array of calcdata items for this
18+
* module and subplot combination. Assumes the calcdata item for each
19+
* trace is an array with the fullData trace attached to the first item.
20+
* @param {string} cls: the class attribute to give each trace group
21+
* so you can give multiple classes separated by spaces
22+
*/
23+
module.exports = function makeTraceGroups(traceLayer, cdModule, cls) {
24+
var traces = traceLayer.selectAll('g.' + cls.replace(/\s/g, '.'))
25+
.data(cdModule, function(cd) { return cd[0].trace.uid; });
26+
27+
traces.exit().remove();
28+
29+
traces.enter().append('g')
30+
.attr('class', cls);
31+
32+
traces.order();
33+
34+
return traces;
35+
};

src/plots/get_data.js

-17
Original file line numberDiff line numberDiff line change
@@ -124,20 +124,3 @@ exports.getSubplotData = function getSubplotData(data, type, subplotId) {
124124

125125
return subplotData;
126126
};
127-
128-
/**
129-
* Get a lookup object of trace uids corresponding in a given calcdata array.
130-
*
131-
* @param {array} calcdata: as in gd.calcdata (or a subset)
132-
* @return {object} lookup object of uids (`uid: 1`)
133-
*/
134-
exports.getUidsFromCalcData = function(calcdata) {
135-
var out = {};
136-
137-
for(var i = 0; i < calcdata.length; i++) {
138-
var trace = calcdata[i][0].trace;
139-
out[trace.uid] = 1;
140-
}
141-
142-
return out;
143-
};

src/traces/bar/plot.js

+11-21
Original file line numberDiff line numberDiff line change
@@ -35,30 +35,20 @@ module.exports = function plot(gd, plotinfo, cdbar, barLayer) {
3535
var ya = plotinfo.yaxis;
3636
var fullLayout = gd._fullLayout;
3737

38-
var bartraces = barLayer.selectAll('g.trace.bars')
39-
.data(cdbar, function(d) { return d[0].trace.uid; });
40-
41-
bartraces.enter().append('g')
42-
.attr('class', 'trace bars')
43-
.append('g')
44-
.attr('class', 'points');
45-
46-
bartraces.exit().remove();
47-
48-
bartraces.order();
49-
50-
bartraces.each(function(d) {
51-
var cd0 = d[0];
38+
var bartraces = Lib.makeTraceGroups(barLayer, cdbar, 'trace bars').each(function(cd) {
39+
var plotGroup = d3.select(this);
40+
var cd0 = cd[0];
5241
var t = cd0.t;
5342
var trace = cd0.trace;
54-
var sel = d3.select(this);
5543

56-
if(!plotinfo.isRangePlot) cd0.node3 = sel;
44+
if(!plotinfo.isRangePlot) cd0.node3 = plotGroup;
5745

5846
var poffset = t.poffset;
5947
var poffsetIsArray = Array.isArray(poffset);
6048

61-
var bars = sel.select('g.points').selectAll('g.point').data(Lib.identity);
49+
var pointGroup = Lib.ensureSingle(plotGroup, 'g', 'points');
50+
51+
var bars = pointGroup.selectAll('g.point').data(Lib.identity);
6252

6353
bars.enter().append('g')
6454
.classed('point', true);
@@ -147,17 +137,17 @@ module.exports = function plot(gd, plotinfo, cdbar, barLayer) {
147137
'M' + x0 + ',' + y0 + 'V' + y1 + 'H' + x1 + 'V' + y0 + 'Z')
148138
.call(Drawing.setClipUrl, plotinfo.layerClipId);
149139

150-
appendBarText(gd, bar, d, i, x0, x1, y0, y1);
140+
appendBarText(gd, bar, cd, i, x0, x1, y0, y1);
151141

152142
if(plotinfo.layerClipId) {
153-
Drawing.hideOutsideRangePoint(d[i], bar.select('text'), xa, ya, trace.xcalendar, trace.ycalendar);
143+
Drawing.hideOutsideRangePoint(di, bar.select('text'), xa, ya, trace.xcalendar, trace.ycalendar);
154144
}
155145
});
156146

157147
// lastly, clip points groups of `cliponaxis !== false` traces
158148
// on `plotinfo._hasClipOnAxisFalse === true` subplots
159-
var hasClipOnAxisFalse = d[0].trace.cliponaxis === false;
160-
Drawing.setClipUrl(sel, hasClipOnAxisFalse ? null : plotinfo.layerClipId);
149+
var hasClipOnAxisFalse = cd0.trace.cliponaxis === false;
150+
Drawing.setClipUrl(plotGroup, hasClipOnAxisFalse ? null : plotinfo.layerClipId);
161151
});
162152

163153
// error bars are on the top

src/traces/box/plot.js

+11-23
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,16 @@ function plot(gd, plotinfo, cdbox, boxLayer) {
2121
var fullLayout = gd._fullLayout;
2222
var xa = plotinfo.xaxis;
2323
var ya = plotinfo.yaxis;
24+
var numBoxes = fullLayout._numBoxes;
25+
var groupFraction = (1 - fullLayout.boxgap);
26+
var group = (fullLayout.boxmode === 'group' && numBoxes > 1);
2427

25-
var boxtraces = boxLayer.selectAll('g.trace.boxes')
26-
.data(cdbox, function(d) { return d[0].trace.uid; });
27-
28-
boxtraces.enter().append('g')
29-
.attr('class', 'trace boxes');
30-
31-
boxtraces.exit().remove();
32-
33-
boxtraces.order();
34-
35-
boxtraces.each(function(d) {
36-
var cd0 = d[0];
28+
Lib.makeTraceGroups(boxLayer, cdbox, 'trace boxes').each(function(cd) {
29+
var plotGroup = d3.select(this);
30+
var cd0 = cd[0];
3731
var t = cd0.t;
3832
var trace = cd0.trace;
39-
var sel = d3.select(this);
40-
if(!plotinfo.isRangePlot) cd0.node3 = sel;
41-
var numBoxes = fullLayout._numBoxes;
42-
43-
var groupFraction = (1 - fullLayout.boxgap);
44-
45-
var group = (fullLayout.boxmode === 'group' && numBoxes > 1);
33+
if(!plotinfo.isRangePlot) cd0.node3 = plotGroup;
4634
// box half width
4735
var bdPos = t.dPos * groupFraction * (1 - fullLayout.boxgroupgap) / (group ? numBoxes : 1);
4836
// box center offset
@@ -51,7 +39,7 @@ function plot(gd, plotinfo, cdbox, boxLayer) {
5139
var wdPos = bdPos * trace.whiskerwidth;
5240

5341
if(trace.visible !== true || t.empty) {
54-
sel.remove();
42+
plotGroup.remove();
5543
return;
5644
}
5745

@@ -73,9 +61,9 @@ function plot(gd, plotinfo, cdbox, boxLayer) {
7361
// always split the distance to the closest box
7462
t.wHover = t.dPos * (group ? groupFraction / numBoxes : 1);
7563

76-
plotBoxAndWhiskers(sel, {pos: posAxis, val: valAxis}, trace, t);
77-
plotPoints(sel, {x: xa, y: ya}, trace, t);
78-
plotBoxMean(sel, {pos: posAxis, val: valAxis}, trace, t);
64+
plotBoxAndWhiskers(plotGroup, {pos: posAxis, val: valAxis}, trace, t);
65+
plotPoints(plotGroup, {x: xa, y: ya}, trace, t);
66+
plotBoxMean(plotGroup, {pos: posAxis, val: valAxis}, trace, t);
7967
});
8068
}
8169

src/traces/carpet/plot.js

+29-45
Original file line numberDiff line numberDiff line change
@@ -17,61 +17,45 @@ var orientText = require('./orient_text');
1717
var svgTextUtils = require('../../lib/svg_text_utils');
1818
var Lib = require('../../lib');
1919
var alignmentConstants = require('../../constants/alignment');
20-
var getUidsFromCalcData = require('../../plots/get_data').getUidsFromCalcData;
2120

2221
module.exports = function plot(gd, plotinfo, cdcarpet, carpetLayer) {
23-
var uidLookup = getUidsFromCalcData(cdcarpet);
24-
25-
carpetLayer.selectAll('g.trace').each(function() {
26-
var classString = d3.select(this).attr('class');
27-
var oldUid = classString.split('carpet')[1].split(/\s/)[0];
28-
29-
if(!uidLookup[oldUid]) {
30-
d3.select(this).remove();
31-
}
32-
});
33-
34-
for(var i = 0; i < cdcarpet.length; i++) {
35-
plotOne(gd, plotinfo, cdcarpet[i], carpetLayer);
36-
}
37-
};
38-
39-
function plotOne(gd, plotinfo, cd, carpetLayer) {
40-
var t = cd[0];
41-
var trace = cd[0].trace,
42-
xa = plotinfo.xaxis,
43-
ya = plotinfo.yaxis,
44-
aax = trace.aaxis,
45-
bax = trace.baxis,
46-
fullLayout = gd._fullLayout;
47-
22+
var xa = plotinfo.xaxis;
23+
var ya = plotinfo.yaxis;
24+
var fullLayout = gd._fullLayout;
4825
var clipLayer = fullLayout._clips;
4926

50-
var axisLayer = Lib.ensureSingle(carpetLayer, 'g', 'carpet' + trace.uid).classed('trace', true);
51-
var minorLayer = Lib.ensureSingle(axisLayer, 'g', 'minorlayer');
52-
var majorLayer = Lib.ensureSingle(axisLayer, 'g', 'majorlayer');
53-
var boundaryLayer = Lib.ensureSingle(axisLayer, 'g', 'boundarylayer');
54-
var labelLayer = Lib.ensureSingle(axisLayer, 'g', 'labellayer');
27+
Lib.makeTraceGroups(carpetLayer, cdcarpet, 'trace').each(function(cd) {
28+
var axisLayer = d3.select(this);
29+
var cd0 = cd[0];
30+
var trace = cd0.trace;
31+
var aax = trace.aaxis;
32+
var bax = trace.baxis;
5533

56-
axisLayer.style('opacity', trace.opacity);
34+
var minorLayer = Lib.ensureSingle(axisLayer, 'g', 'minorlayer');
35+
var majorLayer = Lib.ensureSingle(axisLayer, 'g', 'majorlayer');
36+
var boundaryLayer = Lib.ensureSingle(axisLayer, 'g', 'boundarylayer');
37+
var labelLayer = Lib.ensureSingle(axisLayer, 'g', 'labellayer');
5738

58-
drawGridLines(xa, ya, majorLayer, aax, 'a', aax._gridlines, true);
59-
drawGridLines(xa, ya, majorLayer, bax, 'b', bax._gridlines, true);
60-
drawGridLines(xa, ya, minorLayer, aax, 'a', aax._minorgridlines, true);
61-
drawGridLines(xa, ya, minorLayer, bax, 'b', bax._minorgridlines, true);
39+
axisLayer.style('opacity', trace.opacity);
6240

63-
// NB: These are not ommitted if the lines are not active. The joins must be executed
64-
// in order for them to get cleaned up without a full redraw
65-
drawGridLines(xa, ya, boundaryLayer, aax, 'a-boundary', aax._boundarylines);
66-
drawGridLines(xa, ya, boundaryLayer, bax, 'b-boundary', bax._boundarylines);
41+
drawGridLines(xa, ya, majorLayer, aax, 'a', aax._gridlines, true);
42+
drawGridLines(xa, ya, majorLayer, bax, 'b', bax._gridlines, true);
43+
drawGridLines(xa, ya, minorLayer, aax, 'a', aax._minorgridlines, true);
44+
drawGridLines(xa, ya, minorLayer, bax, 'b', bax._minorgridlines, true);
6745

68-
var labelOrientationA = drawAxisLabels(gd, xa, ya, trace, t, labelLayer, aax._labels, 'a-label');
69-
var labelOrientationB = drawAxisLabels(gd, xa, ya, trace, t, labelLayer, bax._labels, 'b-label');
46+
// NB: These are not ommitted if the lines are not active. The joins must be executed
47+
// in order for them to get cleaned up without a full redraw
48+
drawGridLines(xa, ya, boundaryLayer, aax, 'a-boundary', aax._boundarylines);
49+
drawGridLines(xa, ya, boundaryLayer, bax, 'b-boundary', bax._boundarylines);
7050

71-
drawAxisTitles(gd, labelLayer, trace, t, xa, ya, labelOrientationA, labelOrientationB);
51+
var labelOrientationA = drawAxisLabels(gd, xa, ya, trace, cd0, labelLayer, aax._labels, 'a-label');
52+
var labelOrientationB = drawAxisLabels(gd, xa, ya, trace, cd0, labelLayer, bax._labels, 'b-label');
7253

73-
drawClipPath(trace, t, clipLayer, xa, ya);
74-
}
54+
drawAxisTitles(gd, labelLayer, trace, cd0, xa, ya, labelOrientationA, labelOrientationB);
55+
56+
drawClipPath(trace, cd0, clipLayer, xa, ya);
57+
});
58+
};
7559

7660
function drawClipPath(trace, t, layer, xaxis, yaxis) {
7761
var seg, xp, yp, i;

src/traces/choropleth/plot.js

+2-12
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,8 @@ module.exports = function plot(gd, geo, calcData) {
2222
calcGeoJSON(calcData[i], geo.topojson);
2323
}
2424

25-
function keyFunc(d) { return d[0].trace.uid; }
26-
27-
var gTraces = geo.layers.backplot.select('.choroplethlayer')
28-
.selectAll('g.trace.choropleth')
29-
.data(calcData, keyFunc);
30-
31-
gTraces.enter().append('g')
32-
.attr('class', 'trace choropleth');
33-
34-
gTraces.exit().remove();
35-
36-
gTraces.each(function(calcTrace) {
25+
var choroplethLayer = geo.layers.backplot.select('.choroplethlayer');
26+
Lib.makeTraceGroups(choroplethLayer, calcData, 'trace choropleth').each(function(calcTrace) {
3727
var sel = calcTrace[0].node3 = d3.select(this);
3828

3929
var paths = sel.selectAll('path.choroplethlocation')

0 commit comments

Comments
 (0)