-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Color gradient for scatter3d
snail trail lines [WIP]
#617
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
Conversation
Looking good so far. It's probably already on your checklist, but just to be sure: we should support the case of numeric |
@etpinard yes, the included example uses |
@etpinard On |
ef83a6b
to
46104ac
Compare
@monfera Wow that's a lot of new tests !!! I doubt that they all add something useful to the table though. Generating For example, no need to add an image test for |
@@ -20,7 +20,7 @@ module.exports = function calc(trace, vals, containerStr, cLetter) { | |||
|
|||
if(containerStr) { | |||
container = Lib.nestedProperty(trace, containerStr).get(); | |||
inputContainer = Lib.nestedProperty(trace._input, containerStr).get(); | |||
inputContainer = Lib.nestedProperty(trace, containerStr).get(); |
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?
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 it was just a stop-gap. A few lines below the preexisting code set cmin
/cmax
/colorscale
properties on the inputContainer
. My understanding is that we not set or overwrite what the user gaveth us; that we'd decorate the output container
with defaults (which was also in the code). I eliminated lines that mutated inputContainer
, but glad to do something else if I'm trampling over some important aspect unknowingly.
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.
My understanding is that we not set or overwrite what the user gaveth us;
Correct. But there are a few exceptions to the rule. Namely to make restyle
work as desired. Too bad we never added any test cases. But, something like
Plotly.plot(/* some graph with a colorscale and cmin/cmax auto filled */)
Plotly.restyle(gd, 'cauto', false);
should return the original graph, and at the moment to only way to do so is to mutate gd.data
.
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 is also the case for (all I think) other attributes with an auto
flag e.g. histogram xbins
, xaxis.range
...
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.
What we should do is: mark those attributes with a special flag in the attributes.js
and handle them separately in restyle
/ relayout
so that we don't have to mutate gd.data
. But, that will be for a future PR.
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.
Interesting. Thanks for pointing this out. I'll take a look at this issue tomorrow am.
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.
What we should do is: mark those attributes with a special flag in the attributes.js
I see what you mean, wondered why marker.cauto
restyle magically worked and line.cauto
didn't. Sang a mantra of relief when I found it :-) https://github.com/plotly/plotly.js/blob/master/src/plot_api/plot_api.js#L1559-L1594
I don't remember one off the top of my head.
I switched the code as discussed. But it seems that if we persist the autocalculated cmin
/cmax
then it does not do what you want (provided I understand it well). Why? Only # 5 differs from my above list, the rest is copied.
- Initially the plot has specific
cmin
/cmax
values;cauto
false - I do
Plotly.restyle(gd, 'marker.cauto', true)
- Result is, the color palette now expands to the entire range of the data as it should
- I do
Plotly.restyle(gd, 'marker.cauto', false)
- Result is, the colors on the markers do not get restored to what they were because step 2 caused a destructive, irrecoverable mutation of the original user input
I reverted to my simpler code for now, haven't pushed the code snippet in the above comment but open to do whatever our clarification leads to.
backward-incompatible change
When you mentioned this reliance I initially also thought that retaining compatibility goes without saying. But now there's this nagging feeling that maybe it's not a big risk to break compat for this specifically, and perhaps see if plot.ly/plot workspace needs fixing and handle reported issues in the (perhaps) unlikely case of user reliance. In general I'd favor retaining original user input and not sharing our own intermediate work calculations unless through a querying API (rather than directly querying objects which are implementation detail). As you have a lot more info on the consequences, of course its your call but wanted to share a base sentiment.
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.
The technical difficulty is that this object, on which it attempts to set cmin/cmax may not exist:
In what scenario? calcColorscale
is only called if hasMarkers(trace)
is true (and if hasLines(trace)
, no ?
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 I really can't see a reason for calcCalcscale
to be modified in this PR.
Could you elaborate?
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.
In what scenario?
calcColorscale
is only called ifhasMarkers(trace)
is true (and ifhasLines(trace)
, no ?
From a previous comment:
The technical difficulty is that this object, on which it attempts to set
cmin
/cmax
may not exist: marker inherits props tomarker.line
butmarker.line
might not have been specified among the input. Therefore the code attempts to setcmin
/cmax
onundefined
.I really can't see a reason for calcCalcscale to be modified in this PR. Could you elaborate?
In the past, the color determination was much simpler for scatter3d
: its lines, markers did not participate in the sophisticated color specification that has the attributes from color_attributes.js
. Therefore this specific piece of code was not exercised for scatter3d
lines, markers and marker lines. This explains why there was no issue with cmin
/cmax
here (the code didn't get called and these props weren't present for scatter3d
anyway).
It looked sensible to use common code (colorscale/calc.js
) to deal with the common color attribute set (color_attributes.js
). Therefore colorscale/calc.js
got exercised in new ways, under which it failed (in my understanding) for the following two reasons (not new, just a recap of previous discussion):
- It errors out because it tries to set attributes on an object that may not exist (e.g.
marker.line
) - Persisting a calculated minimum/maximum value on the input (specifically,
trace._input
) means that if the user setscauto
totrue
, then back tofalse
, then they will get a different result than what they originally had (cmin
/cmax
would get overwritten by the data-drivem minimum/maximum).
So I thought we should use this piece of code for the newly introduced scatter3d
coloring options for line
and marker
rather than duplicating this file and it implies a change. Alternatively, if you'd like, I can copy this file just for scatter3d
and contidionally invoke that. Another alternative is if I use the above snippet to solve the case of missing object, so that the tests pass, but in this case, as mentioned, toggling cauto
back and forth will override the original user-supplied cmin
/cmax
values.
@monfera Looks like you got all the functionality in. Fantastic 🎉 This will make a great addition once the tests are cleaned up. |
@@ -1586,7 +1586,9 @@ Plotly.restyle = function restyle(gd, astr, val, traces) { | |||
'outsidetextfont.size', 'outsidetextfont.family', 'outsidetextfont.color', | |||
'hole', 'scalegroup', 'domain', 'domain.x', 'domain.y', | |||
'domain.x[0]', 'domain.x[1]', 'domain.y[0]', 'domain.y[1]', | |||
'tilt', 'tiltaxis', 'depth', 'direction', 'rotation', 'pull' | |||
'tilt', 'tiltaxis', 'depth', 'direction', 'rotation', 'pull', |
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 just thinking about how these arrays could simply be done by flags in the attribute.js
definitions but it's not trivial due to the irregularities:
- Sometimes (as
domain.x[0]
here) the check is below the prop level (this is easy to cover though) - There are multiple sets:
recalcAttrs
,autorangeAttrs
,replotAttrs
, 'swapAttrs' (still easy to cover but not pretty) - Lots of manual overrides (see
elseif
tree withdoextra
s: https://github.com/plotly/plotly.js/blob/master/src/plot_api/plot_api.js#L1736-L1814 - Innumerable special casing for a wide diversity of things such as
pie
,LAYOUT
,if(ai === 'orientationaxes')
etc.
It's possible to first cover 1, 2 and maybe 3 but even that leaves quite a lot of entanglement.
calcColorscale(trace, marker.color, 'marker', 'c'); | ||
|
||
if(subTypes.hasLines(trace) && hasColorscale(trace, 'line')) { | ||
calcColorscale(trace, trace.line.color, 'line', 'c'); |
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.
nicely done here.
Hi @monfera |
Hello @liuyifang you have a great website, very interesting! This branch needs a couple of smaller decisions and test simplifications, and will lead to gradient line coloring, an example of which can be seen on the request ticket: #581 (comment) Ideally this can be merged in a day or two, and a subsequent release in another few days, but depends on workload on tasks running in parallel at Plotly. In this branch, the color interpolation is between connected points, i.e. the color is interpolated via a default linear RGB from the beginning to end of a specific line section. While in theory it's possible to check out this branch and use this, the way it's configured, and the way the default colors are determined will still change a bit, so I think it would be best to wait for a released bundle. As a separate feature, we're also working on an initial version of streamtubes that has support for lighting, occlusion, varying radius, Catmull-Rom spline based curvature and interpolation, and other features, some examples (feature list and target date aren't final yet):
|
6b94edd
to
cd32fe4
Compare
01634e5
to
6bab94f
Compare
70ba46d
to
7347847
Compare
Fantastic work. 🍻 |
The current PR intends to cover functionality as per #581, i.e. a
scatter3d
solution.