8000 Introducing splom traces by etpinard · Pull Request #2505 · plotly/plotly.js · GitHub
[go: up one dir, main page]

Skip to content

Introducing splom traces #2505

10000
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

Merged
merged 108 commits into from
Apr 16, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
44dc3d8
:palm_tree: pie base plot module
etpinard Mar 12, 2018
c56e35e
[tmp] pull splom dep from github repo
etpinard Mar 28, 2018
29ca0ed
lib splom
etpinard Mar 28, 2018
8b5af93
first cut splom attributes and defaults
etpinard Mar 28, 2018
3be9569
adapt grid and cartesian axis logic for sploms
etpinard Mar 28, 2018
76c64e5
first cut splom auto axis type detection
etpinard Mar 28, 2018
59588cc
first cut splom plot
etpinard Mar 28, 2018
66494c7
some linting
etpinard Mar 28, 2018
20f01cc
hook in splom drag
etpinard Mar 28, 2018
c5cda6b
add _hasOnlyLargeSploms flag
etpinard Mar 28, 2018
89fb6bb
add a few DRY up TODOs
etpinard Mar 28, 2018
9cac919
first cut splom defaults test
etpinard Mar 28, 2018
fda1b34
add two splom mocks (image generation is broken currently)
etpinard Mar 28, 2018
cf485b7
fixup c5cda6b
etpinard Mar 28, 2018
fc6c895
fixup PlotSchema.get() for splom
etpinard Mar 28, 2018
7be161b
Enable hover for splom
dy Mar 28, 2018
80dd61e
fixup _scene ref in calcdata stash
etpinard Mar 28, 2018
0fb65dd
first pass splom basePlotModule clean step
etpinard Mar 28, 2018
d50746b
add splom mocks
etpinard Mar 28, 2018
a3c87da
fixup 0fb65dd
etpinard Mar 28, 2018
c4c1514
:hocho: obsolete file
etpinard Mar 28, 2018
469e4cd
add regl_utils lib module
etpinard Mar 28, 2018
c0c5a6e
clear regl colors once per drawData pass
etpinard Mar 28, 2018
d02f572
clear regl colors once per drawData pass
etpinard Mar 28, 2018
60df466
Add basic hover indexes calc
dy Mar 28, 2018
e7b02c0
more robust handling of splom in fx/hover.js
etpinard Mar 28, 2018
658c529
split prepareRegl and clearGlCanvases into two modules
etpinard Mar 28, 2018
2b6c58e
fix and :lock: regl-line2d grids
etpinard Mar 29, 2018
eab3768
Add O(N) hover
dy Mar 29, 2018
b6359ef
Fold hover calc
dy Mar 29, 2018
a37abfb
Remove compare hovermode
dy Mar 29, 2018
4470447
Remove hovermode attr
dy Mar 29, 2018
aaa42c6
Provide selection scaffold
dy Mar 29, 2018
a077c3f
:hocho: (x|y)direction
etpinard Mar 29, 2018
f442f59
fixup autotype for splom trace w/ visible false dims
etpinard Mar 29, 2018
4f68cba
make splom (x|y)axes items by 'subplotid'
etpinard Mar 29, 2018
07d59d5
fix handling of splom visible false dimensions
etpinard Mar 29, 2018
2a048a9
bump regl-scattermatrix
etpinard Mar 29, 2018
697a127
Preven errors on non-splom traces
dy Mar 29, 2018
32118b0
fixup and test splom clean method
etpinard Mar 29, 2018
bb11313
Fixup lines
dy Mar 30, 2018
1bc95d5
swap showdiagonal -> diagonal.visible & better :books:
etpinard Mar 30, 2018
419458c
manually stringify regex during PlotSchema.get()
etpinard Mar 30, 2018
9162265
some DRYing in PlotSchema.get()
etpinard Mar 30, 2018
e14013b
make supplyTraceDefaults work again with splom
alexcjohnson Mar 30, 2018
22e8c7e
Make default splom selection
dy Apr 4, 2018
d072121
Make rough dynamic selection
dy Apr 5, 2018
02ed2eb
move doAutoRangeAndConstraints, drawData and finalDraw to subroutines
etpinard Apr 5, 2018
3ad1eaa
add 'axrange' editType
etpinard Apr 5, 2018
bb02281
speed up doModeBar subroutines for cartesian subplots
etpinard Apr 5, 2018
d07ae70
improve fullLayout._has()
etpinard Apr 5, 2018
468119e
speed up dragbox
etpinard Apr 5, 2018
0979272
clean splom drag logic
etpinard Apr 5, 2018
ebb35ce
lint in plot_api
etpinard Apr 5, 2018
37b585e
Handle upper/lowe halves
dy Apr 5, 2018
92a37c8
bump deps
etpinard Apr 5, 2018
ce379a1
1st cut showupperhalf / showlowerhalf
etpinard Apr 6, 2018
f9090b7
(fixup) add draggedPts to scattercarpet categories
etpinard Apr 6, 2018
b28052b
clean splom drag logic
etpinard Apr 5, 2018
f2569c3
draw regl-line2d grid lines before splom on drag
etpinard Apr 6, 2018
b283919
better grid.(x|y)side defaults for splom 8000
etpinard Apr 6, 2018
571950e
wip work for !diagonal.visible + !show(upper|lower)half
etpinard Apr 6, 2018
76d8ace
bump deps
etpinard Apr 6, 2018
2d39ea7
bump regl-scatter2d dep (fix destroy method)
etpinard Apr 9, 2018
7f916b0
fixups for `diagonal.visible: false`
etpinard Apr 9, 2018
0c901b5
fixup i === j subplot logic and baselines
etpinard Apr 9, 2018
1193e6c
update baseline (from ce379a1d7c2a335733d1c763ab06265606a86154)
etpinard Apr 9, 2018
99712dd
update splom baselines (not sure why that happened?)
etpinard Apr 9, 2018
129e1f2
:hocho: splom 'mode' (for now)
etpinard Apr 9, 2018
b2ee736
Merge branch 'splom-feature' into splom-zoom-perf
etpinard Apr 9, 2018
a6f2664
fixup splom attributes
etpinard Apr 9, 2018
5f0c828
choose more heavy duty patch for setting mode: 'markers' in splom traces
etpinard Apr 9, 2018
0d5a638
add Plotly.react test for splom :tada:
etpinard Apr 9, 2018
a0b2574
Merge branch 'splom-feature' into splom-zoom-perf
etpinard Apr 9, 2018
7ae7159
fix and :lock: regl-line2d grid data
etpinard Apr 10, 2018
d4a2a53
fix and :lock: in-and-out of hasOnlyLargeSploms regime
etpinard Apr 10, 2018
f07ff4b
set visible:false if showupper & showlower & diagonal.visible are false
etpinard Apr 10, 2018
fa8adee
split image tests into 2 jobs
etpinard Apr 10, 2018
d3fe40d
replace selectAll with for(k in _plots) loop
etpinard Apr 10, 2018
cc1b3de
fixup and :lock: dragbox with linked y axes
etpinard Apr 10, 2018
45266ed
fix and :lock: marker.symbol and arrayOk marker attrs
etpinard Apr 10, 2018
a0caefd
fix and :lock: splom on log and date axes
etpinard Apr 11, 2018
2e6b610
ping imagetest before trying to create baseline img
etpinard Apr 11, 2018
980855c
Merge branch 'splom-feature' into splom-zoom-perf
etpinard Apr 11, 2018
f7d637d
:books: link TODOs to gh issues
etpinard Apr 11, 2018
da81a0e
no need to stash splom grid data on fullLayout
etpinard Apr 11, 2018
74abb7f
sort basePlotModules so that splom is always drawn below scattergl
etpinard Apr 11, 2018
062d4a3
fixup splom + scattergl select
etpinard Apr 11, 2018
978a70e
Merge pull request #2527 from plotly/splom-zoom-perf
etpinard Apr 11, 2018
b868959
move clearSelect to cartesian/select.js
etpinard Apr 11, 2018
e38a0a6
rm obsolete scattergl scene clearSelect (confirmed by @dy)
etpinard Apr 11, 2018
651901d
fixup splom with cartesian mock/baseline
etpinard Apr 11, 2018
9aea0ba
fixup scattergl+splom style() on select
etpinard Apr 11, 2018
71a0395
try at robust subplot-to-subplot selections
etpinard Apr 11, 2018
24dad16
:hocho: obsolete comment
etpinard Apr 12, 2018
9d0bcfd
fixup cross-subplot select logic brought up in 71a0395
etpinard Apr 12, 2018
6fd6919
fixup relayout for 'grid.(x|y)side'
etpinard Apr 12, 2018
31e34fa
fix and :lock: basePlotModules sorting
etpinard Apr 12, 2018
a79f5dc
add splom hover/selection/drag tests
etpinard Apr 12, 2018
31836f2
:pencil2: splom meta description + register grid in splom index
etpinard Apr 12, 2018
6cc634a
:cow2: in various new splom code & comment
etpinard Apr 12, 2018
c7b81ec
typos in :books:
etpinard Apr 13, 2018
8e9eaff
Merge branch 'master' into splom-feature
etpinard Apr 13, 2018
ad5abb6
Update deps, adapt line2d code
dy Apr 13, 2018
c98071f
Fix select in splom large
dy Apr 13, 2018
2d93469
sub regl-splom -> regl-scattermatrix in comments
etpinard Apr 13, 2018
6c5a1e7
Fix removing line passes
dy Apr 13, 2018
a7b08b3
clear canvas on doTicksRelayout when hasOnlyLargeSploms
etpinard Apr 16, 2018
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
Prev Previous commit
Next Next commit
first cut splom plot
- only markers for now, reuse scattergl convert logic
  for markers
