Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork7.9k
BUG: fix normalizing image data contained in np.ndarray subclass#27682
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading.Please reload this page.
Conversation
story645 commentedJan 22, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Can you create a fake unit that mimics the astropy behavior? Something like a very thin wrapper over nd.array that triggers the error but is fixed here? Something like#26953 |
febad98
tof6340d4
CompareThank you for your suggestion ! I wasn't able to construct such a mock with a bottom-up approach (build one from the ground up), supposedly because of the sheer complexity of |
Is much appreciated since that helps us better understand what's going wonky here. |
eed2fe8
tod337f69
CompareOk I think it's now ready for review. |
pllim commentedJan 22, 2024
Thanks! Re: mocking astropy.units.Quantity --@mhvk can double check if needed. |
Apologies for asking this several hours late, but are either of these relevant here?
matplotlib/lib/matplotlib/tests/test_image.py Line 1199 in59f9b3c
|
pllim commentedJan 22, 2024
pllim commentedJan 22, 2024
And the second one to#18286 that mentioned |
@rcomer Indeed these classes will not reproduce the issue we're currently seeing with |
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.
Certainly looks like a reasonable mock-up ofQuantity
!
lib/matplotlib/image.py Outdated
@@ -461,12 +461,12 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0, | |||
vmid = np.float64(self.norm.vmin) + dv / 2 | |||
fact = 1e7 if scaled_dtype == np.float64 else 1e4 | |||
newmin = vmid - dv * fact | |||
if newmin < a_min: | |||
if newmin <np.float64(a_min): |
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'd maybe do this just below whereA
itself is converted to a plain array, ie.,
A_scaled = np.array(A, dtype=scaled_dtype)a_min = np.float64(a_min)a_max = np.float64(a_max)
(Arguably,scaled_dtype.type
might be more logical thannp.float64
, but then one should adjust other things 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.
done
Can you add a comment that that's the important bit? |
Actually I thinkevery part of the mock class is crucial to reproduce the problem, should I really comment all of them ? |
d337f69
tob91cae8
Compare
😬 No, if it's a combination of the things then yeah it doesn't need a specific comment. |
I've been trying to understand what's going on here. It seems:
I think the better long term fix here is to add proper support for the image data to have units in the So it's unclear to me whether it's worth merging this PR as a bit of a stopgap fix, or whether we should be aiming to add proper support for unitful data in |
dstansby commentedJan 24, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
As a quick proof of concept, the following diff fixes the original issue, also allows mousing over the data to work (that's still broken with this PR), and opens the door to further improvements like labelling the colorbar with the units. diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.pyindex e326906269..88325a59ed 100644--- a/lib/matplotlib/image.py+++ b/lib/matplotlib/image.py@@ -26,6 +26,7 @@ import matplotlib.colors as mcolors from matplotlib.transforms import ( Affine2D, BboxBase, Bbox, BboxTransform, BboxTransformTo, IdentityTransform, TransformedBbox)+import matplotlib.units as munits _log = logging.getLogger(__name__)@@ -724,6 +725,13 @@ class _ImageBase(martist.Artist, cm.ScalarMappable): ---------- A : array-like or `PIL.Image.Image` """+ converter = munits.registry.get_converter(A)+ if converter is not None:+ self._units = converter.default_units(A, self)+ A = converter.convert(A, self._units, self)+ else:+ self._units = None+ if isinstance(A, PIL.Image.Image): A = pil_to_array(A) # Needed e.g. to apply png palette. self._A = self._normalize_image_array(A) It does have the issue that the last arguments to the converter methods are meant to be of type |
Happy to drop this PR in favour of a better fix if needed ! |
We don't have converter logic for data passed to color mapping. Folks are asked to pass a numpy array to scalar mappables. Maybe its OK to normalize those mappable to so something without units earlier, but I don't know that we have enough infrastructure in place to actually use unit converters here. |
story645 commentedJan 25, 2024 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I still think that throwing a convertor on NoNorm (or possibly writing a I think the complicated part has always been propagating the correct labels back to the colorbar. |
PR summary
This fixes a downstream issue with plotting data from a
astropy.units.Quantity
object (which derives fromnp.ndarray
), namelyastropy/astropy#11306Although the external issue was also linked to#19476, this patch doesnot fix that problem.
As a result, I am unsure how to write a test for the astropy bug here, though I could easily add a test in astropy itself (which is regularily tested against matplotlib dev).
PR checklist