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
Changing cmap(np.nan) to 'bad' value rather than 'under' value #14257
Conversation
Thanks @greglucas ! |
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, looks great, but there is a "Future Warning" coming from numpy that needs fixing!
lib/matplotlib/colors.py
Outdated
@@ -532,6 +532,7 @@ def __call__(self, X, alpha=None, bytes=False): | |||
# otherwise the under-range values get converted to over-range. | |||
xa[xa > self.N - 1] = self._i_over | |||
xa[xa < 0] = self._i_under | |||
xa[np.isnan(X)] = self._i_bad |
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 triggers a test failure: FutureWarning: in the future, boolean array-likes will be handled as a boolean array index
. I guess X is a list for these and needs to be an array?
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... That is actually the behavior I want for this case. This is warning because it is using numpy version 1.11, newer versions are just fine as far as I can tell. The failure is actually because of scalars being passed in rather than lists I think. It is producing a FutureWarning because there are 'good' values currently, but this can produce an error in the situation where a single nan is passed in cmap(np.nan)
:
X = np.nan
xa = np.array([X])
xa[np.isnan(X)] # errors because it tries to access the first index, which doesn't exist
Right now, this works as expected for newer versions of numpy. Let me think if there is a better way of doing this...
943399c
to
79d8ab1
Compare
@jklymak, I have modified the approach and tried to simplify the logic in the code to address the warning that was found before in earlier numpy versions. I removed the masked array creation and got rid of the need to store whether the inputs were scalar or not. I also added some more tests to check for arrays, masked arrays, and scalars now too. |
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 looks right to me, but maybe should have another review after its passed the tests...
@@ -557,8 +557,6 @@ def __call__(self, X, alpha=None, bytes=False): | |||
# override its alpha just as for any other value. | |||
|
|||
rgba = lut.take(xa, axis=0, mode='clip') | |||
if vtype == 'scalar': |
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.
Won't removing this change the return type of cm(.5)
?
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.
Yes, good catch! I apparently neglected to read the return statement of the method requiring a tuple if the input is a scalar.
Old: (0.798216, 0.280197, 0.469538, 1.0)
New: array([0.798216, 0.280197, 0.469538, 1.0])
I was trying to clean the code up a bit and not have multiple if statements for the two different cases. A simple fix to keep things consistent would be:
if np.iterable(X):
# Return a tuple if the input is scalar
rgba = tuple(rgba)
I should be able to push a new change with this addition up later today
I guess w a new test that catches this? |
79d8ab1
to
423bd0d
Compare
Updated with scalar tuple return and new tests. I didn't see any other tests for return values from other RGBA routines, I might open another PR to add some of those to help with this. As a side thought, I was looking at the reason for a tuple return and it looks to be due to immutability and not overwriting a cached RGBA value. Another option would be to add a |
In the interest of getting this PR in, I suggest we push the return-type change to a second PR? |
Yes, I agree with that. I was just opening up food for thought. The return type change could be non-trivial in terms of possibly messing up other areas of code that rely on a tuple being returned, I haven't looked in-depth into it at all. For now, I believe this should be good to go. |
Thanks @greglucas . Congratulations on your first Matplotlib PR 🎉 ! Hopefully we will hear from you again! |
Thank you, @tacaswell! I will try and help out where I can. You all do great (and often un-thanked) work on this project that I use all the time, so thank you for the work you do. |
Previously, cmap(nan) would return the 'lower' value due to casting of ints within the
__call__
function. This adds annp.isnan()
check to return the bad value instead. New tests added to make sure -inf, nan, and inf, return the lower, bad, upper values respectively.Addresses issue #9892
PR Summary
PR Checklist