holoviz / geoviews

Simple, concise geographical visualization in Python
http://geoviews.org
BSD 3-Clause "New" or "Revised" License
588 stars 75 forks source link

ValueError: assignment destination is read-only when using hvplot.quadmesh with resampled xarray dataset #659

Closed morf1102 closed 1 month ago

morf1102 commented 1 year ago

Description:

I encountered an issue when trying to visualize a resampled xarray dataset using hvplot.quadmesh in combination with geoviews. The goal was to use the xarray.Dataset.resample on my dataset to get the maximum values for each 12-hour intervals and then plot each variable on a map. However, this operation results in the following error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[12], line 1
----> 1 ibf = IBF_Class()

Cell In[11], line 8, in IBF_Class.__init__(self)
      6 self._init_sliders()
      7 self._get_time()
----> 8 self.source_mask = self._get_plot(self.time_ds, "jet").opts(alpha=0)
      9 self.hvrow = pn.Row("init")
     10 self._get_ibf_plot("init")

Cell In[11], line 82, in IBF_Class._get_plot(self, dataset, colormap, **params)
     80 def _get_plot(self, dataset: xr.Dataset, colormap: str, **params) -> hv.DynamicMap:
     81     # Generate a quadmesh plot using the hvplot library
---> 82     return dataset.hvplot.quadmesh(
     83         geo=True,
     84         project=True,
     85         rasterize=True,
     86         dynamic=True,
     87         cmap=colormap,
     88         colorbar=False,
     89         **params,
     90     )

File /mamba/envs/dev/lib/python3.10/site-packages/hvplot/plotting/core.py:2067, in hvPlot.quadmesh(self, x, y, z, colorbar, **kwds)
   2018 def quadmesh(self, x=None, y=None, z=None, colorbar=True, **kwds):
   2019     """
   2020     QuadMesh plot
   2021 
   (...)
   2065     - HoloViews: https://holoviews.org/reference/elements/bokeh/QuadMesh.html
   2066     """
-> 2067     return self(x, y, z=z, kind="quadmesh", colorbar=colorbar, **kwds)

File /mamba/envs/dev/lib/python3.10/site-packages/hvplot/plotting/core.py:92, in hvPlotBase.__call__(self, x, y, kind, **kwds)
     89         plot = self._get_converter(x, y, kind, **kwds)(kind, x, y)
     90         return pn.panel(plot, **panel_dict)
---> 92 return self._get_converter(x, y, kind, **kwds)(kind, x, y)

File /mamba/envs/dev/lib/python3.10/site-packages/hvplot/converter.py:1242, in HoloViewsConverter.__call__(self, kind, x, y)
   1240     from geoviews import project
   1241     projection = self._plot_opts.get('projection', ccrs.GOOGLE_MERCATOR)
-> 1242     obj = project(obj, projection=projection)
   1244 if not (self.datashade or self.rasterize):
   1245     layers = self._apply_layers(obj)

File /mamba/envs/dev/lib/python3.10/site-packages/param/parameterized.py:3658, in ParameterizedFunction.__new__(class_, *args, **params)
   3656 inst = class_.instance()
   3657 inst.param._set_name(class_.__name__)
-> 3658 return inst.__call__(*args,**params)

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/operation.py:220, in Operation.__call__(self, element, **kwargs)
    218 kwargs['link_dataset'] = self._propagate_dataset
    219 kwargs['link_inputs'] = self.p.link_inputs
--> 220 return element.apply(self, **kwargs)

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/accessors.py:43, in AccessorPipelineMeta.pipelined.<locals>.pipelined_call(*args, **kwargs)
     40     inst._obj._in_method = True
     42 try:
---> 43     result = __call__(*args, **kwargs)
     45     if not in_method:
     46         init_op = factory.instance(
     47             output_type=type(inst),
     48             kwargs={'mode': getattr(inst, 'mode', None)},
     49         )

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/accessors.py:199, in Apply.__call__(self, apply_function, streams, link_inputs, link_dataset, dynamic, per_element, **kwargs)
    197 if hasattr(apply_function, 'dynamic'):
    198     inner_kwargs['dynamic'] = False
--> 199 new_obj = apply_function(self._obj, **inner_kwargs)
    200 if (link_dataset and isinstance(self._obj, Dataset) and
    201     isinstance(new_obj, Dataset) and new_obj._dataset is None):
    202     new_obj._dataset = self._obj.dataset

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/operation.py:214, in Operation.__call__(self, element, **kwargs)
    210         return element.clone([(k, self._apply(el, key=k))
    211                               for k, el in element.items()])
    212     elif ((self._per_element and isinstance(element, Element)) or
    213           (not self._per_element and isinstance(element, ViewableElement))):
--> 214         return self._apply(element)
    215 elif 'streams' not in kwargs:
    216     kwargs['streams'] = self.p.streams

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/operation.py:141, in Operation._apply(self, element, key)
    139     if not in_method:
    140         element._in_method = True
--> 141 ret = self._process(element, key)
    142 if hasattr(element, '_in_method') and not in_method:
    143     element._in_method = in_method

File /mamba/envs/dev/lib/python3.10/site-packages/geoviews/operation/projection.py:452, in project._process(self, element, key)
    450 def _process(self, element, key=None):
    451     for op in self._operations:
--> 452         element = element.map(op.instance(projection=self.p.projection),
    453                               op.supported_types)
    454     return element

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/data/__init__.py:199, in PipelineMeta.pipelined.<locals>.pipelined_fn(*args, **kwargs)
    196     inst._in_method = True
    198 try:
