Skip to content

Commit 85ca2b2

Browse files
authored
Merge pull request #1256 from monfera/parcoords-squashed-2
parcoords added
2 parents 027d97f + 0d65012 commit 85ca2b2

28 files changed

+3091
-4
lines changed

lib/index-gl2d.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ Plotly.register([
1414
require('./scattergl'),
1515
require('./pointcloud'),
1616
require('./heatmapgl'),
17-
require('./contourgl')
17+
require('./contourgl'),
18+
require('./parcoords')
1819
]);
1920

2021
module.exports = Plotly;

lib/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Plotly.register([
3232
require('./scattergl'),
3333
require('./pointcloud'),
3434
require('./heatmapgl'),
35+
require('./parcoords'),
3536

3637
require('./scattermapbox'),
3738

lib/parcoords.js

Lines changed: 11 additions & 0 deletions
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/parcoords');

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
"version": "npm run build && git add -A dist src build",
4949
"postversion": "node -e \"console.log('Version bumped and committed. If ok, run: git push && git push --tags')\""
5050
},
51+
"browserify": {
52+
"transform": ["glslify"]
53+
},
5154
"dependencies": {
5255
"3d-view": "^2.0.0",
5356
"alpha-shape": "^1.0.0",
@@ -79,10 +82,11 @@
7982
"mapbox-gl": "^0.22.0",
8083
"mouse-change": "^1.4.0",
8184
"mouse-wheel": "^1.0.2",
82-
"ndarray": "^1.0.16",
85+
"ndarray": "^1.0.18",
8386
"ndarray-fill": "^1.0.1",
8487
"ndarray-homography": "^1.0.0",
8588
"ndarray-ops": "^1.2.2",
89+
"regl": "^1.3.0",
8690
"right-now": "^1.0.0",
8791
"robust-orientation": "^1.1.3",
8892
"sane-topojson": "^2.0.0",
@@ -103,6 +107,7 @@
103107
"fs-extra": "^2.0.0",
104108
"fuse.js": "^2.6.1",
105109
"glob": "^7.0.0",
110+
"glslify": "^4.0.0",
106111
"gzip-size": "^3.0.0",
107112
"image-size": "^0.5.1",
108113
"jasmine-core": "^2.4.1",

src/traces/parcoords/attributes.js

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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+
var colorAttributes = require('../../components/colorscale/color_attributes');
12+
var colorbarAttrs = require('../../components/colorbar/attributes');
13+
var colorscales = require('../../components/colorscale/scales');
14+
var axesAttrs = require('../../plots/cartesian/layout_attributes');
15+
16+
var extendDeep = require('../../lib/extend').extendDeep;
17+
var extendFlat = require('../../lib/extend').extendFlat;
18+
19+
module.exports = {
20+
21+
domain: {
22+
x: {
23+
valType: 'info_array',
24+
role: 'info',
25+
items: [
26+
{valType: 'number', min: 0, max: 1},
27+
{valType: 'number', min: 0, max: 1}
28+
],
29+
dflt: [0, 1],
30+
description: [
31+
'Sets the horizontal domain of this `parcoords` trace',
32+
'(in plot fraction).'
33+
].join(' ')
34+
},
35+
y: {
36+
valType: 'info_array',
37+
role: 'info',
38+
items: [
39+
{valType: 'number', min: 0, max: 1},
40+
{valType: 'number', min: 0, max: 1}
41+
],
42+
dflt: [0, 1],
43+
description: [
44+
'Sets the vertical domain of this `parcoords` trace',
45+
'(in plot fraction).'
46+
].join(' ')
47+
}
48+
},
49+
50+
dimensions: {
51+
_isLinkedToArray: 'dimension',
52+
label: {
53+
valType: 'string',
54+
role: 'info',
55+
description: 'The shown name of the dimension.'
56+
},
57+
tickvals: axesAttrs.tickvals,
58+
ticktext: axesAttrs.ticktext,
59+
tickformat: {
60+
valType: 'string',
61+
dflt: '3s',
62+
role: 'style',
63+
description: [
64+
'Sets the tick label formatting rule using d3 formatting mini-language',
65+
'which is similar to those of Python. See',
66+
'https://github.com/d3/d3-format/blob/master/README.md#locale_format'
67+
].join(' ')
68+
},
69+
visible: {
70+
valType: 'boolean',
71+
dflt: true,
72+
role: 'info',
73+
description: 'Shows the dimension when set to `true` (the default). Hides the dimension for `false`.'
74+
},
75+
range: {
76+
valType: 'info_array',
77+
role: 'info',
78+
items: [
79+
{valType: 'number'},
80+
{valType: 'number'}
81+
],
82+
description: [
83+
'The domain range that represents the full, shown axis extent. Defaults to the `values` extent.',
84+
'Must be an array of `[fromValue, toValue]` with finite numbers as elements.'
85+
].join(' ')
86+
},
87+
constraintrange: {
88+
valType: 'info_array',
89+
role: 'info',
90+
items: [
91+
{valType: 'number'},
92+
{valType: 'number'}
93+
],
94+
description: [
95+
'The domain range to which the filter on the dimension is constrained. Must be an array',
96+
'of `[fromValue, toValue]` with finite numbers as elements.'
97+
].join(' ')
98+
},
99+
values: {
100+
valType: 'data_array',
101+
role: 'info',
102+
dflt: [],
103+
description: [
104+
'Dimension values. `values[n]` represents the value of the `n`th point in the dataset,',
105+
'therefore the `values` vector for all dimensions must be the same (longer vectors',
106+
'will be truncated). Each value must be a finite number.'
107+
].join(' ')
108+
},
109+
description: 'The dimensions (variables) of the parallel coordinates chart. 2..60 dimensions are supported.'
110+
},
111+
112+
line: extendFlat({},
113+
114+
// the default autocolorscale isn't quite usable for parcoords due to context ambiguity around 0 (grey, off-white)
115+
// autocolorscale therefore defaults to false too, to avoid being overridden by the blue-white-red autocolor palette
116+
extendDeep(
117+
{},
118+
colorAttributes('line'),
119+
{
120+
colorscale: extendDeep(
121+
{},
122+
colorAttributes('line').colorscale,
123+
{dflt: colorscales.Viridis}
124+
),
125+
autocolorscale: extendDeep(
126+
{},
127+
colorAttributes('line').autocolorscale,
128+
{
129+
dflt: false,
130+
description: [
131+
'Has an effect only if line.color` is set to a numerical array.',
132+
'Determines whether the colorscale is a default palette (`autocolorscale: true`)',
133+
'or the palette determined by `line.colorscale`.',
134+
'In case `colorscale` is unspecified or `autocolorscale` is true, the default ',
135+
'palette will be chosen according to whether numbers in the `color` array are',
136+
'all positive, all negative or mixed.',
137+
'The default value is false, so that `parcoords` colorscale can default to `Viridis`.'
138+
].join(' ')
139+
}
140+
)
141+
142+
}
143+
),
144+
145+
{
146+
showscale: {
147+
valType: 'boolean',
148+
role: 'info',
149+
dflt: false,
150+
description: [
151+
'Has an effect only if `line.color` is set to a numerical array.',
152+
'Determines whether or not a colorbar is displayed.'
153+
].join(' ')
154+
},
155+
colorbar: colorbarAttrs
156+
}
157+
)
158+
};

src/traces/parcoords/base_plot.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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+
var d3 = require('d3');
12+
var Plots = require('../../plots/plots');
13+
var parcoordsPlot = require('./plot');
14+
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
15+
var c = require('./constants');
16+
17+
exports.name = 'parcoords';
18+
19+
exports.attr = 'type';
20+
21+
exports.plot = function(gd) {
22+
var calcData = Plots.getSubplotCalcData(gd.calcdata, 'parcoords', 'parcoords');
23+
if(calcData.length) parcoordsPlot(gd, calcData);
24+
};
25+
26+
exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout) {
27+
var hadParcoords = (oldFullLayout._has && oldFullLayout._has('parcoords'));
28+
var hasParcoords = (newFullLayout._has && newFullLayout._has('parcoords'));
29+
30+
if(hadParcoords && !hasParcoords) {
31+
oldFullLayout._paperdiv.selectAll('.parcoords-line-layers').remove();
32+
oldFullLayout._paperdiv.selectAll('.parcoords-line-layers').remove();
33+
oldFullLayout._paperdiv.selectAll('.parcoords').remove();
34+
oldFullLayout._paperdiv.selectAll('.parcoords').remove();
35+
oldFullLayout._glimages.selectAll('*').remove();
36+
}
37+
};
38+
39+
exports.toSVG = function(gd) {
40+
41+
var imageRoot = gd._fullLayout._glimages;
42+
var root = d3.selectAll('.svg-container');
43+
var canvases = root.filter(function(d, i) {return i === root.size() - 1;})
44+
.selectAll('.parcoords-lines.context, .parcoords-lines.focus');
45+
46+
function canvasToImage(d) {
47+
var canvas = this;
48+
var imageData = canvas.toDataURL('image/png');
49+
var image = imageRoot.append('svg:image');
50+
var size = gd._fullLayout._size;
51+
var domain = gd._fullData[d.model.key].domain;
52+
53+
image.attr({
54+
xmlns: xmlnsNamespaces.svg,
55+
'xlink:href': imageData,
56+
x: size.l + size.w * domain.x[0] - c.overdrag,
57+
y: size.t + size.h * (1 - domain.y[1]),
58+
width: (domain.x[1] - domain.x[0]) * size.w + 2 * c.overdrag,
59+
height: (domain.y[1] - domain.y[0]) * size.h,
60+
preserveAspectRatio: 'none'
61+
});
62+
}
63+
64+
imageRoot.selectAll('*').remove();
65+
canvases.each(canvasToImage);
66+
67+
// Chrome / Safari bug workaround - browser apparently loses connection to the defined pattern
68+
// Without the workaround, these browsers 'lose' the filter brush styling (color etc.) after a snapshot
69+
// on a subsequent interaction.
70+
// Firefox works fine without this workaround
71+
window.setTimeout(function() {
72+
d3.selectAll('#filterBarPattern')
73+
.attr('id', 'filterBarPattern');
74+
}, 60);
75+
};

src/traces/parcoords/calc.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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+
var hasColorscale = require('../../components/colorscale/has_colorscale');
12+
var calcColorscale = require('../../components/colorscale/calc');
13+
var Lib = require('../../lib');
14+
15+
16+
module.exports = function calc(gd, trace) {
17+
var cs = !!trace.line.colorscale && Lib.isArray(trace.line.color);
18+
var color = cs ? trace.line.color : Array.apply(0, Array(trace.dimensions.reduce(function(p, n) {return Math.max(p, n.values.length);}, 0))).map(function() {return 0.5;});
19+
var cscale = cs ? trace.line.colorscale : [[0, trace.line.color], [1, trace.line.color]];
20+
21+
trace.line.color = color;
22+
trace.line.colorscale = cscale;
23+
24+
if(hasColorscale(trace, 'line')) {
25+
calcColorscale(trace, trace.line.color, 'line', 'c');
26+
}
27+
28+
return [{}];
29+
};

src/traces/parcoords/colorbar.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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+
10+
'use strict';
11+
12+
var isNumeric = require('fast-isnumeric');
13+
14+
var Lib = require('../../lib');
15+
var Plots = require('../../plots/plots');
16+
var Colorscale = require('../../components/colorscale');
17+
var drawColorbar = require('../../components/colorbar/draw');
18+
19+
20+
module.exports = function colorbar(gd, cd) {
21+
var trace = cd[0].trace,
22+
line = trace.line,
23+
cbId = 'cb' + trace.uid;
24+
25+
gd._fullLayout._infolayer.selectAll('.' + cbId).remove();
26+
27+
if((line === undefined) || !line.showscale) {
28+
Plots.autoMargin(gd, cbId);
29+
return;
30+
}
31+
32+
var vals = line.color,
33+
cmin = line.cmin,
34+
cmax = line.cmax;
35+
36+
if(!isNumeric(cmin)) cmin = Lib.aggNums(Math.min, null, vals);
37+
if(!isNumeric(cmax)) cmax = Lib.aggNums(Math.max, null, vals);
38+
39+
var cb = cd[0].t.cb = drawColorbar(gd, cbId);
40+
var sclFunc = Colorscale.makeColorScaleFunc(
41+
Colorscale.extractScale(
42+
line.colorscale,
43+
cmin,
44+
cmax
45+
),
46+
{ noNumericCheck: true }
47+
);
48+
49+
cb.fillcolor(sclFunc)
50+
.filllevels({start: cmin, end: cmax, size: (cmax - cmin) / 254})
51+
.options(line.colorbar)();
52+
};

0 commit comments

Comments
 (0)