-
-
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
Fix contour plot colorscale domain #6625
Conversation
Following 66e7b3c, set colorscale domain bounds for consistency
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.
NB. Regarding fb7e181,
See this test case, which otherwise would complain about fill level attributes changing between transition/redraw, having style: ''
vs style: 'stroke: none;'
, I think this was not happening before the fix because none of the fill levels rect to draw were missing (in the enter selection) after transition.
NB. Regarding the update of some mocks ae34826 In the airfoil and h-colorbar_airfoil mock, there is a contourcarpet plot which displays (without the fix) a colorbar ranging from -1 to +1. The min value of z is -6.04, and the config has In contour_edge_cases, set zmin and zmax for some traces to keep focus on precise contours levels that are far from zmin/zmax and let the colorscale "open" (ie. as without the fix) above/below the central values, in this case setting For those plots with computed tickvals/ticktext (not explicitly set in config) and for which the colorscale has changed, we may obtain different tickvals/ticktext (expected). The tick prefix/suffix if any are properly applied according to those calculated ticks. |
@@ -512,7 +512,7 @@ function drawColorBar(g, opts, gd) { | |||
.data(fillLevels); | |||
fills.enter().append('rect') | |||
.classed(cn.cbfill, true) | |||
.style('stroke', 'none'); | |||
.attr('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.
Could you please explain this change?
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.
Well, it's a bit tricky to explain.. The first thing to note is that when calling Plotly.newPlot()
, the colorbar is drawn twice, ie. the code above runs twice (which might be a bug (?) as the first draw seems correct, but I didn't dig much into that). When calling Plotly.react()
though, it runs once.
Now, we have (before this commit) :
var fills = g.select('.' + cn.cbfills)
.selectAll('rect.' + cn.cbfill)
.attr('style', '') // -> existing <rect> have empty `style` attribute
.data(fillLevels);
fills.enter().append('rect')
.classed(cn.cbfill, true)
.style('stroke', 'none'); // -> missing <rect> are added with `style='stroke: none;'`
fills.exit().remove();
So, if I'm not wrong :
- After calling
Plotly.newPlot()
, because the code runs twice, there is no missing<rect>
on the second pass obviously, and in the end all of them have an emptystyle
attribute (for contour colorbar, each element get colored via thefill
attribute) - After calling
Plotly.react()
however, because the code runs once, those<rect>
that were newly added, if any, will have in the endstyle='stroke: none;'
This discrepancy causes this test case to fail, because some attributes are changing between transition/redraw. So this commit is just to fix that.
Now the question is : how the heck this test case hasn't ever failed until this PR ?
I think this could have to do with the double call and possible race conditions.. Hopefully I've been able to reproduce the failure without the colorbar fix, by using a mock with more data than those used previously by the test (longer to draw, hence the suspicion about race conditions), also fixed the promise chaining. I'm going to commit that so you can double check all of this.
Very interesting PR. 🎖️ |
@lvlte very interesting, thanks for this PR. In most cases I think this exactly the right change - in the fully-auto case now we're representing the full data range in the colorbar, which is the main thing. Even when it results in a substantial change in the colorbar, like the The other case I think might not be what we want is when you specify |
hi @lvlte Thank you for taking the time to create this helpful PR. We've been talking about a new project we'd like to pursue within Plotly.js, and your name came up 🤗 Would you be willing to share your email address with me so I can tell you more about it. Feel free to email me directly at adam@plot.ly Thank you, |
For now, if we use However, if a user specifies both contours start/end and zmin/zmax, and if
Yes this makes total sense, it's not reasonable to oblige the user to specify zmin and zmax in that case. |
@Coding-with-Adam Hi, thanks for reaching out ! You should have an email from me in your inbox. |
- Force include zmin/zmax only if explicitly set - Allows to set zmin/zmax range narrower than contours start/end
src/traces/contour/make_color_map.js
Outdated
@@ -65,6 +65,30 @@ module.exports = function makeColorMap(trace) { | |||
domain[i] = (si[0] * (nc + extra - 1) - (extra / 2)) * cs + start; | |||
range[i] = si[1]; | |||
} | |||
|
|||
// If zmin/zmax are explicitly set | |||
if(typeof trace._input.zmin === 'number' && typeof trace._input.zmax === 'number') { |
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.
if(typeof trace._input.zmin === 'number' && typeof trace._input.zmax === 'number') { | |
if(trace._input && (typeof trace._input.zmin === 'number') && (typeof trace._input.zmax === 'number')) { |
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, I was doing some testing and just realized there are still issues with my code (if user explicitly sets larger z range with smaller contour size), so it needs more work, I will fix that tomorrow I think.
Co-authored-by: Mojtaba Samimi <33888540+archmoj@users.noreply.github.com>
- Fix for when user specifies narrower z range than that of the contours start/end - Ensure colormap is consistent between coloring methods
@lvlte The PR looks very good. However I noticed something strange is going on with |
@archmoj yes it looks like a bug, if I'm not wrong we should have the same colors for the contour fills in In fact, it seems like the colorbar is built using contours from the first trace, the zmin/zmax extremes seem correct (extremes from all traces), but each trace builds its own colorMap from its own (auto)contour attributes (start, end, size), and since these contour attributes are computed independently for each trace, their colorscale domain is independent from the "main" colorscale (first trace). |
💃 |
Fixes #6623
Basically, it allows to make the colorscale domain fit a fixed range [min, max], whether by setting zmin/zmax or coloraxis cmin/cmax, which was not possible before except for the "heatmap" contour coloring method.
This is still possible to obtain the old behavior, ie. when the contours are defined to focus around median values (contour start/end far from min/max in z), then narrowing zmin/zmax (cmin/cmax) accordingly is fine.
Before vs After.