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

Contourf plot with transform_first=True does not handle masked data correctly #2468

Open
schlunma opened this issue Oct 31, 2024 · 1 comment

Comments

@schlunma
Copy link

Description

Using contourf with transform_first=True on masked data simply ignores the mask and plots the underlying value.

Code to reproduce

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import numpy as np

def masked_sample_data(shape=(73, 145)):
    """Return ``lons``, ``lats`` and ``data`` of some fake data."""
    nlats, nlons = shape
    lats = np.linspace(-np.pi / 2, np.pi / 2, nlats)
    lons = np.linspace(0, 2 * np.pi, nlons)
    lons, lats = np.meshgrid(lons, lats)
    wave = 0.75 * (np.sin(2 * lats) ** 8) * np.cos(4 * lons)
    mean = 0.5 * np.cos(2 * lats) * ((np.sin(2 * lats)) ** 2 + 2)
    lats = np.rad2deg(lats)
    lons = np.rad2deg(lons)
    data = wave + mean

    # mask data
    data = np.where(data > 0.5, 1e36, data)
    data = np.ma.masked_greater(data, 10)

    return lons, lats, data

x, y, z = masked_sample_data((20, 40))

# z = np.ma.filled(z, np.nan)  # with the plot always looks good

fig = plt.figure()
projection = ccrs.Robinson(central_longitude=10.0)
axes = fig.add_subplot(projection=projection)
plot = axes.contourf(x, y, z, transform=ccrs.PlateCarree(), transform_first=True)
colorbar = fig.colorbar(plot, ax=axes)

gives a plot that shows very high values ~1e36 (which actually should be masked!):

grafik

transform_first=False and/or filling the masked array with nans gives the expected result:

grafik

Full environment definition

Operating system

Cartopy version

0.23.0

conda list

env.txt

pip list

pip.txt

@greglucas
Copy link
Contributor

The transform_first is creating a new x, y, and z arrays with the definition found here:

This handles a fast-path optimization that projects the points before
creating any patches or lines. This means that the lines/patches will be
calculated in projected-space, not data-space. It requires the first
three arguments to be x, y, and z and all must be two-dimensional to use
the fast-path option.

It looks like we are creating new arrays for z even if you've already passed one in. I wonder if this:

x, y, z = (np.array(i) for i in args[:3])

should be np.asanyarray() instead of np.array() to respect any potential masks. I'm not sure if the take_along_axis later will respect the mask or not, but hopefully this gives someone some pointers on where to look to solve this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants