Skip to content

Commit e004a09

Browse files
authored
Merge pull request #2620 from plotly/scattergl-errors
scattergl errorbars fixes
2 parents abcc6cc + 7e77bb4 commit e004a09

File tree

8 files changed

+88
-63
lines changed

8 files changed

+88
-63
lines changed

src/components/errorbars/index.js

+2-27
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ var Lib = require('../../lib');
1212
var overrideAll = require('../../plot_api/edit_types').overrideAll;
1313

1414
var attributes = require('./attributes');
15-
var calc = require('./calc');
1615

1716
var xyAttrs = {
1817
error_x: Lib.extendFlat({}, attributes),
@@ -48,38 +47,14 @@ module.exports = {
4847

4948
supplyDefaults: require('./defaults'),
5049

51-
calc: calc,
52-
calcFromTrace: calcFromTrace,
50+
calc: require('./calc'),
51+
makeComputeError: require('./compute_error'),
5352

5453
plot: require('./plot'),
5554
style: require('./style'),
5655
hoverInfo: hoverInfo
5756
};
5857

59-
function calcFromTrace(trace, layout) {
60-
var x = trace.x || [],
61-
y = trace.y || [],
62-
len = x.length || y.length;
63-
64-
var calcdataMock = new Array(len);
65-
66-
for(var i = 0; i < len; i++) {
67-
calcdataMock[i] = {
68-
x: x[i],
69-
y: y[i]
70-
};
71-
}
72-
73-
calcdataMock[0].trace = trace;
74-
75-
calc({
76-
calcdata: [calcdataMock],
77-
_fullLayout: layout
78-
});
79-
80-
return calcdataMock;
81-
}
82-
8358
function hoverInfo(calcPoint, trace, hoverPoint) {
8459
if((trace.error_y || {}).visible) {
8560
hoverPoint.yerr = calcPoint.yh - calcPoint.y;

src/traces/scatter3d/calc_errors.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

12-
var makeComputeError = require('../../components/errorbars/compute_error');
11+
var Registry = require('../../registry');
1312

1413
function calculateAxisErrors(data, params, scaleFactor) {
1514
if(!params || !params.visible) return null;
1615

17-
var computeError = makeComputeError(params);
16+
var computeError = Registry.getComponentMethod('errorbars', 'makeComputeError')(params);
1817
var result = new Array(data.length);
1918

2019
for(var i = 0; i < data.length; i++) {

src/traces/scattergl/convert.js

+49-29
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88

99
'use strict';
1010

11+
var isNumeric = require('fast-isnumeric');
1112
var svgSdf = require('svg-path-sdf');
1213
var rgba = require('color-normalize');
1314

1415
var Registry = require('../../registry');
1516
var Lib = require('../../lib');
1617
var Drawing = require('../../components/drawing');
18+
var Axes = require('../../plots/cartesian/axes');
1719
var AxisIDs = require('../../plots/cartesian/axis_ids');
1820

1921
var formatColor = require('../../lib/gl_format_color').formatColor;
@@ -360,42 +362,60 @@ function convertLinePositions(gd, trace, positions) {
360362
};
361363
}
362364

363-
function convertErrorBarPositions(gd, trace, positions) {
364-
var calcFromTrace = Registry.getComponentMethod('errorbars', 'calcFromTrace');
365-
var vals = calcFromTrace(trace, gd._fullLayout);
365+
function convertErrorBarPositions(gd, trace, positions, x, y) {
366+
var makeComputeError = Registry.getComponentMethod('errorbars', 'makeComputeError');
367+
var xa = AxisIDs.getFromId(gd, trace.xaxis);
368+
var ya = AxisIDs.getFromId(gd, trace.yaxis);
366369
var count = positions.length / 2;
367370
var out = {};
368371

369-
function put(axLetter) {
370-
var errors = new Float64Array(4 * count);
371-
var ax = AxisIDs.getFromId(gd, trace[axLetter + 'axis']);
372-
var pOffset = {x: 0, y: 1}[axLetter];
373-
var eOffset = {x: [0, 1, 2, 3], y: [2, 3, 0, 1]}[axLetter];
374-
375-
for(var i = 0, p = 0; i < count; i++, p += 4) {
376-
errors[p + eOffset[0]] = positions[i * 2 + pOffset] - ax.d2l(vals[i][axLetter + 's']) || 0;
377-
errors[p + eOffset[1]] = ax.d2l(vals[i][axLetter + 'h']) - positions[i * 2 + pOffset] || 0;
378-
errors[p + eOffset[2]] = 0;
379-
errors[p + eOffset[3]] = 0;
380-
}
381-
382-
return errors;
383-
}
372+
function convertOneAxis(coords, ax) {
373+
var axLetter = ax._id.charAt(0);
374+
var opts = trace['error_' + axLetter];
375+
376+
if(opts && opts.visible && (ax.type === 'linear' || ax.type === 'log')) {
377+
var computeError = makeComputeError(opts);
378+
var pOffset = {x: 0, y: 1}[axLetter];
379+
var eOffset = {x: [0, 1, 2, 3], y: [2, 3, 0, 1]}[axLetter];
380+
var errors = new Float64Array(4 * count);
381+
var minShoe = Infinity;
382+
var maxHat = -Infinity;
383+
384+
for(var i = 0, j = 0; i < count; i++, j += 4) {
385+
var dc = coords[i];
386+
387+
if(isNumeric(dc)) {
388+
var dl = positions[i * 2 + pOffset];
389+
var vals = computeError(dc, i);
390+
var lv = vals[0];
391+
var hv = vals[1];
392+
393+
if(isNumeric(lv) && isNumeric(hv)) {
394+
var shoe = dc - lv;
395+
var hat = dc + hv;
396+
397+
errors[j + eOffset[0]] = dl - ax.c2l(shoe);
398+
errors[j + eOffset[1]] = ax.c2l(hat) - dl;
399+
errors[j + eOffset[2]] = 0;
400+
errors[j + eOffset[3]] = 0;
401+
402+
minShoe = Math.min(minShoe, dc - lv);
403+
maxHat = Math.max(maxHat, dc + hv);
404+
}
405+
}
406+
}
384407

408+
Axes.expand(ax, [minShoe, maxHat], {padded: true});
385409

386-
if(trace.error_x && trace.error_x.visible) {
387-
out.x = {
388-
positions: positions,
389-
errors: put('x')
390-
};
391-
}
392-
if(trace.error_y && trace.error_y.visible) {
393-
out.y = {
394-
positions: positions,
395-
errors: put('y')
396-
};
410+
out[axLetter] = {
411+
positions: positions,
412+
errors: errors
413+
};
414+
}
397415
}
398416

417+
convertOneAxis(x, xa);
418+
convertOneAxis(y, ya);
399419
return out;
400420
}
401421

src/traces/scattergl/index.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ function calc(gd, trace) {
8282

8383
// create scene options and scene
8484
calcColorscales(trace);
85-
var opts = sceneOptions(gd, subplot, trace, positions);
85+
var opts = sceneOptions(gd, subplot, trace, positions, x, y);
8686
var scene = sceneUpdate(gd, subplot);
8787

8888
// Re-use SVG scatter axis expansion routine except
@@ -133,7 +133,7 @@ function calc(gd, trace) {
133133
}
134134

135135
// create scene options
136-
function sceneOptions(gd, subplot, trace, positions) {
136+
function sceneOptions(gd, subplot, trace, positions, x, y) {
137137
var opts = convertStyle(gd, trace);
138138

139139
if(opts.marker) {
@@ -148,7 +148,7 @@ function sceneOptions(gd, subplot, trace, positions) {
148148
}
149149

150150
if(opts.errorX || opts.errorY) {
151-
var errors = convertErrorBarPositions(gd, trace, positions);
151+
var errors = convertErrorBarPositions(gd, trace, positions, x, y);
152152

153153
if(opts.errorX) {
154154
Lib.extendFlat(opts.errorX, errors.x);
3.33 KB
Loading
-8 Bytes
Loading

test/image/mocks/gl2d_error_bars.json

+23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
{
22
"data": [
3+
{
4+
"x": [6],
5+
"y": ["2"],
6+
"error_y": {
7+
"type": "data",
8+
"array": [2],
9+
"arrayminus": [4]
10+
},
11+
"type": "scattergl"
12+
},
313
{
414
"x": [
515
0,
@@ -92,6 +102,19 @@
92102
"value": 10
93103
},
94104
"type": "scattergl"
105+
},
106+
{
107+
"y": [
108+
3,
109+
3,
110+
6,
111+
5
112+
],
113+
"error_x": {
114+
"type": "constant",
115+
"value": 0.1
116+
},
117+
"type": "scattergl"
95118
}
96119
]
97120
}
+9-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
{
22
"data": [{
3+
"name": "array error bars",
34
"type": "scattergl",
45
"y": [10, 2e4, 5e6],
56
"error_y": {"array": [5, 1e4, 4e6]}
7+
}, {
8+
"name": "50% percent error bars",
9+
"type": "scattergl",
10+
"x0": 0.2,
11+
"y": [10, 2e4, 5e6],
12+
"error_y": {"type": "percent", "value": 50}
613
}],
714
"layout": {
8-
"yaxis": {"type": "log"}
15+
"yaxis": {"type": "log"},
16+
"showlegend": false
917
}
1018
}

0 commit comments

Comments
 (0)