Skip to content

Commit

Permalink
Merge pull request #2505 from plotly/splom-feature
Browse files Browse the repository at this point in the history
Introducing splom traces
  • Loading branch information
etpinard authored Apr 16, 2018
2 parents 14504e5 + a7b08b3 commit 6f25ac6
Show file tree
Hide file tree
Showing 91 changed files with 7,242 additions and 678 deletions.
22 changes: 22 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,25 @@ jobs:
- store_artifacts:
path: build

test-image2:
docker:
- image: plotly/testbed:latest
working_directory: /var/www/streambed/image_server/plotly.js/
steps:
- checkout
- attach_workspace:
at: /var/www/streambed/image_server/plotly.js/
- run:
name: Run and setup container
command: |
supervisord &
npm run docker -- setup
- run:
name: Run image tests
command: ./.circleci/test.sh image2
- store_artifacts:
path: build

test-syntax:
docker:
- image: circleci/node:8.9.4
Expand All @@ -123,6 +142,9 @@ workflows:
- test-image:
requires:
- build
- test-image2:
requires:
- build
- test-syntax:
requires:
- build
4 changes: 4 additions & 0 deletions .circleci/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ case $1 in

image)
npm run test-image || EXIT_STATE=$?
exit $EXIT_STATE
;;

image2)
npm run test-export || EXIT_STATE=$?
npm run test-image-gl2d || EXIT_STATE=$?
exit $EXIT_STATE
Expand Down
1 change: 1 addition & 0 deletions lib/index-gl2d.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var Plotly = require('./core');

