-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Non-fancy scattergl to work with dates #1021
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
Changes from 3 commits
fac70b2
a23756d
ab4ffbf
f5d6113
3c79068
5b71b47
46a6b6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -118,7 +118,7 @@ proto.handlePick = function(pickResult) { | |
trace: this, | ||
dataCoord: pickResult.dataCoord, | ||
traceCoord: [ | ||
this.pickXData[index], | ||
Number(this.pickXData[index]), // non-fancy scattergl has Dates | ||
this.pickYData[index] | ||
], | ||
textLabel: Array.isArray(this.textLabels) ? | ||
|
@@ -135,7 +135,7 @@ proto.handlePick = function(pickResult) { | |
|
||
// check if trace is fancy | ||
proto.isFancy = function(options) { | ||
if(this.scene.xaxis.type !== 'linear') return true; | ||
if(this.scene.xaxis.type !== 'linear' && this.scene.xaxis.type !== 'date') return true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
if(this.scene.yaxis.type !== 'linear') return true; | ||
|
||
if(!options.x || !options.y) return true; | ||
|
@@ -279,7 +279,8 @@ proto.updateFast = function(options) { | |
yy = y[i]; | ||
|
||
// check for isNaN is faster but doesn't skip over nulls | ||
if(!isNumeric(xx) || !isNumeric(yy)) continue; | ||
if(!isNumeric(yy)) continue; | ||
if(!isNumeric(xx) && !(xx instanceof Date)) continue; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm afraid it will be significantly slower than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @etpinard @alexcjohnson I'd just like to clarify something here. Testing with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a little surprised that epoch milliseconds are accepted as date data right now, I don't think our svg cartesian axes accept that, do they? But anyway I think your plan sounds good. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @alexcjohnson sorry I conflated two things in the spur of the moment, acceptance of numeric values and the rendering of dates. If I pass on epoch milliseconds it'll render fine but it won't render the numbers as dates; it'll simply show the epoch milliseconds as numbers. I'll revise my comment. |
||
|
||
idToIndex[pId++] = i; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ var Plots = require('@src/plots/plots'); | |
var Lib = require('@src/lib'); | ||
var Color = require('@src/components/color'); | ||
var tinycolor = require('tinycolor2'); | ||
var hasWebGLSupport = require('../assets/has_webgl_support'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to keep @monfera can you move your new test cases to one of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. New test are now separated from |
||
|
||
var handleTickValueDefaults = require('@src/plots/cartesian/tick_value_defaults'); | ||
var Axes = PlotlyInternal.Axes; | ||
|
@@ -387,6 +388,84 @@ describe('Test axes', function() { | |
}); | ||
}); | ||
|
||
describe('date axis', function() { | ||
|
||
if(!hasWebGLSupport('axes_test date axis')) return; | ||
|
||
var gd; | ||
|
||
beforeEach(function() { | ||
gd = createGraphDiv(); | ||
}); | ||
|
||
afterEach(destroyGraphDiv); | ||
|
||
it('should use the fancy gl-vis/gl-scatter2d', function() { | ||
PlotlyInternal.plot(gd, [{ | ||
type: 'scattergl', | ||
'marker': { | ||
'color': 'rgb(31, 119, 180)', | ||
'size': 18, | ||
'symbol': [ | ||
'diamond', | ||
'cross' | ||
] | ||
}, | ||
x: [new Date('2016-10-10'), new Date('2016-10-12')], | ||
y: [15, 16] | ||
}]); | ||
|
||
expect(gd._fullLayout.xaxis.type).toBe('date'); | ||
expect(gd._fullLayout.yaxis.type).toBe('linear'); | ||
expect(gd._fullData[0].type).toBe('scattergl'); | ||
expect(gd._fullData[0]._module.basePlotModule.name).toBe('gl2d'); | ||
|
||
// one way of check which renderer - fancy vs not - we're using | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice find 👍 |
||
expect(gd._fullLayout._plots.xy._scene2d.glplot.objects[3].pointCount).toBe(0); | ||
}); | ||
|
||
it('should use the fancy gl-vis/gl-scatter2d once again', function() { | ||
PlotlyInternal.plot(gd, [{ | ||
type: 'scattergl', | ||
'marker': { | ||
'color': 'rgb(31, 119, 180)', | ||
'size': 36, | ||
'symbol': [ | ||
'circle', | ||
'cross' | ||
] | ||
}, | ||
x: [new Date('2016-10-10'), new Date('2016-10-11')], | ||
y: [15, 16] | ||
}]); | ||
|
||
expect(gd._fullLayout.xaxis.type).toBe('date'); | ||
expect(gd._fullLayout.yaxis.type).toBe('linear'); | ||
expect(gd._fullData[0].type).toBe('scattergl'); | ||
expect(gd._fullData[0]._module.basePlotModule.name).toBe('gl2d'); | ||
|
||
// one way of check which renderer - fancy vs not - we're using | ||
expect(gd._fullLayout._plots.xy._scene2d.glplot.objects[3].pointCount).toBe(0); | ||
}); | ||
|
||
it('should now use the non-fancy gl-vis/gl-scatter2d', function() { | ||
PlotlyInternal.plot(gd, [{ | ||
type: 'scattergl', | ||
mode: 'markers', // important, as otherwise lines are assumed (which needs fancy) | ||
x: [new Date('2016-10-10'), new Date('2016-10-11')], | ||
y: [15, 16] | ||
}]); | ||
|
||
expect(gd._fullLayout.xaxis.type).toBe('date'); | ||
expect(gd._fullLayout.yaxis.type).toBe('linear'); | ||
expect(gd._fullData[0].type).toBe('scattergl'); | ||
expect(gd._fullData[0]._module.basePlotModule.name).toBe('gl2d'); | ||
|
||
expect(gd._fullLayout._plots.xy._scene2d.glplot.objects[3].pointCount).toBe(2); | ||
}); | ||
|
||
}); | ||
|
||
describe('categoryorder', function() { | ||
|
||
var gd; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@monfera while pure-js users of plotly.js can use
Date
objects, plot.ly (and plotly.js users that may want to serialize their plots) use date strings viaLib.dateTime2ms
(here is what regular cartesian does). I realize that this will be slower, but can we at least support it for compatibility with the rest of our dates?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey Alex, good point. Currently,
scatter
works with ISO formatted dates e.g.2016-10-13
but I'll need to add a conversion from string to date forscattergl
. It'll be done upfront. The line you refer to above probably won't need to change as by the time the tooltip gets data it's already in the standard JSDate
format, but the front-end part needs some logic. To avoid having to loop through a possibly large number of array elements, I'm thinking about just checking the type of the first element of the array; if it'sDate
it's fine; if it's a string, then convert all elements toDate
. Is it OK in your opinion and also @etpinard ?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes me a little wary, but I can't think of a reason users would mix
Date
s and date strings (at least within one trace - definitely different traces should be checked independently). The first element may not be enough though, in case it'snull
or something, but the first valid element seems OK. Especially since this trace type is specifically built for performance, I guess we can impose some sane restrictions on the users.I haven't really looked at the architecture here, but if you're already converting the values you can just go straight to milliseconds, ignore
Date
objects altogether. Also notice that it's not exactly ISO 8601 we use, I don't know its name but I think of it as SQL date format - ie maximally it's2016-10-13 12:34:56.789123
but we're permissive about letting you truncate it after any part.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alex I'd probably reuse the date conversion routine you pointed to above, as if at all possible, I'd shy away from rolling a new
string
->Date
parser. Yes I agree with using epoch milliseconds as a general principle esp. on greenfield projects, although inplotly
it looks like it's not typically done. There's already conversion by default, as WebGL buffers cover float arrays, so it does get converted to epoch ms already.