holoviews icon indicating copy to clipboard operation
holoviews copied to clipboard

Errors with apply_when, rasterize, and ImageStack

Open maximlt opened this issue 10 months ago • 1 comments

I got two errors when running the script below (notebook and served) and zooming in.

The first one was raised in the web console and happens shortly after starting to zoom in. It seems like it happens when data from one category is no longer present in the viewport:

Error: Expected 5 not 4 colors in palette
    a https://cdn.bokeh.org/bokeh/release/bokeh-3.7.3.min.js:178
    c https://cdn.bokeh.org/bokeh/release/bokeh-3.7.3.min.js:178
    _v_compute_uint32 https://cdn.bokeh.org/bokeh/release/bokeh-3.7.3.min.js:455
    v_compute https://cdn.bokeh.org/bokeh/release/bokeh-3.7.3.min.js:383
    _flat_img_to_buf8 https://cdn.bokeh.org/bokeh/release/bokeh-3.7.3.min.js:559
...

The second one happens in Python, and later, I think at the moment when the rasterize operation is no longer applied by apply_when:

Traceback (most recent call last):
  File "/Users/mliquet/dev/holoviews/holoviews/plotting/util.py", line 305, in get_plot_frame
    return map_obj[key]
           ~~~~~~~^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/core/spaces.py", line 1302, in __getitem__
    val = self._execute_callback(*tuple_key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/core/spaces.py", line 1050, in _execute_callback
    retval = self.callback(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/core/spaces.py", line 597, in __call__
    return self.callable()
           ^^^^^^^^^^^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/util/__init__.py", line 1071, in dynamic_operation
    key, obj = resolve(key, kwargs)
               ^^^^^^^^^^^^^^^^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/util/__init__.py", line 1060, in resolve
    return key, map_obj[key]
                ~~~~~~~^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/core/spaces.py", line 1302, in __getitem__
    val = self._execute_callback(*tuple_key)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/core/spaces.py", line 1050, in _execute_callback
    retval = self.callback(*args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/core/spaces.py", line 597, in __call__
    return self.callable()
           ^^^^^^^^^^^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/core/spaces.py", line 212, in dynamic_mul
    self_el = self.select(HoloMap, **key_map) if self.kdims else self[()]
                                                                 ~~~~^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/core/spaces.py", line 1305, in __getitem__
    self._cache(tuple_key, val)
  File "/Users/mliquet/dev/holoviews/holoviews/core/spaces.py", line 1380, in _cache
    self[key] = val
    ~~~~^^^^^
  File "/Users/mliquet/dev/holoviews/holoviews/core/ndmapping.py", line 615, in __setitem__
    self._add_item(key, value, update=False)
  File "/Users/mliquet/dev/holoviews/holoviews/core/ndmapping.py", line 163, in _add_item
    self._item_check(dim_vals, data)
  File "/Users/mliquet/dev/holoviews/holoviews/core/ndmapping.py", line 1061, in _item_check
    raise AssertionError(f"{self.__class__.__name__} must only contain one type of object, not both {type(data).__name__} and {self.type.__name__}.")
AssertionError: DynamicMap must only contain one type of object, not both Image and ImageStack.
import numpy as np
import pandas as pd
import holoviews as hv
import datashader as ds
from holoviews.operation import apply_when
from holoviews.operation.datashader import rasterize

hv.extension('bokeh')

def create_synthetic_dataset(x, y, s, val, cat):
    seed = np.random.default_rng(1)
    num = 10_000
    return pd.DataFrame(
        {"x": seed.normal(x, s, num), "y": seed.normal(y, s, num), "s": s, "val": val, "cat": cat}
    )

df = pd.concat(
    {
        cat: create_synthetic_dataset(x, y, s, val, cat)
        for x, y, s, val, cat in [
            (2, 2, 0.03, 0, "d1"),
            (2, -2, 0.10, 1, "d2"),
            (-2, -2, 0.50, 2, "d3"),
            (-2, 2, 1.00, 3, "d4"),
            (0, 0, 3.00, 4, "d5"),
        ]
    },
    ignore_index=True,
)

points = hv.Points(df, kdims=['x', 'y'], vdims=['cat'])

def op(obj):
    return rasterize(obj, aggregator=ds.count_cat('cat'))

p = apply_when(points, operation=op, predicate=lambda obj: len(obj) > 1000)
p
Image

maximlt avatar Jun 13 '25 14:06 maximlt

The second problem should be fixed by #6628

The first problem does not seem to break the code completely, but it changes the coloring when zooming in.

https://github.com/user-attachments/assets/3a4f3474-bf63-4da4-99c5-b4c029aa9ca2

hoxbro avatar Jun 19 '25 17:06 hoxbro