Skip to content

Commit ba0e3a5

Browse files
authored
Merge pull request #1595 from plotly/carpet-rebase
Carpet plot rebase
2 parents 6255f6d + c2a7092 commit ba0e3a5

File tree

152 files changed

+15665
-98
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+15665
-98
lines changed

lib/carpet.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Copyright 2012-2017, 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+
'use strict';
10+
11+
module.exports = require('../src/traces/carpet');

lib/contourcarpet.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Copyright 2012-2017, 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+
'use strict';
10+
11+
module.exports = require('../src/traces/contourcarpet');

lib/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ Plotly.register([
3636

3737
require('./scattermapbox'),
3838

39+
require('./carpet'),
40+
require('./scattercarpet'),
41+
require('./contourcarpet'),
42+
3943
require('./ohlc'),
4044
require('./candlestick')
4145
]);

lib/scattercarpet.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/**
2+
* Copyright 2012-2017, 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+
'use strict';
10+
11+
module.exports = require('../src/traces/scattercarpet');

package.json

-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555
"dependencies": {
5656
"3d-view": "^2.0.0",
5757
"alpha-shape": "^1.0.0",
58-
"arraytools": "^1.0.0",
5958
"color-rgba": "^1.0.4",
6059
"convex-hull": "^1.0.3",
6160
"country-regex": "^1.1.0",

src/components/drawing/index.js

+10
Original file line numberDiff line numberDiff line change
@@ -678,3 +678,13 @@ drawing.setPointGroupScale = function(selection, x, y) {
678678

679679
return scale;
680680
};
681+
682+
drawing.measureText = function(tester, text, font) {
683+
var dummyText = tester.append('text')
684+
.text(text)
685+
.call(drawing.font, font);
686+
687+
var bbox = drawing.bBox(dummyText.node());
688+
dummyText.remove();
689+
return bbox;
690+
};

src/components/legend/draw.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,8 @@ function handleClick(g, gd, numClicks) {
512512

513513
for(i = 0; i < fullData.length; i++) {
514514
allTraces.push(i);
515+
// Allow the legendonly state through for *all* trace types (including
516+
// carpet for which it's overridden with true/false in supplyDefaults)
515517
traceVisibility.push('legendonly');
516518
}
517519

@@ -542,7 +544,11 @@ function handleClick(g, gd, numClicks) {
542544
if(sameAsLast) {
543545
traceVisibility = true;
544546
}
545-
Plotly.restyle(gd, 'visible', traceVisibility, allTraces);
547+
var visibilityUpdates = [];
548+
for(i = 0; i < fullData.length; i++) {
549+
visibilityUpdates.push(allTraces[i]);
550+
}
551+
Plotly.restyle(gd, 'visible', traceVisibility, visibilityUpdates);
546552
}
547553
}
548554
}

src/components/legend/style.js

+5
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ function styleLines(d) {
6565
showFill = trace.visible && trace.fill && trace.fill !== 'none',
6666
showLine = subTypes.hasLines(trace);
6767

68+
if(trace && trace._module && trace._module.name === 'contourcarpet') {
69+
showLine = trace.contours.showlines;
70+
showFill = trace.contours.coloring === 'fill';
71+
}
72+
6873
var fill = d3.select(this).select('.legendfill').selectAll('path')
6974
.data(showFill ? [d] : []);
7075
fill.enter().append('path').classed('js-fill', true);

src/lib/ensure_array.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Copyright 2012-2017, 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+
'use strict';
10+
11+
/*
12+
* Ensures an array has the right amount of storage space. If it doesn't
13+
* exist, it creates an array. If it does exist, it returns it if too
14+
* short or truncates it in-place.
15+
*
16+
* The goal is to just reuse memory to avoid a bit of excessive garbage
17+
* collection.
18+
*/
19+
module.exports = function ensureArray(out, n) {
20+
if(!Array.isArray(out)) out = [];
21+
22+
// If too long, truncate. (If too short, it will grow
23+
// automatically so we don't care about that case)
24+
out.length = n;
25+
26+
return out;
27+
};

src/lib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ lib.isArray = require('./is_array');
1919
lib.mod = require('./mod');
2020
lib.toLogRange = require('./to_log_range');
2121
lib.relinkPrivateKeys = require('./relink_private');
22+
lib.ensureArray = require('./ensure_array');
2223

2324
var coerceModule = require('./coerce');
2425
lib.valObjects = coerceModule.valObjects;

src/plot_api/plot_api.js

+31-3
Original file line numberDiff line numberDiff line change
@@ -1294,6 +1294,7 @@ function _restyle(gd, aobj, _traces) {
12941294
'autobinx', 'nbinsx', 'xbins', 'xbins.start', 'xbins.end', 'xbins.size',
12951295
'autobiny', 'nbinsy', 'ybins', 'ybins.start', 'ybins.end', 'ybins.size',
12961296
'autocontour', 'ncontours', 'contours', 'contours.coloring',
1297+
'contours.operation', 'contours.value', 'contours.type', 'contours.value[0]', 'contours.value[1]',
12971298
'error_y', 'error_y.visible', 'error_y.value', 'error_y.type',
12981299
'error_y.traceref', 'error_y.array', 'error_y.symmetric',
12991300
'error_y.arrayminus', 'error_y.valueminus', 'error_y.tracerefminus',
@@ -1311,9 +1312,31 @@ function _restyle(gd, aobj, _traces) {
13111312
'line.showscale', 'line.cauto', 'line.autocolorscale', 'line.reversescale',
13121313
'marker.line.showscale', 'marker.line.cauto', 'marker.line.autocolorscale', 'marker.line.reversescale',
13131314
'xcalendar', 'ycalendar',
1314-
'cumulative', 'cumulative.enabled', 'cumulative.direction', 'cumulative.currentbin'
1315+
'cumulative', 'cumulative.enabled', 'cumulative.direction', 'cumulative.currentbin',
1316+
'a0', 'da', 'b0', 'db', 'atype', 'btype',
1317+
'cheaterslope', 'carpet', 'sum',
13151318
];
13161319

1320+
var carpetAxisAttributes = [
1321+
'color', 'smoothing', 'title', 'titlefont', 'titlefont.size', 'titlefont.family',
1322+
'titlefont.color', 'titleoffset', 'type', 'autorange', 'rangemode', 'range',
1323+
'fixedrange', 'cheatertype', 'tickmode', 'nticks', 'tickvals', 'ticktext',
1324+
'ticks', 'mirror', 'ticklen', 'tickwidth', 'tickcolor', 'showticklabels',
1325+
'tickfont', 'tickfont.size', 'tickfont.family', 'tickfont.color', 'tickprefix',
1326+
'showtickprefix', 'ticksuffix', 'showticksuffix', 'showexponent', 'exponentformat',
1327+
'separatethousands', 'tickformat', 'categoryorder', 'categoryarray', 'labelpadding',
1328+
'labelprefix', 'labelsuffix', 'labelfont', 'labelfont.family', 'labelfont.size',
1329+
'labelfont.color', 'showline', 'linecolor', 'linewidth', 'gridcolor', 'gridwidth',
1330+
'showgrid', 'minorgridcount', 'minorgridwidth', 'minorgridcolor', 'startline',
1331+
'startlinecolor', 'startlinewidth', 'endline', 'endlinewidth', 'endlinecolor',
1332+
'tick0', 'dtick', 'arraytick0', 'arraydtick', 'hoverformat', 'tickangle'
1333+
];
1334+
1335+
for(i = 0; i < carpetAxisAttributes.length; i++) {
1336+
recalcAttrs.push('aaxis.' + carpetAxisAttributes[i]);
1337+
recalcAttrs.push('baxis.' + carpetAxisAttributes[i]);
1338+
}
1339+
13171340
for(i = 0; i < traces.length; i++) {
13181341
if(Registry.traceIs(fullData[traces[i]], 'box')) {
13191342
recalcAttrs.push('name');
@@ -1657,9 +1680,14 @@ function _restyle(gd, aobj, _traces) {
16571680
doextra(axlist.map(rangeAttr), [0, 1], 0);
16581681
}
16591682
flags.docalc = true;
1683+
1684+
} else if(replotAttrs.indexOf(aiAboveArray) !== -1) {
1685+
flags.doplot = true;
1686+
} else if(aiAboveArray.indexOf('aaxis') === 0 || aiAboveArray.indexOf('baxis') === 0) {
1687+
flags.doplot = true;
1688+
} else if(autorangeAttrs.indexOf(aiAboveArray) !== -1) {
1689+
flags.docalcAutorange = true;
16601690
}
1661-
else if(replotAttrs.indexOf(aiAboveArray) !== -1) flags.doplot = true;
1662-
else if(autorangeAttrs.indexOf(aiAboveArray) !== -1) flags.docalcAutorange = true;
16631691
}
16641692

16651693
// do we need to force a recalc?

src/plots/cartesian/axes.js

+2
Original file line numberDiff line numberDiff line change
@@ -1665,6 +1665,8 @@ axes.doTicks = function(gd, axid, skipTitle) {
16651665
ticksign = ticksign.map(function(v) { return -v; });
16661666
}
16671667

1668+
if(!ax.visible) return;
1669+
16681670
// remove zero lines, grid lines, and inside ticks if they're within
16691671
// 1 pixel of the end
16701672
// The key case here is removing zero lines when the axis bound is zero.

src/plots/cartesian/axis_defaults.js

+16-13
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
4747
return Lib.coerce2(containerIn, containerOut, layoutAttributes, attr, dflt);
4848
}
4949

50+
var visible = coerce('visible', !options.cheateronly);
51+
5052
var axType = containerOut.type;
5153

5254
if(axType === 'date') {
@@ -56,6 +58,20 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
5658

5759
setConvert(containerOut, layoutOut);
5860

61+
var autoRange = coerce('autorange', !containerOut.isValidRange(containerIn.range));
62+
63+
if(autoRange) coerce('rangemode');
64+
65+
coerce('range');
66+
containerOut.cleanRange();
67+
68+
handleCategoryOrderDefaults(containerIn, containerOut, coerce);
69+
containerOut._initialCategories = axType === 'category' ?
70+
orderedCategories(letter, containerOut.categoryorder, containerOut.categoryarray, options.data) :
71+
[];
72+
73+
if(!visible) return containerOut;
74+
5975
var dfltColor = coerce('color');
6076
// if axis.color was provided, use it for fonts too; otherwise,
6177
// inherit from global font color in case that was provided.
@@ -68,17 +84,9 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
6884
color: dfltFontColor
6985
});
7086

71-
var autoRange = coerce('autorange', !containerOut.isValidRange(containerIn.range));
72-
73-
if(autoRange) coerce('rangemode');
74-
75-
coerce('range');
76-
containerOut.cleanRange();
77-
7887
handleTickValueDefaults(containerIn, containerOut, coerce, axType);
7988
handleTickLabelDefaults(containerIn, containerOut, coerce, axType, options);
8089
handleTickMarkDefaults(containerIn, containerOut, coerce, options);
81-
handleCategoryOrderDefaults(containerIn, containerOut, coerce);
8290

8391
var lineColor = coerce2('linecolor', dfltColor),
8492
lineWidth = coerce2('linewidth'),
@@ -109,10 +117,5 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
109117
delete containerOut.zerolinewidth;
110118
}
111119

112-
// fill in categories
113-
containerOut._initialCategories = axType === 'category' ?
114-
orderedCategories(letter, containerOut.categoryorder, containerOut.categoryarray, options.data) :
115-
[];
116-
117120
return containerOut;
118121
};

src/plots/cartesian/graph_interact.js

+5
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,11 @@ function hover(gd, evt, subplot) {
467467
if(!cd || !cd[0] || !cd[0].trace || cd[0].trace.visible !== true) continue;
468468

469469
trace = cd[0].trace;
470+
471+
// Explicitly bail out for these two. I don't know how to otherwise prevent
472+
// the rest of this function from running and failing
473+
if(['carpet', 'contourcarpet'].indexOf(trace._module.name) !== -1) continue;
474+
470475
subplotId = getSubplot(trace);
471476
subploti = subplots.indexOf(subplotId);
472477

src/plots/cartesian/index.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,11 @@ exports.plot = function(gd, traces, transitionOpts, makeOnCompleteCallback) {
6363
// Skip trace if whitelist provided and it's not whitelisted:
6464
// if (Array.isArray(traces) && traces.indexOf(i) === -1) continue;
6565
if(trace.xaxis + trace.yaxis === subplot) {
66+
// XXX: Should trace carpet dependencies. Only replot all carpet plots if the carpet
67+
// axis has actually changed:
68+
//
6669
// If this trace is specifically requested, add it to the list:
67-
if(traces.indexOf(trace.index) !== -1) {
70+
if(traces.indexOf(trace.index) !== -1 || trace.carpet) {
6871
// Okay, so example: traces 0, 1, and 2 have fill = tonext. You animate
6972
// traces 0 and 2. Trace 1 also needs to be updated, otherwise its fill
7073
// is outdated. So this retroactively adds the previous trace if the
@@ -300,6 +303,7 @@ function makeSubplotLayer(plotinfo) {
300303
joinLayer(parent, 'g', 'imagelayer');
301304
joinLayer(parent, 'g', 'maplayer');
302305
joinLayer(parent, 'g', 'barlayer');
306+
joinLayer(parent, 'g', 'carpetlayer');
303307
joinLayer(parent, 'g', 'boxlayer');
304308
joinLayer(parent, 'g', 'scatterlayer');
305309
}

src/plots/cartesian/layout_attributes.js

+9
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ var constants = require('./constants');
1616

1717

1818
module.exports = {
19+
visible: {
20+
valType: 'boolean',
21+
role: 'info',
22+
description: [
23+
'A single toggle to hide the axis while preserving interaction like dragging.',
24+
'Default is true when a cheater plot is present on the axis, otherwise',
25+
'false'
26+
].join(' ')
27+
},
1928
color: {
2029
valType: 'color',
2130
dflt: colorAttrs.defaultLine,

src/plots/cartesian/layout_defaults.js

+19-1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
2929
yaListCartesian = [],
3030
xaListGl2d = [],
3131
yaListGl2d = [],
32+
xaListCheater = [],
33+
xaListNonCheater = [],
3234
outerTicks = {},
3335
noGrids = {},
3436
i;
@@ -51,6 +53,21 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
5153
var xaName = axisIds.id2name(trace.xaxis),
5254
yaName = axisIds.id2name(trace.yaxis);
5355

56+
// Two things trigger axis visibility:
57+
// 1. is not carpet
58+
// 2. carpet that's not cheater
59+
if(!Registry.traceIs(trace, 'carpet') || (trace.type === 'carpet' && !trace._cheater)) {
60+
if(xaName) Lib.pushUnique(xaListNonCheater, xaName);
61+
}
62+
63+
// The above check for definitely-not-cheater is not adequate. This
64+
// second list tracks which axes *could* be a cheater so that the
65+
// full condition triggering hiding is:
66+
// *could* be a cheater and *is not definitely visible*
67+
if(trace.type === 'carpet' && trace._cheater) {
68+
if(xaName) Lib.pushUnique(xaListCheater, xaName);
69+
}
70+
5471
// add axes implied by traces
5572
if(xaName && listX.indexOf(xaName) === -1) listX.push(xaName);
5673
if(yaName && listY.indexOf(yaName) === -1) listY.push(yaName);
@@ -168,7 +185,8 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
168185
showGrid: !noGrids[axName],
169186
data: fullData,
170187
bgColor: bgColor,
171-
calendar: layoutOut.calendar
188+
calendar: layoutOut.calendar,
189+
cheateronly: axLetter === 'x' && (xaListCheater.indexOf(axName) !== -1 && xaListNonCheater.indexOf(axName) === -1)
172190
};
173191

174192
handleAxisDefaults(axLayoutIn, axLayoutOut, coerce, defaultOptions, layoutOut);

src/plots/gl3d/layout/axis_attributes.js

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ var extendFlat = require('../../../lib/extend').extendFlat;
1414

1515

1616
module.exports = {
17+
visible: axesAttrs.visible,
1718
showspikes: {
1819
valType: 'boolean',
1920
role: 'info',

0 commit comments

Comments
 (0)