Skip to content

fix error bar trace ordering [fixes #338] #343

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
Mar 21, 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
126 changes: 2 additions & 124 deletions src/components/errorbars/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@

'use strict';

var d3 = require('d3');
var isNumeric = require('fast-isnumeric');

var Lib = require('../../lib');
var Color = require('../color');
var subTypes = require('../../traces/scatter/subtypes');


var errorBars = module.exports = {};

errorBars.attributes = require('./attributes');
Expand Down Expand Up @@ -49,123 +41,9 @@ errorBars.calcFromTrace = function(trace, layout) {
return calcdataMock;
};

// the main drawing function for errorbars
errorBars.plot = function(gd, plotinfo, cd) {
// ___ <-- "errorhats"
// |
// | <-- "errorbars"
// |
// ___ <-- "errorshoes"

var xa = plotinfo.x(),
ya = plotinfo.y();

// first remove all existing errorbars
// TODO: use enter/exit instead
plotinfo.plot.select('.errorlayer').selectAll('g.errorbars').remove();
var coords;

// draw the errorbars
plotinfo.plot.select('.errorlayer').selectAll('g.errorbars')
.data(cd)
.enter().append('g')
.attr('class','errorbars')
.each(function(d) {
var trace = d[0].trace,
xObj = trace.error_x,
yObj = trace.error_y,
sparse = subTypes.hasMarkers(trace) &&
trace.marker.maxdisplayed>0;

if(!yObj.visible && !xObj.visible) return;

d3.select(this).selectAll('g')
.data(Lib.identity)
.enter().append('g')
.each(function(d) {
coords = errorcoords(d, xa, ya);
var eb = d3.select(this),
path;
if(sparse && !d.vis) return;

if(yObj.visible && isNumeric(coords.x) &&
isNumeric(coords.yh) &&
isNumeric(coords.ys)) {
var yw = yObj.width;
path = 'M'+(coords.x-yw)+','+coords.yh+'h'+(2*yw) + // hat
'm-'+yw+',0V'+coords.ys; // bar
if(!coords.noYS) path += 'm-'+yw+',0h'+(2*yw); // shoe

eb.append('path')
.classed('yerror', true)
.attr('d', path);
}
if(xObj.visible && isNumeric(coords.y) &&
isNumeric(coords.xh) &&
isNumeric(coords.xs)) {
var xw = (xObj.copy_ystyle ? yObj : xObj).width;
path = 'M'+coords.xh+','+(coords.y-xw)+'v'+(2*xw) + // hat
'm0,-'+xw+'H'+coords.xs; // bar
if(!coords.noXS) path += 'm0,-'+xw+'v'+(2*xw); // shoe

eb.append('path')
.classed('xerror', true)
.attr('d', path);
}
});
});
};

errorBars.style = function(gd) {
d3.select(gd).selectAll('g.errorbars').each(function(d) {
var eb = d3.select(this),
trace = d[0].trace,
yObj = trace.error_y||{},
xObj = trace.error_x||{};

eb.selectAll('g path.yerror')
.style('stroke-width', yObj.thickness+'px')
.call(Color.stroke, yObj.color);

if(xObj.copy_ystyle) xObj = yObj;

eb.selectAll('g path.xerror')
.style('stroke-width', xObj.thickness+'px')
.call(Color.stroke, xObj.color);
});
};

function errorcoords(d, xa, ya) {
// compute the coordinates of the error-bar objects
var out = {
x: xa.c2p(d.x),
y: ya.c2p(d.y)
};

// calculate the error bar size and hat and shoe locations
if(d.yh!==undefined) {
out.yh = ya.c2p(d.yh);
out.ys = ya.c2p(d.ys);

// if the shoes go off-scale (ie log scale, error bars past zero)
// clip the bar and hide the shoes
if(!isNumeric(out.ys)) {
out.noYS = true;
out.ys = ya.c2p(d.ys, true);
}
}
if(d.xh!==undefined) {
out.xh = xa.c2p(d.xh);
out.xs = xa.c2p(d.xs);

if(!isNumeric(out.xs)) {
out.noXS = true;
out.xs = xa.c2p(d.xs, true);
}
}
errorBars.plot = require('./plot');

return out;
}
errorBars.style = require('./style');

errorBars.hoverInfo = function(calcPoint, trace, hoverPoint) {
if(trace.error_y.visible) {
Expand Down
115 changes: 115 additions & 0 deletions src/components/errorbars/plot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/**
* Copyright 2012-2016, 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 d3 = require('d3');
var isNumeric = require('fast-isnumeric');

var Lib = require('../../lib');
var subTypes = require('../../traces/scatter/subtypes');


module.exports = function plot(traces, plotinfo) {
var xa = plotinfo.x(),
ya = plotinfo.y();

traces.each(function(d) {
var trace = d[0].trace,
xObj = trace.error_x,
yObj = trace.error_y;

var sparse = (
subTypes.hasMarkers(trace) &&
trace.marker.maxdisplayed > 0
);

if(!yObj.visible && !xObj.visible) return;

var errorbars = d3.select(this).selectAll('g.errorbar')
.data(Lib.identity);

errorbars.enter().append('g')
.classed('errorbar', true);

errorbars.each(function(d) {
var errorbar = d3.select(this);
var coords = errorCoords(d, xa, ya);

if(sparse && !d.vis) return;

var path;

if(yObj.visible && isNumeric(coords.x) &&
isNumeric(coords.yh) &&
isNumeric(coords.ys)) {
var yw = yObj.width;

path = 'M' + (coords.x - yw) + ',' +
coords.yh + 'h' + (2 * yw) + // hat
'm-' + yw + ',0V' + coords.ys; // bar

if(!coords.noYS) path += 'm-' + yw +',0h' + (2 * yw); // shoe

errorbar.append('path')
.classed('yerror', true)
.attr('d', path);
}

if(xObj.visible && isNumeric(coords.y) &&
isNumeric(coords.xh) &&
isNumeric(coords.xs)) {
var xw = (xObj.copy_ystyle ? yObj : xObj).width;

path = 'M' + coords.xh + ',' +
(coords.y - xw) + 'v' + (2 * xw) + // hat
'm0,-' + xw + 'H' + coords.xs; // bar

if(!coords.noXS) path += 'm0,-' + xw + 'v' + (2 * xw); // shoe

errorbar.append('path')
.classed('xerror', true)
.attr('d', path);
}
});
});
};

// compute the coordinates of the error-bar objects
function errorCoords(d, xa, ya) {
var out = {
x: xa.c2p(d.x),
y: ya.c2p(d.y)
};

// calculate the error bar size and hat and shoe locations
if(d.yh !== undefined) {
out.yh = ya.c2p(d.yh);
out.ys = ya.c2p(d.ys);

// if the shoes go off-scale (ie log scale, error bars past zero)
// clip the bar and hide the shoes
if(!isNumeric(out.ys)) {
out.noYS = true;
out.ys = ya.c2p(d.ys, true);
}
}

if(d.xh !== undefined) {
out.xh = xa.c2p(d.xh);
out.xs = xa.c2p(d.xs);

if(!isNumeric(out.xs)) {
out.noXS = true;
out.xs = xa.c2p(d.xs, true);
}
}

return out;
}
35 changes: 35 additions & 0 deletions src/components/errorbars/style.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright 2012-2016, 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 d3 = require('d3');

var Color = require('../color');


module.exports = function style(traces) {
traces.each(function(d) {
var trace = d[0].trace,
yObj = trace.error_y || {},
xObj = trace.error_x || {};

var s = d3.select(this);

s.selectAll('path.yerror')
.style('stroke-width', yObj.thickness + 'px')
.call(Color.stroke, yObj.color);

if(xObj.copy_ystyle) xObj = yObj;

s.selectAll('path.xerror')
.style('stroke-width', xObj.thickness + 'px')
.call(Color.stroke, xObj.color);
});
};
1 change: 0 additions & 1 deletion src/plot_api/plot_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2672,7 +2672,6 @@ function makeCartesianPlotFramwork(gd, subplots) {
svg.append('g').classed('imagelayer', true);
svg.append('g').classed('maplayer', true);
svg.append('g').classed('barlayer', true);
svg.append('g').classed('errorlayer', true);
svg.append('g').classed('boxlayer', true);
svg.append('g').classed('scatterlayer', true);
}
Expand Down
15 changes: 2 additions & 13 deletions src/plots/cartesian/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@

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


exports.name = 'cartesian';

Expand Down Expand Up @@ -71,8 +69,7 @@ exports.plot = function(gd) {
for(var i = 0; i < subplots.length; i++) {
var subplot = subplots[i],
subplotInfo = fullLayout._plots[subplot],
cdSubplot = getCdSubplot(calcdata, subplot),
cdError = [];
cdSubplot = getCdSubplot(calcdata, subplot);

// remove old traces, then redraw everything
// TODO: use enter/exit appropriately in the plot functions
Expand All @@ -91,17 +88,9 @@ exports.plot = function(gd) {
// 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);
}
Lib.markTime('done ' + (cdModule[0] && cdModule[0][0].trace.type));
}

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

// now draw stuff not on subplots (ie, only pies at the moment)
Expand Down
7 changes: 4 additions & 3 deletions src/plots/plots.js
Original file line number Diff line number Diff line change
Expand Up @@ -805,10 +805,11 @@ plots.purge = function(gd) {
};

plots.style = function(gd) {
var modulesWithErrorBars = gd._modules.concat(Plotly.ErrorBars);
var _modules = gd._modules;

for(var i = 0; i < _modules.length; i++) {
var _module = _modules[i];

for(var i = 0; i < modulesWithErrorBars.length; i++) {
var _module = modulesWithErrorBars[i];
if(_module.style) _module.style(gd);
}
};
Expand Down
5 changes: 5 additions & 0 deletions src/traces/bar/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var isNumeric = require('fast-isnumeric');

var Lib = require('../../lib');
var Color = require('../../components/color');
var ErrorBars = require('../../components/errorbars');

var arraysToCalcdata = require('./arrays_to_calcdata');

Expand Down Expand Up @@ -102,4 +103,8 @@ module.exports = function plot(gd, plotinfo, cdbar) {
'M'+x0+','+y0+'V'+y1+'H'+x1+'V'+y0+'Z');
});
});

// error bars are on the top
bartraces.call(ErrorBars.plot, plotinfo);

};
3 changes: 3 additions & 0 deletions src/traces/bar/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var d3 = require('d3');

var Color = require('../../components/color');
var Drawing = require('../../components/drawing');
var ErrorBars = require('../../components/errorbars');


module.exports = function style(gd) {
Expand Down Expand Up @@ -71,4 +72,6 @@ module.exports = function style(gd) {
// d3.select(this).selectAll('text')
// .call(Plotly.Drawing.textPointStyle,d.t||d[0].t);
});

s.call(ErrorBars.style);
};
Loading