Skip to content

Multi-plot-type graphs #246

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 8 commits into from
Feb 10, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
98 changes: 13 additions & 85 deletions src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,57 +245,15 @@ Plotly.plot = function(gd, data, layout, config) {
return Plotly.Axes.doTicks(gd, 'redraw');
}

// Now plot the data
function drawData() {
// Now plot the data
var calcdata = gd.calcdata,
subplots = Plots.getSubplotIds(fullLayout, 'cartesian'),
modules = gd._modules;

var i, j, trace, subplot, subplotInfo,
cdSubplot, cdError, cdModule, _module;

function getCdSubplot(calcdata, subplot) {
var cdSubplot = [];
var i, cd, trace;
for (i = 0; i < calcdata.length; i++) {
cd = calcdata[i];
trace = cd[0].trace;
if (trace.xaxis+trace.yaxis === subplot) cdSubplot.push(cd);
}
return cdSubplot;
}

function getCdModule(cdSubplot, _module) {
var cdModule = [];

for(var i = 0; i < cdSubplot.length; i++) {
var cd = cdSubplot[i];
var trace = cd[0].trace;

if((trace._module === _module) && (trace.visible === true)) {
cdModule.push(cd);
}
}

return cdModule;
}

// clean up old scenes that no longer have associated data
// will this be a performance hit?

var plotRegistry = Plots.subplotsRegistry;

// TODO incorporate cartesian and polar plots into this paradigm
if(fullLayout._hasGL3D) plotRegistry.gl3d.plot(gd);
if(fullLayout._hasGeo) plotRegistry.geo.plot(gd);
if(fullLayout._hasGL2D) plotRegistry.gl2d.plot(gd);
var calcdata = gd.calcdata;

// in case of traces that were heatmaps or contour maps
// previously, remove them and their colorbars explicitly
for (i = 0; i < calcdata.length; i++) {
trace = calcdata[i][0].trace;

var isVisible = (trace.visible === true),
for(var i = 0; i < calcdata.length; i++) {
var trace = calcdata[i][0].trace,
isVisible = (trace.visible === true),
uid = trace.uid;

if(!isVisible || !Plots.traceIs(trace, '2dMap')) {
Expand All @@ -311,47 +269,17 @@ Plotly.plot = function(gd, data, layout, config) {
}
}

for (i = 0; i < subplots.length; i++) {
subplot = subplots[i];
subplotInfo = fullLayout._plots[subplot];
cdSubplot = getCdSubplot(calcdata, subplot);
cdError = [];

// remove old traces, then redraw everything
// TODO: use enter/exit appropriately in the plot functions
// so we don't need this - should sometimes be a big speedup
if(subplotInfo.plot) subplotInfo.plot.selectAll('g.trace').remove();

for(j = 0; j < modules.length; j++) {
_module = modules[j];

if(!_module.plot && (_module.name === 'pie')) continue;

// plot all traces of this type on this subplot at once
cdModule = getCdModule(cdSubplot, _module);
_module.plot(gd, subplotInfo, cdModule);
Lib.markTime('done ' + (cdModule[0] && cdModule[0][0].trace.type));

// collect the traces that may have error bars
if(cdModule[0] && cdModule[0][0].trace && Plots.traceIs(cdModule[0][0].trace, 'errorBarsOK')) {
cdError = cdError.concat(cdModule);
}
}
var plotRegistry = Plots.subplotsRegistry;

// finally do all error bars at once
if(fullLayout._hasCartesian) {
ErrorBars.plot(gd, subplotInfo, cdError);
Lib.markTime('done ErrorBars');
}
if(fullLayout._hasGL3D) plotRegistry.gl3d.plot(gd);
if(fullLayout._hasGeo) plotRegistry.geo.plot(gd);
if(fullLayout._hasGL2D) plotRegistry.gl2d.plot(gd);
if(fullLayout._hasCartesian || fullLayout._hasPie) {
plotRegistry.cartesian.plot(gd);
}

// now draw stuff not on subplots (ie, only pies at the moment)
if(fullLayout._hasPie) {
var Pie = Plots.getModule('pie');
var cdPie = getCdModule(calcdata, Pie);

if(cdPie.length) Pie.plot(gd, cdPie);
}
// clean up old scenes that no longer have associated data
// will this be a performance hit?

// styling separate from drawing
Plots.style(gd);
Expand Down
13 changes: 5 additions & 8 deletions src/plots/cartesian/axes.js
Original file line number Diff line number Diff line change
Expand Up @@ -1186,23 +1186,20 @@ axes.getSubplots = function(gd, ax) {
ax2.anchor,
ax3 = axes.getFromId(gd, ax3Id);

// if a free axis is already represented in the data, ignore it
// look if ax2 is already represented in the data
var foundAx2 = false;
for(j = 0; j < subplots.length; j++) {
if(hasAx2(subplots[j], ax2)) {
foundAx2 = true;
break;
}
}

// ignore free axes that already represented in the data
if(ax2.anchor === 'free' && foundAx2) continue;

if(!ax3) {
console.log([
'Warning: couldnt find anchor', ax3Id,
'for axis', ax2._id
].join(' '));
return;
}
// ignore anchor-less axes
if(!ax3) continue;

sp = (ax2Letter === 'x') ?
ax2._id + ax3._id :
Expand Down
2 changes: 1 addition & 1 deletion src/plots/cartesian/graph_interact.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ fx.isHoriz = function(fullData) {
fx.init = function(gd) {
var fullLayout = gd._fullLayout;

if(fullLayout._hasGL3D || fullLayout._hasGeo || gd._context.staticPlot) return;
if(!fullLayout._hasCartesian || gd._context.staticPlot) return;

var subplots = Object.keys(fullLayout._plots || {}).sort(function(a,b) {
// sort overlays last, then by x axis number, then y axis number
Expand Down
87 changes: 87 additions & 0 deletions src/plots/cartesian/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@

'use strict';

var Lib = require('../../lib');
var Plots = require('../plots');
var ErrorBars = require('../../components/errorbars');


exports.name = 'cartesian';

Expand All @@ -27,3 +31,86 @@ exports.attrRegex = {
x: /^xaxis([2-9]|[1-9][0-9]+)?$/,
y: /^yaxis([2-9]|[1-9][0-9]+)?$/
};

exports.plot = function(gd) {
var fullLayout = gd._fullLayout,
subplots = Plots.getSubplotIds(fullLayout, 'cartesian'),
calcdata = gd.calcdata,
modules = gd._modules;

function getCdSubplot(calcdata, subplot) {
var cdSubplot = [];

for(var i = 0; i < calcdata.length; i++) {
var cd = calcdata[i];
var trace = cd[0].trace;

if(trace.xaxis + trace.yaxis === subplot) {
cdSubplot.push(cd);
}
}

return cdSubplot;
}

function getCdModule(cdSubplot, _module) {
var cdModule = [];

for(var i = 0; i < cdSubplot.length; i++) {
var cd = cdSubplot[i];
var trace = cd[0].trace;

if((trace._module === _module) && (trace.visible === true)) {
cdModule.push(cd);
}
}

return cdModule;
}

for(var i = 0; i < subplots.length; i++) {
var subplot = subplots[i],
subplotInfo = fullLayout._plots[subplot],
cdSubplot = getCdSubplot(calcdata, subplot),
cdError = [];

// remove old traces, then redraw everything
// TODO: use enter/exit appropriately in the plot functions
// so we don't need this - should sometimes be a big speedup
if(subplotInfo.plot) subplotInfo.plot.selectAll('g.trace').remove();

for(var j = 0; j < modules.length; j++) {
var _module = modules[j];

// skip over non-cartesian trace modules
if(_module.basePlotModule.name !== 'cartesian') continue;

// skip over pies, there are drawn below
if(_module.name === 'pie') continue;

// plot all traces of this type on this subplot at once
var cdModule = getCdModule(cdSubplot, _module);
_module.plot(gd, subplotInfo, cdModule);
Lib.markTime('done ' + (cdModule[0] && cdModule[0][0].trace.type));

// collect the traces that may have error bars
if(cdModule[0] && cdModule[0][0].trace && Plots.traceIs(cdModule[0][0].trace, 'errorBarsOK')) {
cdError = cdError.concat(cdModule);
}
}

// finally do all error bars at once
if(fullLayout._hasCartesian) {
ErrorBars.plot(gd, subplotInfo, cdError);
Lib.markTime('done ErrorBars');
}
}

// now draw stuff not on subplots (ie, only pies at the moment)
if(fullLayout._hasPie) {
var Pie = Plots.getModule('pie');
var cdPie = getCdModule(calcdata, Pie);

if(cdPie.length) Pie.plot(gd, cdPie);
}
};
5 changes: 0 additions & 5 deletions src/plots/gl3d/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,6 @@ exports.setConvert = require('./set_convert');

exports.initAxes = function(gd) {
var fullLayout = gd._fullLayout;

// until they play better together
delete fullLayout.xaxis;
delete fullLayout.yaxis;

var sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d');

for(var i = 0; i < sceneIds.length; ++i) {
Expand Down
23 changes: 10 additions & 13 deletions src/plots/gl3d/layout/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,27 @@

'use strict';

var Plotly = require('../../../plotly');
var Lib = require('../../../lib');
var Plots = require('../../plots');
var layoutAttributes = require('./layout_attributes');
var supplyGl3dAxisLayoutDefaults = require('./axis_defaults');


module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
if (!layoutOut._hasGL3D) return;
if(!layoutOut._hasGL3D) return;

var scenes = Plotly.Plots.getSubplotIdsInData(fullData, 'gl3d');
var i;

// until they play better together
delete layoutOut.xaxis;
delete layoutOut.yaxis;
var scenes = Plots.getSubplotIdsInData(fullData, 'gl3d');

// Get number of scenes to compute default scene domain
var scenesLength = scenes.length;

var sceneLayoutIn, sceneLayoutOut;

function coerce(attr, dflt) {
return Plotly.Lib.coerce(sceneLayoutIn, sceneLayoutOut, layoutAttributes, attr, dflt);
return Lib.coerce(sceneLayoutIn, sceneLayoutOut, layoutAttributes, attr, dflt);
}

for (i = 0; i < scenesLength; ++i) {
for(var i = 0; i < scenesLength; i++) {
var scene = scenes[i];
/*
* Scene numbering proceeds as follows
Expand All @@ -45,7 +42,7 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
* Also write back a blank scene object to user layout so that some
* attributes like aspectratio can be written back dynamically.
*/
sceneLayoutIn;

if(layoutIn[scene] !== undefined) sceneLayoutIn = layoutIn[scene];
else layoutIn[scene] = sceneLayoutIn = {};

Expand Down Expand Up @@ -82,10 +79,10 @@ module.exports = function supplyLayoutDefaults(layoutIn, layoutOut, fullData) {
* for the mode. In this case we must force change it here as the default coerce
* misses it above.
*/
if (!hasAspect) {
if(!hasAspect) {
sceneLayoutIn.aspectratio = sceneLayoutOut.aspectratio = {x: 1, y: 1, z: 1};

if (aspectMode === 'manual') sceneLayoutOut.aspectmode = 'auto';
if(aspectMode === 'manual') sceneLayoutOut.aspectmode = 'auto';
}

/*
Expand Down
Binary file added test/image/baselines/plot_types.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading