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

Plotting datetime time axis with filled contours #5549

Open vlvalenti opened 1 year ago

vlvalenti commented 1 year ago

ALL software version info

(this library, plus any other relevant software, e.g. bokeh, python, notebook, OS, browser, etc) holoviews 1.14.7
hvplot 0.8.1 python 3.8.12

Description of expected behavior and the observed behavior

Attempting to create lon/time or lat/time filled contour plots. Able to create contours, quadmesh, image, but produce holoviews based error with filled contours. Running example code will produce error, uncomment others to see correct plot.

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

import xarray as xr
import holoviews as hv
import hvplot.xarray
hv.extension('bokeh')

data = xr.tutorial.open_dataset('air_temperature').air.isel(time=slice(0,100)).mean(dim='lat')
# data.hvplot.contour(x='lon', y='time', levels=12) #this works, as does quadmesh and image plots
data.hvplot.contourf(x='lon', y='time', levels=12)

#same error not using hvplot
# hv.operation.contours(hv.QuadMesh(data, kdims=['lon', 'time'])) #works
# hv.operation.contours(hv.QuadMesh(data, kdims=['lon', 'time']), filled=True) 

Stack traceback and/or browser JavaScript console output

TypeError: float() argument must be a string or a number, not 'datetime.datetime'

Screen Shot 2022-12-07 at 12 15 37 PM

Screenshots or screencasts of the bug in action

ianthomas23 commented 1 year ago

I have further information on this as I have encountered it whilst working on #5910. There is no explicit testing within HoloViews for contouring data that has datetime coordinates, and I suspect this has never worked. Here's a simple reproducer (using commit 79008ed838 and matplotlib<3.8):

Screenshot 2023-10-05 at 10 11 52

If x and y are float coordinates then it successfully shows an image and both contour lines and filled contours. With x using datetimes it can produce an image and contour lines, but filled contours (not shown) raise an error in the hole manipulation code.

It is explained by how filled polygons store their exterior boundary and internal holes. The x and y coords of the exterior boundary are stored as separate numpy arrays, so they can have different dtypes. But holes are stored with the x and y coords stacked which means there can only be one dtype; if could be float or datetime but it cannot be both at the same time.

Changing the internal storage of holes within HoloViews is unlikely, so after discussing with @Hoxbro we think the best approach in the short term is to explicitly document what is and isn't supported here for filled polygons, and detect what isn't and raise a sensible exception to inform the user. Certainly one of the two x and y dimensions being datetimes isn't supported, we would like to think that both being datetimes should work OK but this will need checking. This will allow me to continue with #5910 which is urgent to support matplotlib 3.8.