Skip to content

Commit 6f25ac6

Browse files
authored
Merge pull request #2505 from plotly/splom-feature
Introducing splom traces
2 parents 14504e5 + a7b08b3 commit 6f25ac6

File tree

91 files changed

+7242
-678
lines changed

Some content is hidden

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

91 files changed

+7242
-678
lines changed

.circleci/config.yml

+22
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,25 @@ jobs:
9797
- store_artifacts:
9898
path: build
9999

100+
test-image2:
101+
docker:
102+
- image: plotly/testbed:latest
103+
working_directory: /var/www/streambed/image_server/plotly.js/
104+
steps:
105+
- checkout
106+
- attach_workspace:
107+
at: /var/www/streambed/image_server/plotly.js/
108+
- run:
109+
name: Run and setup container
110+
command: |
111+
supervisord &
112+
npm run docker -- setup
113+
- run:
114+
name: Run image tests
115+
command: ./.circleci/test.sh image2
116+
- store_artifacts:
117+
path: build
118+
100119
test-syntax:
101120
docker:
102121
- image: circleci/node:8.9.4
@@ -123,6 +142,9 @@ workflows:
123142
- test-image:
124143
requires:
125144
- build
145+
- test-image2:
146+
requires:
147+
- build
126148
- test-syntax:
127149
requires:
128150
- build

.circleci/test.sh

+4
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ case $1 in
4141

4242
image)
4343
npm run test-image || EXIT_STATE=$?
44+
exit $EXIT_STATE
45+
;;
46+
47+
image2)
4448
npm run test-export || EXIT_STATE=$?
4549
npm run test-image-gl2d || EXIT_STATE=$?
4650
exit $EXIT_STATE

lib/index-gl2d.js

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var Plotly = require('./core');
1212

1313
Plotly.register([
1414
require('./scattergl'),
15+
require('./splom'),
1516
require('./pointcloud'),
1617
require('./heatmapgl'),
1718
require('./contourgl'),

lib/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Plotly.register([
3131
require('./choropleth'),
3232

3333
require('./scattergl'),
34+
require('./splom'),
35+
3436
require('./pointcloud'),
3537
require('./heatmapgl'),
3638
require('./parcoords'),

lib/splom.js

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

package-lock.json

+60-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,9 @@
9999
"polybooljs": "^1.2.0",
100100
"regl": "^1.3.1",
101101
"regl-error2d": "^2.0.3",
102-
"regl-line2d": "^3.0.1",
103-
"regl-scatter2d": "^3.0.0",
102+
"regl-line2d": "^3.0.2",
103+
"regl-scatter2d": "^3.0.1",
104+
"regl-splom": "^1.0.0",
104105
"right-now": "^1.0.0",
105106
"robust-orientation": "^1.1.3",
106107
"sane-topojson": "^2.0.0",

src/components/fx/helpers.js

+20
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,30 @@
1111
var Lib = require('../../lib');
1212

1313
// look for either subplot or xaxis and yaxis attributes
14+
// does not handle splom case
1415
exports.getSubplot = function getSubplot(trace) {
1516
return trace.subplot || (trace.xaxis + trace.yaxis) || trace.geo;
1617
};
1718

19+
// is trace in given list of subplots?
20+
// does handle splom case
21+
exports.isTraceInSubplots = function isTraceInSubplot(trace, subplots) {
22+
if(trace.type === 'splom') {
23+
var xaxes = trace.xaxes || [];
24+
var yaxes = trace.yaxes || [];
25+
for(var i = 0; i < xaxes.length; i++) {
26+
for(var j = 0; j < yaxes.length; j++) {
27+
if(subplots.indexOf(xaxes[i] + yaxes[j]) !== -1) {
28+
return true;
29+
}
30+
}
31+
}
32+
return false;
33+
}
34+
35+
return subplots.indexOf(exports.getSubplot(trace)) !== -1;
36+
};
37+
1838
// convenience functions for mapping all relevant axes
1939
exports.flat = function flat(subplots, v) {
2040
var out = new Array(subplots.length);

src/components/fx/hover.js

+11-4
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
215215
var hoverdistance = fullLayout.hoverdistance === -1 ? Infinity : fullLayout.hoverdistance;
216216
var spikedistance = fullLayout.spikedistance === -1 ? Infinity : fullLayout.spikedistance;
217217

218-
// hoverData: the set of candidate points we've found to highlight
218+
// hoverData: the set of candidate points we've found to highlight
219219
var hoverData = [],
220220

221221
// searchData: the data to search in. Mostly this is just a copy of
@@ -265,7 +265,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
265265
for(curvenum = 0; curvenum < gd.calcdata.length; curvenum++) {
266266
cd = gd.calcdata[curvenum];
267267
trace = cd[0].trace;
268-
if(trace.hoverinfo !== 'skip' && subplots.indexOf(helpers.getSubplot(trace)) !== -1) {
268+
if(trace.hoverinfo !== 'skip' && helpers.isTraceInSubplots(trace, subplots)) {
269269
searchData.push(cd);
270270
}
271271
}
@@ -338,8 +338,15 @@ function _hover(gd, evt, subplot, noHoverEvent) {
338338
// the rest of this function from running and failing
339339
if(['carpet', 'contourcarpet'].indexOf(trace._module.name) !== -1) continue;
340340

341-
subplotId = helpers.getSubplot(trace);
342-
subploti = subplots.indexOf(subplotId);
341+
if(trace.type === 'splom') {
342+
// splom traces do not generate overlay subplots,
343+
// it is safe to assume here splom traces correspond to the 0th subplot
344+
subploti = 0;
345+
subplotId = subplots[subploti];
346+
} else {
347+
subplotId = helpers.getSubplot(trace);
348+
subploti = subplots.indexOf(subplotId);
349+
}
343350

344351
// within one trace mode can sometimes be overridden
345352
mode = hovermode;

src/components/grid/index.js

+41-15
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ var gridAttrs = {
143143
values: ['bottom', 'bottom plot', 'top plot', 'top'],
144144
dflt: 'bottom plot',
145145
role: 'info',
146-
editType: 'ticks',
146+
editType: 'plot',
147147
description: [
148148
'Sets where the x axis labels and titles go. *bottom* means',
149149
'the very bottom of the grid. *bottom plot* is the lowest plot',
@@ -155,7 +155,7 @@ var gridAttrs = {
155155
values: ['left', 'left plot', 'right plot', 'right'],
156156
dflt: 'left plot',
157157
role: 'info',
158-
editType: 'ticks',
158+
editType: 'plot',
159159
description: [
160160
'Sets where the y axis labels and titles go. *left* means',
161161
'the very left edge of the grid. *left plot* is the leftmost plot',
@@ -165,15 +165,30 @@ var gridAttrs = {
165165
editType: 'plot'
166166
};
167167

168+
function getAxes(layout, grid, axLetter) {
169+
var gridVal = grid[axLetter + 'axes'];
170+
var splomVal = Object.keys((layout._splomAxes || {})[axLetter] || {});
171+
172+
if(Array.isArray(gridVal)) return gridVal;
173+
if(splomVal.length) return splomVal;
174+
}
175+
168176
// the shape of the grid - this needs to be done BEFORE supplyDataDefaults
169177
// so that non-subplot traces can place themselves in the grid
170178
function sizeDefaults(layoutIn, layoutOut) {
171-
var gridIn = layoutIn.grid;
172-
if(!gridIn) return;
179+
var gridIn = layoutIn.grid || {};
180+
var xAxes = getAxes(layoutOut, gridIn, 'x');
181+
var yAxes = getAxes(layoutOut, gridIn, 'y');
182+
183+
if(!layoutIn.grid && !xAxes && !yAxes) return;
173184

174185
var hasSubplotGrid = Array.isArray(gridIn.subplots) && Array.isArray(gridIn.subplots[0]);
175-
var hasXaxes = Array.isArray(gridIn.xaxes);
176-
var hasYaxes = Array.isArray(gridIn.yaxes);
186+
var hasXaxes = Array.isArray(xAxes);
187+
var hasYaxes = Array.isArray(yAxes);
188+
var isSplomGenerated = (
189+
hasXaxes && xAxes !== gridIn.xaxes &&
190+
hasYaxes && yAxes !== gridIn.yaxes
191+
);
177192

178193
var dfltRows, dfltColumns;
179194

@@ -182,8 +197,8 @@ function sizeDefaults(layoutIn, layoutOut) {
182197
dfltColumns = gridIn.subplots[0].length;
183198
}
184199
else {
185-
if(hasYaxes) dfltRows = gridIn.yaxes.length;
186-
if(hasXaxes) dfltColumns = gridIn.xaxes.length;
200+
if(hasYaxes) dfltRows = yAxes.length;
201+
if(hasXaxes) dfltColumns = xAxes.length;
187202
}
188203

189204
var gridOut = layoutOut.grid = {};
@@ -206,17 +221,26 @@ function sizeDefaults(layoutIn, layoutOut) {
206221
var rowOrder = coerce('roworder');
207222
var reversed = rowOrder === 'top to bottom';
208223

224+
var dfltGapX = hasSubplotGrid ? 0.2 : 0.1;
225+
var dfltGapY = hasSubplotGrid ? 0.3 : 0.1;
226+
227+
var dfltSideX, dfltSideY;
228+
if(isSplomGenerated) {
229+
dfltSideX = 'bottom';
230+
dfltSideY = 'left';
231+
}
232+
209233
gridOut._domains = {
210-
x: fillGridPositions('x', coerce, hasSubplotGrid ? 0.2 : 0.1, columns),
211-
y: fillGridPositions('y', coerce, hasSubplotGrid ? 0.3 : 0.1, rows, reversed)
234+
x: fillGridPositions('x', coerce, dfltGapX, dfltSideX, columns),
235+
y: fillGridPositions('y', coerce, dfltGapY, dfltSideY, rows, reversed)
212236
};
213237
}
214238

215239
// coerce x or y sizing attributes and return an array of domains for this direction
216-
function fillGridPositions(axLetter, coerce, dfltGap, len, reversed) {
240+
function fillGridPositions(axLetter, coerce, dfltGap, dfltSide, len, reversed) {
217241
var dirGap = coerce(axLetter + 'gap', dfltGap);
218242
var domain = coerce('domain.' + axLetter);
219-
coerce(axLetter + 'side');
243+
coerce(axLetter + 'side', dfltSide);
220244

221245
var out = new Array(len);
222246
var start = domain[0];
@@ -236,7 +260,7 @@ function contentDefaults(layoutIn, layoutOut) {
236260
// make sure we got to the end of handleGridSizing
237261
if(!gridOut || !gridOut._domains) return;
238262

239-
var gridIn = layoutIn.grid;
263+
var gridIn = layoutIn.grid || {};
240264
var subplots = layoutOut._subplots;
241265
var hasSubplotGrid = gridOut._hasSubplotGrid;
242266
var rows = gridOut.rows;
@@ -282,8 +306,10 @@ function contentDefaults(layoutIn, layoutOut) {
282306
}
283307
}
284308
else {
285-
gridOut.xaxes = fillGridAxes(gridIn.xaxes, subplots.xaxis, columns, axisMap, 'x');
286-
gridOut.yaxes = fillGridAxes(gridIn.yaxes, subplots.yaxis, rows, axisMap, 'y');
309+
var xAxes = getAxes(layoutOut, gridIn, 'x');
310+
var yAxes = getAxes(layoutOut, gridIn, 'y');
311+
gridOut.xaxes = fillGridAxes(xAxes, subplots.xaxis, columns, axisMap, 'x');
312+
gridOut.yaxes = fillGridAxes(yAxes, subplots.yaxis, rows, axisMap, 'y');
287313
}
288314

289315
var anchors = gridOut._anchors = {};

0 commit comments

Comments
 (0)