- use a splom basePlotModule to handle multiple traces
  and splom-wide field (like regl-line2d grids coming up)
  • Loading branch information
etpinard committed Mar 28, 2018
commit 59588cc155692921f6823c039984ed8a2913be7b
2 changes: 1 addition & 1 deletion src/traces/scatter/calc.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function calcAxisExpansion(gd, trace, xa, ya, x, y, ppad) {
}

// if no error bars, markers or text, or fill to y=0 remove x padding
else if(!trace.error_y.visible && (
else if(!(trace.error_y || {}).visible && (
['tonexty', 'tozeroy'].indexOf(trace.fill) !== -1 ||
(!subTypes.hasMarkers(trace) && !subTypes.hasText(trace))
)) {
Expand Down
1 change: 1 addition & 0 deletions src/traces/scattergl/convert.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ function convertErrorBarPositions(gd, trace, positions) {

module.exports = {
convertStyle: convertStyle,
convertMarkerStyle: convertMarkerStyle,
convertLinePositions: convertLinePositions,
convertErrorBarPositions: convertErrorBarPositions
};
64 changes: 64 additions & 0 deletions src/traces/splom/base_plot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* 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';

var createRegl = require('regl');

var Registry = require('../../registry');
var getModuleCalcData = require('../../plots/get_data').getModuleCalcData;
var Cartesian = require('../../plots/cartesian');

var SPLOM = 'splom';

function plot(gd) {
var fullLayout = gd._fullLayout;
var _module = Registry.getModule(SPLOM);
var splomCalcData = getModuleCalcData(gd.calcdata, _module);

// clear gl frame, if any, since we preserve drawing buffer
if(fullLayout._glcanvas && fullLayout._glcanvas.size()) {
fullLayout._glcanvas.each(function(d) {
if(d.regl) d.regl.clear({color: true});
});
}

// make sure proper regl instances are created
fullLayout._glcanvas.each(function(d) {
if(d.regl || d.pick) return;
d.regl = createRegl({
canvas: this,
attributes: {
antialias: !d.pick,
preserveDrawingBuffer: true
},
extensions: ['ANGLE_instanced_arrays', 'OES_element_index_uint'],
pixelRatio: gd._context.plotGlPixelRatio || global.devicePixelRatio
});
});

_module.plot(gd, {}, splomCalcData);
}

function clean(newFullData, newFullLayout, oldFullData, oldFullLayout) {
// TODO clear regl-splom instances
// TODO clear regl-line2d grid instance!

Cartesian.clean(newFullData, newFullLayout, oldFullData, oldFullLayout);
}

module.exports = {
name: SPLOM,
attrRegex: Cartesian.attrRegex,
layoutAttributes: Cartesian.layoutAttributes,
supplyLayoutDefaults: Cartesian.supplyLayoutDefaults,
drawFramework: Cartesian.drawFramework,
plot: plot,
clean: clean,
toSVG: Cartesian.toSVG
};
7 changes: 7 additions & 0 deletions src/traces/splom/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('mode', traceOut._commonLength < PTS_LINESONLY ? 'lines+markers' : 'lines');
coerce('text');

// TODO just markers for now
traceOut.mode = 'markers';

if(subTypes.hasLines(traceOut)) {
handleLineDefaults(traceIn, traceOut, defaultColor, layout, coerce);
coerce('connectgaps');
Expand All @@ -44,11 +47,13 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
coerce('marker.line.width', isOpen || isBubble ? 1 : 0);
}

// TODO not implemented yet
coerce('xdirection');
coerce('ydirection');

handleAxisDefaults(traceIn, traceOut, layout, coerce);

// TODO not implemented yet
coerce('showdiagonal');
coerce('showupperhalf');
coerce('showlowerhalf');
Expand Down Expand Up @@ -115,6 +120,8 @@ function handleAxisDefaults(traceIn, traceOut, layout, coerce) {
var xaxes = coerce('xaxes', xaxesDflt);
var yaxes = coerce('yaxes', yaxesDflt);

// TODO what to do when xaxes.length or yaxes.length !== dimLength ???
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess if dimLength is longer it's easy to just drop the later dims. What if xaxes.length !== yaxes.length or dimLength is shorter than xaxes or yaxes? The easy thing to do is just truncate them all to the same length, and perhaps until we have a clear use case otherwise we should just do that.

Related though: if you have several splom traces but they don't share all the same dimensions, you could of course handle this by specifying xaxes and yaxes for each, but could you also just pass in an empty dimension for ones you want to skip? If that takes more than 5 minutes to implement though, skip it for now and leave it as an item for future expansion.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh you already have dimensions[i].visible: false, nice! That should take care of my "related" point, it'll still reserve x/y axes for these dimensions, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The easy thing to do is just truncate them all to the same length, and perhaps until we have a clear use case otherwise we should just do that.

That sounds right to me. I'll go with that unless anyone disagrees.

That should take care of my "related" point, it'll still reserve x/y axes for these dimensions, right?

Yes that should take care of it, but I haven't tried that yet. Putting that on my TODO list 📝

Copy link
Contributor Author
@etpinard etpinard Mar 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.... thanks for all these comments by the way. I hope you don't find the _hasOnlyLargeSplom flag too hacky.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alexcjohnson just to confirm what you meant in your related point:

Plotly.newPlot(gd, [{
  type: 'splom',
  dimensions: [{
    values: [1, 2, 3]
  }, {
    values: [4, 5, 6]
  }]
}, {
  type: 'splom',
  dimensions: [{
    visible: false
  }, {
    visible: false,
  }, {
    values: [1, 2, 3]
  }, {
    values: [4, 5, 6]
  }]
}])

gives:

image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 07d59d5


for(i = 0; i < dimLength; i++) {
var dim = dimensions[i];
var xa = xaxes[i];
Expand Down
220 changes: 220 additions & 0 deletions src/traces/splom/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/**
* 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';

var createMatrix = require('regl-scattermatrix');

var Lib = require('../../lib');
var AxisIDs = require('../../plots/cartesian/axis_ids');

var calcMarkerSize = require('../scatter/calc').calcMarkerSize;
var calcAxisExpansion = require('../scatter/calc').calcAxisExpansion;
var calcColorscales = require('../scatter/colorscale_calc');
var convertMarkerStyle = require('../scattergl/convert').convertMarkerStyle;

var BADNUM = require('../../constants/numerical').BADNUM;
var TOO_MANY_POINTS = require('../scattergl/constants').TOO_MANY_POINTS;

function calc(gd, trace) {
var stash = {};
var opts = {};
var i, xa, ya;

var dimLength = trace.dimensions.length;
var hasTooManyPoints = (dimLength * trace._commonLength) > TOO_MANY_POINTS;
var matrix = opts.data = new Array(dimLength);

for(i = 0; i < dimLength; i++) {
// using xa or ya should make no difference here
xa = AxisIDs.getFromId(gd, trace.xaxes[i]);
matrix[i] = makeCalcdata(xa, trace, trace.dimensions[i]);
}

calcColorscales(trace);
Lib.extendFlat(opts, convertMarkerStyle(trace));

for(i = 0; i < dimLength; i++) {
xa = AxisIDs.getFromId(gd, trace.xaxes[i]);
ya = AxisIDs.getFromId(gd, trace.yaxes[i]);

// Re-use SVG scatter axis expansion routine except
// for graph with very large number of points where it
// performs poorly.
// In big data case, fake Axes.expand outputs with data bounds,
// and an average size for array marker.size inputs.
var ppad;
if(hasTooManyPoints) {
ppad = 2 * (opts.sizeAvg || Math.max(opts.size, 3));
} else {
ppad = calcMarkerSize(trace, trace._commonLength);
}
calcAxisExpansion(gd, trace, xa, ya, matrix[i], matrix[i], ppad);
}


var scene = stash.scene = sceneUpdate(gd, stash);
if(!scene.matrix) scene.matrix = true;
scene.matrixOptions = opts;

return [{x: false, y: false, t: stash, trace: trace}];
}

function makeCalcdata(ax, trace, dim) {
var i;

var cdata = ax.makeCalcdata({
v: dim.values,
vcalendar: trace.calendar
}, 'v');

for(i = 0; i < cdata.length; i++) {
cdata[i] = cdata[i] === BADNUM ? NaN : cdata[i];
}

if(ax.type === 'log') {
for(i = 0; i < cdata.length; i++) {
cdata[i] = ax.c2l(cdata[i]);
}
}

return cdata;
}

// TODO do we need this?
function sceneUpdate(gd, stash) {
var scene = stash._scene;

var reset = {
dirty: true,
opts: null
};

var first = {
selectBatch: null,
unselectBatch: null,
matrix: false,
select: null
};

if(!scene) {
scene = stash._scene = Lib.extendFlat({}, reset, first);

// TODO should we use something like this on drag?
scene.update = function update(opt) {
if(scene.matrix) scene.matrix.update(opt);
scene.draw();
};

scene.draw = function draw() {
if(scene.matrix) scene.matrix.draw();

// TODO selection stuff

// do we need to use this flag anywhere??
scene.dirty = false;
};

// make sure canvas is clear
scene.clear = function clear() {
// TODO
};

// remove selection
scene.clearSelect = function clearSelect() {
if(!scene.selectBatch) return;
scene.selectBatch = null;
scene.unselectBatch = null;
scene.matrix.update(scene.opts);
scene.clear();
scene.draw();
};

// remove scene resources
scene.destroy = function destroy() {
if(scene.matrix) scene.matrix.destroy();

scene.opts = null;
scene.selectBatch = null;
scene.unselectBatch = null;

stash._scene = null;
};
}

// In case if we have scene from the last calc - reset data
if(!scene.dirty) {
Lib.extendFlat(scene, reset);
}

return scene;
}

function plot(gd, _, cdata) {
if(!cdata.length) return;

for(var i = 0; i < cdata.length; i++) {
plotOne(gd, cdata[i][0]);
}
}

function plotOne(gd, cd0) {
var fullLayout = gd._fullLayout;
var gs = fullLayout._size;
var scene = cd0.t.scene;
var trace = cd0.trace;
var regl = fullLayout._glcanvas.data()[0].regl;

var dimLength = trace.dimensions.length;
var viewOpts = {
ranges: new Array(dimLength),
domains: new Array(dimLength)
};

for(var i = 0; i < dimLength; i++) {
var xa = AxisIDs.getFromId(gd, trace.xaxes[i]);
var ya = AxisIDs.getFromId(gd, trace.yaxes[i]);
viewOpts.ranges[i] = [xa.range[0], ya.range[0], xa.range[1], ya.range[1]];
viewOpts.domains[i] = [xa.domain[0], ya.domain[0], xa.domain[1], ya.domain[1]];
}

viewOpts.viewport = [gs.l, gs.b, fullLayout.width - gs.r, fullLayout.height - gs.t];

if(scene.matrix === true) {
scene.matrix = createMatrix(regl);
}

scene.matrix.update(scene.matrixOptions);
scene.matrix.update(viewOpts);
scene.matrix.draw();
}

// TODO splom 'needs' the grid component, register it here?

module.exports = {
moduleType: 'trace',
name: 'splom',

basePlotModule: require('./base_plot'),
categories: ['gl', 'regl', 'cartesian', 'symbols', 'markerColorscale', 'showLegend', 'scatter-like'],

attributes: require('./attributes'),
supplyDefaults: require('./defaults'),

calc: calc,
plot: plot,
hoverPoints: function() {},
selectPoints: function() {},
style: function() {},

meta: {
description: [
'SPLOM !!!'
].join(' ')
}
};
0