holoviz / holoviews

With Holoviews, your data visualizes itself.
https://holoviews.org
BSD 3-Clause "New" or "Revised" License
2.7k stars 402 forks source link

Contour doesn't handle NaNs properly #5779

Open kcpevey opened 1 year ago

kcpevey commented 1 year ago

ALL software version info

hvplot 0.8.4 holoviews 1.16.2

Description of expected behavior and the observed behavior

I want to plot my data on a contour plot. I'm getting an empty plot.

I can plot the same data with hvplot.quadmesh just fine image

But the hvplot.contour plot is empty and I get a warning about none of the projected data falling within the bounds of the plot.

image

Complete, minimal, self-contained example code that reproduces the issue

import xarray as xr
import hvplot.xarray
import cartopy.crs as ccrs

ds = xr.open_dataset('http://geoport.usgs.esipfed.org/thredds/dodsC/bathy/etopo1_bed_g2')

na = ds.topo.sel(lon=slice(-130,-50),lat=slice(15,50))   # North America
na = na.where(na < 0)
na = na.where(na > -1000)

bathy = na.hvplot.quadmesh(x='lon', y='lat', rasterize=True, geo=True, project=True, cmap='viridis', frame_width=800, crs=ccrs.PlateCarree())

contours = na.hvplot.contour(x='lon', y='lat', levels=5, cmap=['#000000'], 
                             geo=True, crs=ccrs.PlateCarree())
contours

Findings:

I was able to determine that the contour function isn't properly handling NaNs in the dataset. If you comment out the

na = na.where(na < 0)
na = na.where(na > -1000)

Then there are no NaNs in the dataset and the contours plot fine.

Also, if I remove geo=True, the contouring works properly

bathy.hvplot.contour(x='lon', y='lat', levels=5, cmap=['#000000']).opts(projection=ccrs.PlateCarree())

Finally, adding project=True to the contour plot will throw an error:

bathy.hvplot.contour(x='lon', y='lat', levels=1, cmap=['#000000'], geo=True, project=True, crs=ccrs.PlateCarree())

File /home/conda/global/d346bceda0a73e0d4a1d000f6e408ff98f97300889e28f2363f683db19a0f74c-20230620-190627-268969-5-hytest-workshop/lib/python3.10/site-packages/holoviews/plotting/bokeh/element.py:903, in ElementPlot._update_ranges(self, element, ranges)
    901 if fixed_height:
    902     plot.frame_height = height
--> 903     plot.frame_width = int(height/aspect)
    904     plot.width, plot.height = None, None
    905 elif fixed_width:

ValueError: cannot convert float NaN to integer

I can't tell if this is one issue or two, but I'd suggest switching the contouring to contourpy to improve the data handling.

hoxbro commented 1 year ago

I'm not completely sure, the hvplot.contour is a holoviews problem. hvplot is doing a lot of guessing when it comes to geo stuff.

Just a note for future reference contourpy can not be a direct dependency as it is not compatible with pyodide.

philippjfr commented 1 year ago

Just a note for future reference contourpy can not be a direct dependency as it is not compatible with pyodide.

It is already a direct dependency of bokeh so we don't have to do anything to require it. I can live with contours not working in pyodide.

ianthomas23 commented 1 year ago

There is now a pyodide build of contourpy pyodide/pyodide#4102.