Plotly.register([
require('./scattergl'),
require('./splom'),
require('./pointcloud'),
require('./heatmapgl'),
require('./contourgl'),
Expand Down
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Plotly.register([
require('./choropleth'),

require('./scattergl'),
require('./splom'),

require('./pointcloud'),
require('./heatmapgl'),
require('./parcoords'),
Expand Down
11 changes: 11 additions & 0 deletions lib/splom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright 2012-2018, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

module.exports = require('../src/traces/splom');
70 changes: 60 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@
"polybooljs": "^1.2.0",
"regl": "^1.3.1",
"regl-error2d": "^2.0.3",
"regl-line2d": "^3.0.1",
"regl-scatter2d": "^3.0.0",
"regl-line2d": "^3.0.2",
"regl-scatter2d": "^3.0.1",
"regl-splom": "^1.0.0",
"right-now": "^1.0.0",
"robust-orientation": "^1.1.3",
"sane-topojson": "^2.0.0",
Expand Down
20 changes: 20 additions & 0 deletions src/components/fx/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,30 @@
var Lib = require('../../lib');

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

// is trace in given list of subplots?
// does handle splom case
exports.isTraceInSubplots = function isTraceInSubplot(trace, subplots) {
if(trace.type === 'splom') {
var xaxes = trace.xaxes || [];
var yaxes = trace.yaxes || [];
for(var i = 0; i < xaxes.length; i++) {
for(var j = 0; j < yaxes.length; j++) {
if(subplots.indexOf(xaxes[i] + yaxes[j]) !== -1) {
return true;
}
}
}
return false;
}

return subplots.indexOf(exports.getSubplot(trace)) !== -1;
};

// convenience functions for mapping all relevant axes
exports.flat = function flat(subplots, v) {
var out = new Array(subplots.length);
Expand Down
15 changes: 11 additions & 4 deletions src/components/fx/hover.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ function _hover(gd, evt, subplot, noHoverEvent) {
var hoverdistance = fullLayout.hoverdistance === -1 ? Infinity : fullLayout.hoverdistance;
var spikedistance = fullLayout.spikedistance === -1 ? Infinity : fullLayout.spikedistance;

// hoverData: the set of candidate points we've found to highlight
// hoverData: the set of candidate points we've found to highlight
var hoverData = [],

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

subplotId = helpers.getSubplot(trace);
subploti = subplots.indexOf(subplotId);
if(trace.type === 'splom') {
// splom traces do not generate overlay subplots,
// it is safe to assume here splom traces correspond to the 0th subplot
subploti = 0;
subplotId = subplots[subploti];
} else {
subplotId = helpers.getSubplot(trace);
subploti = subplots.indexOf(subplotId);
}

// within one trace mode can sometimes be overridden
mode = hovermode;
Expand Down
56 changes: 41 additions & 15 deletions src/components/grid/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ var gridAttrs = {
values: ['bottom', 'bottom plot', 'top plot', 'top'],
dflt: 'bottom plot',
role: 'info',
editType: 'ticks',
editType: 'plot',
description: [
'Sets where the x axis labels and titles go. *bottom* means',
'the very bottom of the grid. *bottom plot* is the lowest plot',
Expand All @@ -155,7 +155,7 @@ var gridAttrs = {
values: ['left', 'left plot', 'right plot', 'right'],
dflt: 'left plot',
role: 'info',
editType: 'ticks',
editType: 'plot',
description: [
'Sets where the y axis labels and titles go. *left* means',
'the very left edge of the grid. *left plot* is the leftmost plot',
Expand All @@ -165,15 +165,30 @@ var gridAttrs = {
editType: 'plot'
};

function getAxes(layout, grid, axLetter) {
var gridVal = grid[axLetter + 'axes'];
var splomVal = Object.keys((layout._splomAxes || {})[axLetter] || {});

if(Array.isArray(gridVal)) return gridVal;
if(splomVal.length) return splomVal;
}

// the shape of the grid - this needs to be done BEFORE supplyDataDefaults
// so that non-subplot traces can place themselves in the grid
function sizeDefaults(layoutIn, layoutOut) {
var gridIn = layoutIn.grid;
if(!gridIn) return;
var gridIn = layoutIn.grid || {};
var xAxes = getAxes(layoutOut, gridIn, 'x');
var yAxes = getAxes(layoutOut, gridIn, 'y');

if(!layoutIn.grid && !xAxes && !yAxes) return;

var hasSubplotGrid = Array.isArray(gridIn.subplots) && Array.isArray(gridIn.subplots[0]);
var hasXaxes = Array.isArray(gridIn.xaxes);
var hasYaxes = Array.isArray(gridIn.yaxes);
var hasXaxes = Array.isArray(xAxes);
var hasYaxes = Array.isArray(yAxes);
var isSplomGenerated = (
hasXaxes && xAxes !== gridIn.xaxes &&
hasYaxes && yAxes !== gridIn.yaxes
);

var dfltRows, dfltColumns;

Expand All @@ -182,8 +197,8 @@ function sizeDefaults(layoutIn, layoutOut) {
dfltColumns = gridIn.subplots[0].length;
}
else {
if(hasYaxes) dfltRows = gridIn.yaxes.length;
if(hasXaxes) dfltColumns = gridIn.xaxes.length;
if(hasYaxes) dfltRows = yAxes.length;
if(hasXaxes) dfltColumns = xAxes.length;
}

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

var dfltGapX = hasSubplotGrid ? 0.2 : 0.1;
var dfltGapY = hasSubplotGrid ? 0.3 : 0.1;

var dfltSideX, dfltSideY;
if(isSplomGenerated) {
dfltSideX = 'bottom';
dfltSideY = 'left';
}

gridOut._domains = {
x: fillGridPositions('x', coerce, hasSubplotGrid ? 0.2 : 0.1, columns),
y: fillGridPositions('y', coerce, hasSubplotGrid ? 0.3 : 0.1, rows, reversed)
x: fillGridPositions('x', coerce, dfltGapX, dfltSideX, columns),
y: fillGridPositions('y', coerce, dfltGapY, dfltSideY, rows, reversed)
};
}

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

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

var gridIn = layoutIn.grid;
var gridIn = layoutIn.grid || {};
var subplots = layoutOut._subplots;
var hasSubplotGrid = gridOut._hasSubplotGrid;
var rows = gridOut.rows;
Expand Down Expand Up @@ -282,8 +306,10 @@ function contentDefaults(layoutIn, layoutOut) {
}
}
else {
gridOut.xaxes = fillGridAxes(gridIn.xaxes, subplots.xaxis, columns, axisMap, 'x');
gridOut.yaxes = fillGridAxes(gridIn.yaxes, subplots.yaxis, rows, axisMap, 'y');
var xAxes = getAxes(layoutOut, gridIn, 'x');
var yAxes = getAxes(layoutOut, gridIn, 'y');
gridOut.xaxes = fillGridAxes(xAxes, subplots.xaxis, columns, axisMap, 'x');
gridOut.yaxes = fillGridAxes(yAxes, subplots.yaxis, rows, axisMap, 'y');
}

var anchors = gridOut._anchors = {};
Expand Down
Loading

0 comments on commit 6f25ac6

Please sign in to comment.