--> 199     result = method_fn(*args, **kwargs)
    200     if PipelineMeta.disable:
    201         return result

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/data/__init__.py:1207, in Dataset.map(self, *args, **kwargs)
   1205 @wraps(LabelledData.map)
   1206 def map(self, *args, **kwargs):
-> 1207     return super().map(*args, **kwargs)

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/dimension.py:700, in LabelledData.map(self, map_fn, specs, clone)
    698     return deep_mapped
    699 else:
--> 700     return map_fn(self) if applies else self

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/operation.py:220, in Operation.__call__(self, element, **kwargs)
    218 kwargs['link_dataset'] = self._propagate_dataset
    219 kwargs['link_inputs'] = self.p.link_inputs
--> 220 return element.apply(self, **kwargs)

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/accessors.py:43, in AccessorPipelineMeta.pipelined.<locals>.pipelined_call(*args, **kwargs)
     40     inst._obj._in_method = True
     42 try:
---> 43     result = __call__(*args, **kwargs)
     45     if not in_method:
     46         init_op = factory.instance(
     47             output_type=type(inst),
     48             kwargs={'mode': getattr(inst, 'mode', None)},
     49         )

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/accessors.py:199, in Apply.__call__(self, apply_function, streams, link_inputs, link_dataset, dynamic, per_element, **kwargs)
    197 if hasattr(apply_function, 'dynamic'):
    198     inner_kwargs['dynamic'] = False
--> 199 new_obj = apply_function(self._obj, **inner_kwargs)
    200 if (link_dataset and isinstance(self._obj, Dataset) and
    201     isinstance(new_obj, Dataset) and new_obj._dataset is None):
    202     new_obj._dataset = self._obj.dataset

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/operation.py:214, in Operation.__call__(self, element, **kwargs)
    210         return element.clone([(k, self._apply(el, key=k))
    211                               for k, el in element.items()])
    212     elif ((self._per_element and isinstance(element, Element)) or
    213           (not self._per_element and isinstance(element, ViewableElement))):
--> 214         return self._apply(element)
    215 elif 'streams' not in kwargs:
    216     kwargs['streams'] = self.p.streams

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/operation.py:141, in Operation._apply(self, element, key)
    139     if not in_method:
    140         element._in_method = True
--> 141 ret = self._process(element, key)
    142 if hasattr(element, '_in_method') and not in_method:
    143     element._in_method = in_method

File /mamba/envs/dev/lib/python3.10/site-packages/geoviews/operation/projection.py:40, in _project_operation._process(self, element, key)
     39 def _process(self, element, key=None):
---> 40     return element.map(self._process_element, self.supported_types)

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/data/__init__.py:199, in PipelineMeta.pipelined.<locals>.pipelined_fn(*args, **kwargs)
    196     inst._in_method = True
    198 try:
--> 199     result = method_fn(*args, **kwargs)
    200     if PipelineMeta.disable:
    201         return result

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/data/__init__.py:1207, in Dataset.map(self, *args, **kwargs)
   1205 @wraps(LabelledData.map)
   1206 def map(self, *args, **kwargs):
-> 1207     return super().map(*args, **kwargs)

File /mamba/envs/dev/lib/python3.10/site-packages/holoviews/core/dimension.py:700, in LabelledData.map(self, map_fn, specs, clone)
    698     return deep_mapped
    699 else:
--> 700     return map_fn(self) if applies else self

File /mamba/envs/dev/lib/python3.10/site-packages/geoviews/operation/projection.py:298, in project_quadmesh._process_element(self, element)
    296         mask[:-1, 1:][to_mask[1:]] = True
    297         mask[:-1, :-1][to_mask[1:]] = True
--> 298         zs[mask] = np.NaN
    300 params = get_param_values(element)
    301 return element.clone((PX, PY, zs), crs=self.p.projection, **params)

ValueError: assignment destination is read-only

Additional information:

System Information:

Please let me know if any further information is required.

hoxbro commented 1 year ago

We can only find out what the problem is with a minimal, reproducible example (MRE).

morf1102 commented 1 year ago

Sorry for the delay; for some reason I encountered some difficulties in recreating the error with a MRE, but here's what I came up with:

import hvplot.xarray
import numpy as np
import pandas as pd
import xarray as xr
TT = np.random.randn(100, 100, 24)
lon = list(range(0, 100))
lat = list(range(0, 100))
time = pd.date_range("2023-07-05", periods=24, freq="1H")

ds = xr.Dataset(
    data_vars=dict(
        TT=(["lon", "lat", "time"], TT),
    ),
    coords=dict(lon=(["lon"], lon), lat=(["lat"], lat), time=(["time"], time)),
).chunk()

ds = ds.resample(time="3H").max()
ds.isel(time=0).hvplot.quadmesh(
    geo=True,
    project=True,
    rasterize=True,
    dynamic=True,
)
hoxbro commented 1 year ago

I don't get the error what are your versions of HoloViews and Datashader?

morf1102 commented 1 year ago

Holoviews : 1.16.1 Datashader: 0.15.0

hoxbro commented 1 year ago

Those seem like recent enough versions. Where do you see the error in Jupyter notebook / Jupyter lab / VScode?

morf1102 commented 1 year ago

Jupyter lab

ahuang11 commented 1 month ago

I cannot reproduce this in holoviews==1.19.1 and datashader==0.16.3 and geoviews==1.12.0

Going to close this for now, but please re-open if upgrading doesn't work for you.