Skip to content

Commit 7bba266

Browse files
authored
Merge pull request #2899 from plotly/categorical-sploms
Multi-axis-type sploms
2 parents 6f35b5e + adb0004 commit 7bba266

19 files changed

+463
-145
lines changed

src/plot_api/subroutines.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ exports.doModeBar = function(gd) {
520520

521521
for(var i = 0; i < fullLayout._basePlotModules.length; i++) {
522522
var updateFx = fullLayout._basePlotModules[i].updateFx;
523-
if(updateFx) updateFx(fullLayout);
523+
if(updateFx) updateFx(gd);
524524
}
525525

526526
return Plots.previousPromises(gd);

src/plots/cartesian/axis_defaults.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ var setConvert = require('./set_convert');
3333
*/
3434
module.exports = function handleAxisDefaults(containerIn, containerOut, coerce, options, layoutOut) {
3535
var letter = options.letter;
36-
var id = containerOut._id;
3736
var font = options.font || {};
37+
var splomStash = options.splomStash || {};
3838

3939
var visible = coerce('visible', !options.cheateronly);
4040

@@ -66,7 +66,7 @@ module.exports = function handleAxisDefaults(containerIn, containerOut, coerce,
6666
// template too.
6767
var dfltFontColor = (dfltColor !== layoutAttributes.color.dflt) ? dfltColor : font.color;
6868
// try to get default title from splom trace, fallback to graph-wide value
69-
var dfltTitle = ((layoutOut._splomAxes || {})[letter] || {})[id] || layoutOut._dfltTitle[letter];
69+
var dfltTitle = splomStash.label || layoutOut._dfltTitle[letter];
7070

7171
coerce('title', dfltTitle);
7272
Lib.coerceFont(coerce, 'titlefont', {

src/plots/cartesian/graph_interact.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -151,15 +151,16 @@ exports.initInteractions = function initInteractions(gd) {
151151
gd._fullLayout._lasthover.onmousedown(evt);
152152
};
153153

154-
exports.updateFx(fullLayout);
154+
exports.updateFx(gd);
155155
};
156156

157157
// Minimal set of update needed on 'modebar' edits.
158158
// We only need to update the <g .draglayer> cursor style.
159159
//
160160
// Note that changing the axis configuration and/or the fixedrange attribute
161161
// should trigger a full initInteractions.
162-
exports.updateFx = function(fullLayout) {
162+
exports.updateFx = function(gd) {
163+
var fullLayout = gd._fullLayout;
163164
var cursor = fullLayout.dragmode === 'pan' ? 'move' : 'crosshair';
164165
setCursor(fullLayout._draggers, cursor);
165166
};

src/plots/cartesian/layout_defaults.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,9 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
157157
axLayoutOut._annIndices = [];
158158
axLayoutOut._shapeIndices = [];
159159

160-
handleTypeDefaults(axLayoutIn, axLayoutOut, coerce, traces, axName);
160+
// set up some private properties
161+
axLayoutOut._name = axName;
162+
var id = axLayoutOut._id = name2id(axName);
161163

162164
var overlayableAxes = getOverlayableAxes(axLetter, axName);
163165

@@ -170,9 +172,11 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
170172
bgColor: bgColor,
171173
calendar: layoutOut.calendar,
172174
automargin: true,
173-
cheateronly: axLetter === 'x' && xaCheater[axName] && !xaNonCheater[axName]
175+
cheateronly: axLetter === 'x' && xaCheater[axName] && !xaNonCheater[axName],
176+
splomStash: ((layoutOut._splomAxes || {})[axLetter] || {})[id]
174177
};
175178

179+
handleTypeDefaults(axLayoutIn, axLayoutOut, coerce, defaultOptions);
176180
handleAxisDefaults(axLayoutIn, axLayoutOut, coerce, defaultOptions, layoutOut);
177181

178182
var spikecolor = coerce2('spikecolor'),

src/plots/cartesian/type_defaults.js

+6-13
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,24 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

1211
var Registry = require('../../registry');
1312
var autoType = require('./axis_autotype');
14-
var name2id = require('./axis_ids').name2id;
1513

1614
/*
1715
* data: the plot data to use in choosing auto type
1816
* name: axis object name (ie 'xaxis') if one should be stored
1917
*/
20-
module.exports = function handleTypeDefaults(containerIn, containerOut, coerce, data, name) {
21-
// set up some private properties
22-
if(name) {
23-
containerOut._name = name;
24-
containerOut._id = name2id(name);
25-
}
18+
module.exports = function handleTypeDefaults(containerIn, containerOut, coerce, options) {
19+
var axType = coerce('type', (options.splomStash || {}).type);
2620

27-
var axType = coerce('type');
2821
if(axType === '-') {
29-
setAutoType(containerOut, data);
22+
setAutoType(containerOut, options.data);
3023

3124
if(containerOut.type === '-') {
3225
containerOut.type = 'linear';
33-
}
34-
else {
26+
} else {
3527
// copy autoType back to input axis
3628
// note that if this object didn't exist
3729
// in the input layout, we have to put it in
@@ -89,9 +81,10 @@ function setAutoType(ax, data) {
8981
}
9082
else if(d0.type === 'splom') {
9183
var dimensions = d0.dimensions;
84+
var diag = d0._diag;
9285
for(i = 0; i < dimensions.length; i++) {
9386
var dim = dimensions[i];
94-
if(dim.visible) {
87+
if(dim.visible && (diag[i][0] === id || diag[i][1] === id)) {
9588
ax.type = autoType(dim.values, calendar);
9689
break;
9790
}

src/plots/geo/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
7878
}
7979
};
8080

81-
exports.updateFx = function(fullLayout) {
81+
exports.updateFx = function(gd) {
82+
var fullLayout = gd._fullLayout;
8283
var subplotIds = fullLayout._subplots[GEO];
8384

8485
for(var i = 0; i < subplotIds.length; i++) {

src/plots/gl2d/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ exports.toSVG = function(gd) {
138138
}
139139
};
140140

141-
exports.updateFx = function(fullLayout) {
141+
exports.updateFx = function(gd) {
142+
var fullLayout = gd._fullLayout;
142143
var subplotIds = fullLayout._subplots.gl2d;
143144

144145
for(var i = 0; i < subplotIds.length; i++) {

src/plots/gl3d/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ exports.cleanId = function cleanId(id) {
129129
return SCENE + sceneNum;
130130
};
131131

132-
exports.updateFx = function(fullLayout) {
132+
exports.updateFx = function(gd) {
133+
var fullLayout = gd._fullLayout;
133134
var subplotIds = fullLayout._subplots[GL3D];
134135

135136
for(var i = 0; i < subplotIds.length; i++) {

src/plots/gl3d/layout/axis_defaults.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, options) {
3939
containerOut._id = axName[0] + options.scene;
4040
containerOut._name = axName;
4141

42-
handleTypeDefaults(containerIn, containerOut, coerce, options.data);
42+
handleTypeDefaults(containerIn, containerOut, coerce, options);
4343

4444
handleAxisDefaults(
4545
containerIn,

src/plots/mapbox/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ function findAccessToken(gd, mapboxIds) {
152152
throw new Error(constants.noAccessTokenErrorMsg);
153153
}
154154

155-
exports.updateFx = function(fullLayout) {
155+
exports.updateFx = function(gd) {
156+
var fullLayout = gd._fullLayout;
156157
var subplotIds = fullLayout._subplots[MAPBOX];
157158

158159
for(var i = 0; i < subplotIds.length; i++) {

src/traces/splom/attributes.js

+17
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,23 @@ module.exports = {
5858
description: 'Sets the dimension values to be plotted.'
5959
},
6060

61+
axis: {
62+
type: {
63+
valType: 'enumerated',
64+
values: ['linear', 'log', 'date', 'category'],
65+
role: 'info',
66+
editType: 'calc+clearAxisTypes',
67+
description: [
68+
'Sets the axis type for this dimension\'s generated',
69+
'x and y axes.',
70+
'Note that the axis `type` values set in layout take',
71+
'precedence over this attribute.'
72+
].join(' ')
73+
},
74+
75+
editType: 'calc+clearAxisTypes'
76+
},
77+
6178
// TODO should add an attribute to pin down x only vars and y only vars
6279
// like https://seaborn.pydata.org/generated/seaborn.pairplot.html
6380
// x_vars and y_vars

src/traces/splom/base_plot.js

+42-20
Original file line numberDiff line numberDiff line change
@@ -45,36 +45,34 @@ function drag(gd) {
4545
for(var i = 0; i < cd.length; i++) {
4646
var cd0 = cd[i][0];
4747
var trace = cd0.trace;
48-
var scene = cd0.t._scene;
48+
var stash = cd0.t;
49+
var scene = stash._scene;
4950

5051
if(trace.type === 'splom' && scene && scene.matrix) {
51-
dragOne(gd, trace, scene);
52+
dragOne(gd, trace, stash, scene);
5253
}
5354
}
5455
}
5556

56-
function dragOne(gd, trace, scene) {
57-
var dimensions = trace.dimensions;
57+
function dragOne(gd, trace, stash, scene) {
5858
var visibleLength = scene.matrixOptions.data.length;
59+
var visibleDims = stash.visibleDims;
5960
var ranges = new Array(visibleLength);
6061

61-
for(var i = 0, k = 0; i < dimensions.length; i++) {
62-
if(dimensions[i].visible) {
63-
var rng = ranges[k] = new Array(4);
62+
for(var k = 0; k < visibleDims.length; k++) {
63+
var i = visibleDims[k];
64+
var rng = ranges[k] = new Array(4);
6465

65-
var xa = AxisIDs.getFromId(gd, trace._diag[i][0]);
66-
if(xa) {
67-
rng[0] = xa.r2l(xa.range[0]);
68-
rng[2] = xa.r2l(xa.range[1]);
69-
}
70-
71-
var ya = AxisIDs.getFromId(gd, trace._diag[i][1]);
72-
if(ya) {
73-
rng[1] = ya.r2l(ya.range[0]);
74-
rng[3] = ya.r2l(ya.range[1]);
75-
}
66+
var xa = AxisIDs.getFromId(gd, trace._diag[i][0]);
67+
if(xa) {
68+
rng[0] = xa.r2l(xa.range[0]);
69+
rng[2] = xa.r2l(xa.range[1]);
70+
}
7671

77-
k++;
72+
var ya = AxisIDs.getFromId(gd, trace._diag[i][1]);
73+
if(ya) {
74+
rng[1] = ya.r2l(ya.range[0]);
75+
rng[3] = ya.r2l(ya.range[1]);
7876
}
7977
}
8078

@@ -229,6 +227,30 @@ function clean(newFullData, newFullLayout, oldFullData, oldFullLayout, oldCalcda
229227
Cartesian.clean(newFullData, newFullLayout, oldFullData, oldFullLayout);
230228
}
231229

230+
function updateFx(gd) {
231+
Cartesian.updateFx(gd);
232+
233+
var fullLayout = gd._fullLayout;
234+
var dragmode = fullLayout.dragmode;
235+
236+
// unset selection styles when coming out of a selection mode
237+
if(dragmode === 'zoom' || dragmode === 'pan') {
238+
var cd = gd.calcdata;
239+
240+
for(var i = 0; i < cd.length; i++) {
241+
var cd0 = cd[i][0];
242+
var trace = cd0.trace;
243+
244+
if(trace.type === 'splom') {
245+
var scene = cd0.t._scene;
246+
if(scene.selectBatch === null) {
247+
scene.matrix.update(scene.matrixOptions, null);
248+
}
249+
}
250+
}
251+
}
252+
}
253+
232254
module.exports = {
233255
name: SPLOM,
234256
attr: Cartesian.attr,
@@ -239,6 +261,6 @@ module.exports = {
239261
plot: plot,
240262
drag: drag,
241263
clean: clean,
242-
updateFx: Cartesian.updateFx,
264+
updateFx: updateFx,
243265
toSVG: Cartesian.toSVG
244266
};

src/traces/splom/defaults.js

+14-6
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ function dimensionDefaults(dimIn, dimOut) {
6161

6262
if(!(values && values.length)) dimOut.visible = false;
6363
else coerce('visible');
64+
65+
coerce('axis.type');
6466
}
6567

6668
function handleAxisDefaults(traceIn, traceOut, layout, coerce) {
@@ -113,14 +115,14 @@ function handleAxisDefaults(traceIn, traceOut, layout, coerce) {
113115

114116
for(i = 0; i < dimLength; i++) {
115117
var dim = dimensions[i];
116-
var xa = xaxes[i + xShift];
117-
var ya = yaxes[i + yShift];
118+
var xaId = xaxes[i + xShift];
119+
var yaId = yaxes[i + yShift];
118120

119-
fillAxisStash(layout, xa, dim);
120-
fillAxisStash(layout, ya, dim);
121+
fillAxisStash(layout, xaId, dim);
122+
fillAxisStash(layout, yaId, dim);
121123

122124
// note that some the entries here may be undefined
123-
diag[i] = [xa, ya];
125+
diag[i] = [xaId, yaId];
124126
}
125127

126128
// when lower half is omitted, override grid default
@@ -148,7 +150,13 @@ function fillAxisStash(layout, axId, dim) {
148150
var stash = layout._splomAxes[axLetter];
149151

150152
if(!(axId in stash)) {
151-
stash[axId] = (dim || {}).label || '';
153+
var s = stash[axId] = {};
154+
if(dim) {
155+
s.label = dim.label || '';
156+
if(dim.visible && dim.axis) {
157+
s.type = dim.axis.type;
158+
}
159+
}
152160
}
153161
}
154162

0 commit comments

Comments
 (0)