Skip to content
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

plot_rgb fails with stretch=True for masked array with masked NaNs #675

Open
adamancer opened this issue Mar 18, 2021 · 1 comment
Open
Labels
bug Something isn't working good first issue Good for newcomers

Comments

@adamancer
Copy link

adamancer commented Mar 18, 2021

Describe the bug
Using ep.plot_rgb() with stretch=True fails when plotting a masked array when the original array contains NaNs. Plotting returns a black plot and gives the following warning "UserWarning: One or more intensity levels are NaN. Rescaling will broadcast NaN to the full image. Provide intensity levels yourself to avoid this. E.g. with np.nanmin(image), np.nanmax(image)."

I think this bug results from the use of np.percentile in the function earthpy uses to stretch the image. Neither np.percentile nor np.nanpercentile work intuitively with masked arrays. For a masked array where NaNs are masked, they return NaN(s). For a masked array where numeric values are masked, they return values based on the original (not masked) array, resulting in washed out images where nodata values are low (see screenshot below). This behavior has been reported as an issue but not fixed at numpy/numpy#4767 (although that link does provide potential workarounds).

To Reproduce

import earthpy.plot as ep
import numpy as np

# Create a 9x9 array with some pretty colors and some NaNs
r = [[128,  64, np.nan], [128,   0,   0], [  0, 128, 128]]
g = [[128,  64, np.nan], [  0, 128,   0], [128,   0, 128]]
b = [[128,  64, np.nan], [  0,   0, 128], [128, 128,   0]]

arr = np.array([r, g, b])

# Works as expected if NaNs are zeroed
arr_nan_zeroed = np.nan_to_num(arr)
ep.plot_rgb(arr_nan_zeroed, rgb=(2, 1, 0), stretch=True, title="NaN zeroed")

# Generates a warning and returns a black square if NaNs are masked
arr_nan_masked = np.ma.masked_invalid(arr)
ep.plot_rgb(arr_nan_masked, rgb=(2, 1, 0), stretch=True, title="NaN masked")

Expected behavior
The plot of the masked array should look similar/identical to the plot of the zeroed array

Screenshots
This is from the plot_rgb vignette when stretch is applied using the same approach as above:

plot_rgb_vignette

What Operating System Are you Running?

  • Windows

Additional context
The rioxarray library seems to convert nodata values to NaN automatically when loading rasters, so the masked arrays needed by plot_rgb are not stretchable for anything loaded using that library.

@lwasser
Copy link

lwasser commented Mar 22, 2021

hi @adamancer !! thank you for this issue!! @nkorinek and I were just talking last week about how we could make plot_rgb support xarray objects. While this issue is separate from that i think we could definitely tackle this as well when we start working on it. thank you for an excellent first issue to earthpy!!!

@lwasser lwasser added good first issue Good for newcomers bug Something isn't working labels Mar 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants