Description
Summary
- Initializing plots with empty traces (traces are defined and styled but have no data yet) throws an error when using
scattergl
for the traces' type. - This behavior is not consistent with how Plotly acts when using
scatter
, which allows the user to do this. - An error also results when using
Plotly.addTraces
withscattergl
trace that has no data present, which is also inconsistent with how Plotly behaves when the trace is of typescatter
. - It seems to be due to an assumption that the traces always have some data in plotly.js/src/components/errorbars/index.js`, but I do not understand enough of the code base to create a pull request, hence this issue.
Details
In some situations I find it helpful to initialize traces with empty arrays for their data prior to adding values through Plotly.extendTraces()
.
For example, before data starts arriving, we might wish to style the traces, or ensure that the traces are in some particular order.
This behavior appears to be supported in the SVG case (at least for type: scatter
), but results in an error when using GL version.
The following works, allowing one to define the traces without adding data, and later extend them see CodePen demo
var data = [
{y: [], type: 'scatter'}
];
var layout = {
title: 'Graph Title'
};
Plotly.newPlot(graphDiv, data, layout);
Plotly.extendTraces(graphDiv, {y: [[1, 2, 3]]}, [0])
If we use type: 'scattergl'
instead, it throws an error
var data = [
{y: [], type: 'scattergl'}
];
var layout = {
title: 'Graph Title'
};
// This throws an error (Plotly 1.21.3)
Plotly.newPlot(graphDiv, data, layout);
From the console, we get:
Uncaught TypeError: Cannot set property 'trace' of undefined
at Object.errorBars.calcFromTrace (eval at <anonymous> (bundle.js:3613), <anonymous>:96224:27)
at LineWithMarkers.proto.updateFancy (eval at <anonymous> (bundle.js:3613), <anonymous>:147929:31)
at LineWithMarkers.proto.update (eval at <anonymous> (bundle.js:3613), <anonymous>:147793:14)
at Object.createLineWithMarkers [as plot] (eval at <anonymous> (bundle.js:3613), <anonymous>:148148:10)
at Scene2D.proto.updateTraces (eval at <anonymous> (bundle.js:3613), <anonymous>:124457:42)
at Scene2D.proto.plot (eval at <anonymous> (bundle.js:3613), <anonymous>:124336:10)
at Object.plotGl2d [as plot] (eval at <anonymous> (bundle.js:3613), <anonymous>:123933:15)
at drawData (eval at <anonymous> (bundle.js:3613), <anonymous>:109268:32)
at Object.lib.syncOrAsync (eval at <anonymous> (bundle.js:3613), <anonymous>:106093:15)
at Object.Plotly.plot (eval at <anonymous> (bundle.js:3613), <anonymous>:109312:9)
For verification that it works when initial data is supplied, see this CodePen demo
It would appear that the issue originates in the assumption that the initial traces will always contain some data, in plotly.js/src/components/errorbars/index.js
:
[...]
errorBars.calcFromTrace = function(trace, layout) {
var x = trace.x || [],
y = trace.y,
len = x.length || y.length;
var calcdataMock = new Array(len);
for(var i = 0; i < len; i++) {
calcdataMock[i] = {
x: x[i],
y: y[i]
};
}
calcdataMock[0].trace = trace;
errorBars.calc({
calcdata: [calcdataMock],
_fullLayout: layout
});
return calcdataMock;
};
...Which is in turn called because Plotly determines that these traces are fancy (I apologize but I could not find reference to what qualifies a trace as fancy in the documentation and was unable to assess what was going on without delving deeply into the code).
Requested Fix
It would be nice if I could still initialize empty traces when using the GL charts.