-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Finance refactor #2561
Finance refactor #2561
Conversation
…expanded acceptance
- notice I added a legend to finance_style, so we test ohlc legend drawing - also notice that I changed ohlc line drawing to not overdraw. Directions were chosen to optimize dashes: - the ticks are drawn starting from the outside toward the middle - the main line is drawn top-to-bottom, so in principle you might not actually see the low value, but that was the case before anyway, there's really no way around this with dashes...
removing direction names & showlegend, and picking a composite name
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.
Fantastic PR! I've never been this happy seeing some of my old code disappear. Transformed traces are a thing of the past and should never never be resuscitated (cc #1015 and #1217).
I made a few comments, mostly to highlight things that might be hidden in big commits that I was too lazy to examine in detail.
// the rest of this will still apply, so such modules | ||
// can still put things in (x|y|z)Label, text, and name | ||
// and hoverinfo will still determine their visibility | ||
if(d.extraText !== undefined) text += (text ? '<br>' : '') + d.extraText; |
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.
Why did you have to move this block down?
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.
Our previous users of extraText
use only extraText
, no x/y/z text, so they're essentially independent of the intervening block. But finance traces use extraText
in place of yLabel
, and still use xLabel
. Contrary to the comment (that I just moved down here with extraText
) previously if you had both parts, the x/y/z labels would obliterate extraText
.
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.
Thanks for the headsup 👌
@@ -455,7 +455,8 @@ function drawRangePlot(rangeSlider, gd, axisOpts, opts) { | |||
id: id, | |||
plotgroup: plotgroup, | |||
xaxis: xa, | |||
yaxis: ya | |||
yaxis: ya, | |||
isRangePlot: true |
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.
I don't think this range-plot range slider fix got 🔒 anywhere. We could add a case in select_test.js
selects a point in the main plot and asserts that it is really that main-plot plot that gets the selected style.
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.
Ah, thanks for reminding me about the rangeslider + selection fix! 🔒-> c77a8a3
src/plot_api/plot_schema.js
Outdated
if(!valObject) valObject = baseAttributes[head]; | ||
|
||
// finally check if we have a transform matching the original trace type | ||
if(!valObject && transforms) { |
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.
Why do we need this?
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.
Ah good catch, this is a holdover from my original attempt to fix these traces without refactoring them. We should never again have a trace type matching a transform type, and we certainly shouldn't have a transform that doesn't exist in gd.data
but gets added in during supplyDefaults
. I'll take this out.
@@ -68,6 +68,7 @@ module.exports = { | |||
'carpetlayer', | |||
'violinlayer', | |||
'boxlayer', |
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.
Can box
traces and candlestick
coexist on the same subplot?
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.
good 👀 - they probably could have before this PR, but this morning they couldn't. Now they can 0b7541e
@@ -203,7 +203,7 @@ function plotOne(gd, plotinfo, cdSubplot, transitionOpts, makeOnCompleteCallback | |||
// remaining plot traces should also be able to do this. Once implemented, | |||
// we won't need this - which should sometimes be a big speedup. | |||
if(plotinfo.plot) { | |||
plotinfo.plot.selectAll('g:not(.scatterlayer)').selectAll('g.trace').remove(); | |||
plotinfo.plot.selectAll('g:not(.scatterlayer):not(.ohlclayer)').selectAll('g.trace').remove(); |
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.
This query is getting ridiculous.
Can we instead loop over constants.traceLayerClasses
?
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.
Can we instead loop over
constants.traceLayerClasses
?
Somehow we need to distinguish between trace types that know how to update and those that don't - I feel like rather than adding another category for this, we should just teach the remaining types how to update. Probably actually not that hard to do, right? Just adding the right exit()
statements and moving things appropriately between enter()
and each
?
I wouldn't want to do that in this PR of course...
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.
Moved to #2563
Thanks!
pointData.xLabelVal = di.pos; | ||
|
||
pointData.spikeDistance = dxy(di) * spikePseudoDistance / hoverPseudoDistance; | ||
pointData.xSpike = xa.c2p(di.pos, true); |
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.
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.
are we expecting spike lines over this point to be black
Yeah, that color fails the tinycolor.readability
test so we just pick a color that contrasts with the background.
d3.select(this) | ||
.style('fill', 'none') | ||
.call(Color.stroke, dirLine.color) | ||
.call(Drawing.dashLine, dirLine.dash, dirLine.width) |
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.
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.
True, it looks weird... but it also looks weird in the plot. I think that just says anyone who would really use line.dash
here would want it to be a very short dash pattern, like 'dot'
. Hardly anyone will use it, but I don't think we should prohibit it, nor should we draw different dashes in the legend vs the plot.
I've changed that mock to dash: 'dot'
f84dfae and I have another mock in 0b7541e that shows it without dashes, so users can see the normal look.
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.
True, it looks weird... but it also looks weird in the plot.
Very good point. f84dfae is 👌
|
||
// Even if both showlegends are false, leave trace.showlegend out | ||
// My rationale for this is that legends are sufficiently different | ||
// now that it's worthwhile resetting their existence to default |
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.
👌
@@ -2781,6 +2865,53 @@ describe('Test plot api', function() { | |||
.then(done); | |||
}); | |||
|
|||
it('can change data in candlesticks multiple times', function(done) { |
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.
Should we added add a finance trace case for the can redraw with no changes as a noop set of tests?
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.
Should we added add a finance trace case for the can redraw with no changes as a noop set of tests?
It's there ->
plotly.js/test/jasmine/tests/plot_api_test.js
Line 2826 in 7d91d29
['finance_style', require('@mocks/finance_style.json')], |
and the previous
fullJson
exemption was cleared in this PR -> https://github.com/plotly/plotly.js/pull/2561/files#diff-5a140ce1cc87a420496039bbf8d699f1L2913
.then(done); | ||
}); | ||
|
||
['ohlc', 'candlestick'].forEach(function(type) { |
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.
So, apart from selection and the new legend items, can you list all the new features this PR adds to finance traces?
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.
.... mostly for changelog purposes 📚
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.
- selection
- new legend items (one per trace)
- fully compatible with
Plotly.react
- OHLC works with category x data OHLC calculations are off on category axes #2004
- improved event data Event data for transformed traces is inconsistent #1807
I think that's it...
also an image test for #2004 category OHLC and candlestick using box layout attrs
so it doesn't look like quite such a dumb feature
@@ -22,7 +22,7 @@ var SPLOM = 'splom'; | |||
function plot(gd) { | |||
var fullLayout = gd._fullLayout; | |||
var _module = Registry.getModule(SPLOM); | |||
var splomCalcData = getModuleCalcData(gd.calcdata, _module); | |||
var splomCalcData = getModuleCalcData(gd.calcdata, _module)[0]; |
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.
@etpinard I changed the API for getModuleCalcData
in 0b7541e - so that cartesian could avoid double-drawing the same trace when two trace modules share a plotting step (box
and candlestick
). In principle we could extend this pattern (a plot
step removes the calcdata
items it plotted and returns the items that are left) which could have a small 🐎 benefit when you have many traces of several types, you don't have to search the whole array each time, only the items that haven't already been handled.
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.
👍 for 0b7541e
In principle we could extend this pattern (a plot step removes the calcdata items it plotted and returns the items that are left) which could have a small racehorse benefit when you have many traces of several types, you don't have to search the whole array each time, only the items that haven't already been handled.
Good idea here. We should keep that in mind when we'll 🔪 calcdata
completely.
moduleCalcData.push(cd); | ||
} | ||
else { | ||
remainingCalcData.push(cd); |
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.
Brilliantly efficient. ❤️ this.
.each(stylePoints); | ||
.each(stylePoints) | ||
.each(styleCandles) | ||
.each(styleOHLC); |
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.
🚨 Non-blocking thinking-out-loud comment alert 🚨
We should perhaps make these trace module method (e.g. named _module.legendStyle
) instead of having the legend component handle all trace types by itself.
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.
Good idea, that would be way more efficient too - instead of calling every style routine on every trace and quitting if it's not the right one, just something like:
.each(function(d) { d.trace._module.legendStyle(...) })
Amazing work 💃 |
Closes #2510 - Makes finance traces (OHLC, candlestick) into 🥇 first-class trace types.
Along with this I added selection to both of these trace types. I did not however add custom selection styles. I'd like to leave this for a later PR.
cc @etpinard