-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Behavior of masked values in colormap plot has changed in 2.2.0 #11039
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
Comments
From #9961, I tried using LogNorm(vmin=1, vmax=5), and I got: ln(1) -> 0 But with LogNorm() Numpy version 1.13 |
To recap (some tests were done in #9961): If LogNorm sets vmin != vmax, the graph is plotted correctly: If the vmin == vmax == None (i.e. LogNorm()), the shown effect of a block of blue with no stripes is seen. |
class LogNorm(Normalize):
"""
Normalize a given value to the 0-1 range on a log scale
"""
def __call__(self, value, clip=None):
if clip is None:
clip = self.clip
result, is_scalar = self.process_value(value)
result = np.ma.masked_less_equal(result, 0, copy=False)
self.autoscale_None(result)
vmin, vmax = self.vmin, self.vmax
if vmin > vmax:
raise ValueError("minvalue must be less than or equal to maxvalue")
elif vmin <= 0:
raise ValueError("values must all be positive")
elif vmin == vmax:
result.fill(0) The problem is coming from the last line above, which is throwing away the mask in the special case where there is only a single valid value in the array. I will submit a PR for it. |
Wrong! Investigating... |
The problem is that all the complex rescaling in the resampling code in imshow probably should be skipped for the special case where there is only a single valid value in the array. @tacaswell, sorry, but I think I had better leave the implementation of that special case to you. |
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help! |
I cannot reproduce this problem with the specified versions. However I can reproduce on So in the end, I do have to wonder if |
After some further investigation, I think @efiring was on the right track above. With the refactoring of
When matplotlib/lib/matplotlib/colors.py Lines 1712 to 1713 in 5a89bdb
This can be fixed by something like: diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py
index 434bb54235..94a50e1d90 100644
--- a/lib/matplotlib/colors.py
+++ b/lib/matplotlib/colors.py
@@ -1709,8 +1709,6 @@ def _make_norm_from_scale(
self.autoscale_None(value)
if self.vmin > self.vmax:
raise ValueError("vmin must be less or equal to vmax")
- if self.vmin == self.vmax:
- return np.full_like(value, 0)
if clip is None:
clip = self.clip
if clip:
@@ -1720,8 +1718,11 @@ def _make_norm_from_scale(
if not np.isfinite([t_vmin, t_vmax]).all():
raise ValueError("Invalid vmin or vmax")
t_value -= t_vmin
- t_value /= (t_vmax - t_vmin)
- t_value = np.ma.masked_invalid(t_value, copy=False)
+ if self.vmin == self.vmax:
+ t_value[t_value > 0] += 1
+ else:
+ t_value /= (t_vmax - t_vmin)
+ t_value = np.ma.masked_invalid(t_value, copy=False)
return t_value[0] if is_scalar else t_value
def inverse(self, value): (though I'm not sure if the last line should be in or out of the However, fixing that does not fix the image. This appears to be due to this extra clipping applied at: matplotlib/lib/matplotlib/image.py Lines 454 to 473 in 5a89bdb
Since a |
Is We already apply a nonsingular transform in Colorbar to specifically avoid this case when the norm is on an axis, but I'm wondering if this special-casing should actually be moved upstream to the |
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help! |
The topic of singular norms (vmin == vmax) is not consistently solved. Not a high priority, but we should come up with a consistent approach. See also |
Bug report
Bug summary
Something changed the behavior of masked values in colormaps. Before, masked values on a 'jet' colormap would be drawn as white (and could be set to different colors with set_bad). This is no longer the case on matplotlib 2.2.0 - the masked values are being printed out as blue, the same color as valid values, and set_bad has no effect. Verified former behavior to be working on 2.1.1 and 2.0.2.
Not sure this is an issue or expected behavior, but I couldn't find a description of this behavior change anywhere. Please close if this is expected.
Changing interpolation from gaussian to none makes no difference (the sample code was originally used for another bug)
Code for reproduction
Actual outcome
Expected outcome
Matplotlib version
print(matplotlib.get_backend())
): TkAggInstalled from pip
The text was updated successfully, but these errors were encountered: