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 not plotting negative contours in certain cases #2336

Open
dsroberts opened this issue Mar 4, 2024 · 2 comments
Open

Contourf not plotting negative contours in certain cases #2336

dsroberts opened this issue Mar 4, 2024 · 2 comments

Comments

@dsroberts
Copy link

Description

In some very specific circumstances, negative contours will not be shown, and some odd contours are shown in a contourf plot. The code below demonstrates the issue, but the issue is not present when the central_longitude argument to projection=ccrs.PlateCarree() is 0 or removed, or when the contour levels are not centered around 0 or extended beyond levels=np.arange(-4,4.4,0.4). The researcher I'm helping with this has 3 other similar contourf plots (same levels, central_longitude=180) that don't have this issue. The issue is present in the latest cartopy 0.22.0 conda-forge release, and in the current main branch, though only present for Matplotlib >= 3.8. Example plots are below:
mpl38_cl0
Cartopy main, matplotlib 3.8.3, central_longitude=0
mpl38_cl1
Cartopy main, matplotlib 3.8.3, central_longitude=1
cartopy_main_mpl37_cl1
Cartopy main, matplotlib 3.7.5, central_longitude=1

Looking through some of the other contourf based issues, this one seems similar to #2288, #1822 and #1076, but distinct in some way from all of those.

Code to reproduce

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import numpy as np
import netCDF4
ds = netCDF4.Dataset('dataset.nc','r')
ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=1))
ax.contourf(np.array(ds['lon']),np.array(ds['lat']),np.array(ds['a']),transform=ccrs.PlateCarree(),levels=np.arange(-2,2.2,0.2),extend='both')
plt.show()

With dataset.nc.gz

Full environment definition

Operating system

linux-64

Cartopy version

0.22.1.dev109+g36eb99ef

pip list

Package         Version
--------------- -----------------------
Cartopy         0.22.1.dev109+g36eb99ef
certifi         2024.2.2
cftime          1.6.3
contourpy       1.2.0
cycler          0.12.1
fonttools       4.49.0
kiwisolver      1.4.5
matplotlib      3.8.3
netCDF4         1.6.5
numpy           1.26.4
packaging       23.2
pillow          10.2.0
pip             23.2.1
pyparsing       3.1.1
pyproj          3.6.1
pyshp           2.3.1
python-dateutil 2.9.0.post0
shapely         2.0.3
six             1.16.0
@rcomer
Copy link
Member

rcomer commented Mar 5, 2024

Thanks for the report and the clear reproducer @dsroberts. This seems reminiscent of #2224 which I ultimately solved by locating the specific problem level and analyzing that. I had some trouble locating the problem level in this case as it seems to be very specific to the slightly off-zero value generated by arange. But now I have this:

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

ds = netCDF4.Dataset('dataset.nc','r')

def try_plot(lev0):
    ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=1))
    cf = ax.contourf(np.array(ds['lon']), np.array(ds['lat']), np.array(ds['a']), transform=ccrs.PlateCarree(), levels=[lev0, lev0+0.2], extend='both')
    plt.colorbar(cf)
    plt.show()


try_plot(-4.44e-16)
try_plot(0)

The slightly negative value give this (bad!)
image

Whereas zero give this (good!)
image

A workaround for your researcher might be to use levels=np.linspace(-2, 2, 21), which gives me this:

image

@dsroberts
Copy link
Author

Thanks for looking into this @rcomer. I will pass your recommendation on. I played around with your try_plot function and got some interesting results. The resultant contours are extremely sensitive to that central value.
044
try_plot(-4.44e-16)
000
try_plot(0)
050
try_plot(-5e-16)
040
try_plot(-4e-16)
045
try_plot(-4.5e-16)

I also added lev0 to the data (after casting it to float64) which would align the 'zeros' in the data with the middle level, and this resulted in 5 identical plots. I guess this would indicate a floating point conversion and/or equality error somewhere?

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

No branches or pull requests

2 participants