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

interpolation for Image is broken with datashade #6361

Open
1 task done
ahartikainen opened this issue Aug 15, 2024 · 0 comments
Open
1 task done

interpolation for Image is broken with datashade #6361

ahartikainen opened this issue Aug 15, 2024 · 0 comments
Labels
type: bug Something isn't correct or isn't working

Comments

@ahartikainen
Copy link

ALL software version info

(this library, plus any other relevant software, e.g. bokeh, python, notebook, OS, browser, etc)

Bokeh 3.4.3
Holoviews 1.18.1
Python 3.11.6
OS Windows 11 Pro

Description of expected behavior and the observed behavior

When sending holoviews.Image to datashade with interpolation="nearest" raises ValueError. Also interpolation=None has similar issues.

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

import numpy as np
import xarray as xr

import holoviews as hv
import holoviews.operation.datashader as hd
hd.shade.cmap=["lightblue", "darkblue"]
hv.extension("bokeh", "matplotlib") 
from bokeh.plotting import show

n = 10
data = xr.DataArray(np.random.randn(n,n), coords={"x": np.linspace(0,1,n), "y": np.linspace(0,10,n)}, dims=["x", "y"])

image = hv.Image(data)
hd_image = hd.datashade(image, interpolation="nearest", width=300, height=300)
show(hv.render(hd_image))

Stack traceback and/or browser JavaScript console output

ValueError: ObjectSelector parameter 'trimesh_rasterize.interpolation' does not accept 'nearest'; valid options include: '[bilinear, linear, None, False]'
Full traceback
WARNING:param.dynamic_operation: Callable raised "ValueError("ObjectSelector parameter 'trimesh_rasterize.interpolation' does not accept 'nearest'; valid options include: '[bilinear, linear, None, False]'")".
Invoked as dynamic_operation(height=300, scale=1.0, width=300, x_range=None, y_range=None)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File ~\miniconda3\envs\myenv\Lib\site-packages\IPython\core\formatters.py:974, in MimeBundleFormatter.__call__(self, obj, include, exclude)
    971     method = get_real_method(obj, self.print_method)
    973     if method is not None:
--> 974         return method(include=include, exclude=exclude)
    975     return None
    976 else:

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\core\dimension.py:1286, in Dimensioned._repr_mimebundle_(self, include, exclude)
   1279 def _repr_mimebundle_(self, include=None, exclude=None):
   1280     """
   1281     Resolves the class hierarchy for the class rendering the
   1282     object using any display hooks registered on Store.display
   1283     hooks.  The output of all registered display_hooks is then
   1284     combined and returned.
   1285     """
-> 1286     return Store.render(self)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\core\options.py:1428, in Store.render(cls, obj)
   1426 data, metadata = {}, {}
   1427 for hook in hooks:
-> 1428     ret = hook(obj)
   1429     if ret is None:
   1430         continue

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\ipython\display_hooks.py:287, in pprint_display(obj)
    285 if not ip.display_formatter.formatters['text/plain'].pprint:
    286     return None
--> 287 return display(obj, raw_output=True)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\ipython\display_hooks.py:261, in display(obj, raw_output, **kwargs)
    259 elif isinstance(obj, (HoloMap, DynamicMap)):
    260     with option_state(obj):
--> 261         output = map_display(obj)
    262 elif isinstance(obj, Plot):
    263     output = render(obj)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\ipython\display_hooks.py:149, in display_hook.<locals>.wrapped(element)
    147 try:
    148     max_frames = OutputSettings.options['max_frames']
--> 149     mimebundle = fn(element, max_frames=max_frames)
    150     if mimebundle is None:
    151         return {}, {}

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\ipython\display_hooks.py:209, in map_display(vmap, max_frames)
    206     max_frame_warning(max_frames)
    207     return None
--> 209 return render(vmap)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\ipython\display_hooks.py:76, in render(obj, **kwargs)
     73 if renderer.fig == 'pdf':
     74     renderer = renderer.instance(fig='png')
---> 76 return renderer.components(obj, **kwargs)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\plotting\renderer.py:396, in Renderer.components(self, obj, fmt, comm, **kwargs)
    393 embed = (not (dynamic or streams or self.widget_mode == 'live') or config.embed)
    395 if embed or config.comms == 'default':
--> 396     return self._render_panel(plot, embed, comm)
    397 return self._render_ipywidget(plot)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\plotting\renderer.py:403, in Renderer._render_panel(self, plot, embed, comm)
    401 doc = Document()
    402 with config.set(embed=embed):
--> 403     model = plot.layout._render_model(doc, comm)
    404 if embed:
    405     return render_model(model, comm)

File ~\miniconda3\envs\myenv\Lib\site-packages\panel\viewable.py:735, in Viewable._render_model(self, doc, comm)
    733 if comm is None:
    734     comm = state._comm_manager.get_server_comm()
--> 735 model = self.get_root(doc, comm)
    737 if self._design and self._design.theme.bokeh_theme:
    738     doc.theme = self._design.theme.bokeh_theme

File ~\miniconda3\envs\myenv\Lib\site-packages\panel\layout\base.py:319, in Panel.get_root(self, doc, comm, preprocess)
    315 def get_root(
    316     self, doc: Optional[Document] = None, comm: Optional[Comm] = None,
    317     preprocess: bool = True
    318 ) -> Model:
--> 319     root = super().get_root(doc, comm, preprocess)
    320     # ALERT: Find a better way to handle this
    321     if hasattr(root, 'styles') and 'overflow-x' in root.styles:

File ~\miniconda3\envs\myenv\Lib\site-packages\panel\viewable.py:666, in Renderable.get_root(self, doc, comm, preprocess)
    664 wrapper = self._design._wrapper(self)
    665 if wrapper is self:
--> 666     root = self._get_model(doc, comm=comm)
    667     if preprocess:
    668         self._preprocess(root)

File ~\miniconda3\envs\myenv\Lib\site-packages\panel\layout\base.py:185, in Panel._get_model(self, doc, root, parent, comm)
    183 root = root or model
    184 self._models[root.ref['id']] = (model, parent)
--> 185 objects, _ = self._get_objects(model, [], doc, root, comm)
    186 props = self._get_properties(doc)
    187 props[self._property_mapping['objects']] = objects

File ~\miniconda3\envs\myenv\Lib\site-packages\panel\layout\base.py:167, in Panel._get_objects(self, model, old_objects, doc, root, comm)
    165 else:
    166     try:
--> 167         child = pane._get_model(doc, root, model, comm)
    168     except RerenderError as e:
    169         if e.layout is not None and e.layout is not self:

File ~\miniconda3\envs\myenv\Lib\site-packages\panel\pane\holoviews.py:429, in HoloViews._get_model(self, doc, root, parent, comm)
    427     plot = self.object
    428 else:
--> 429     plot = self._render(doc, comm, root)
    431 plot.pane = self
    432 backend = plot.renderer.backend

File ~\miniconda3\envs\myenv\Lib\site-packages\panel\pane\holoviews.py:525, in HoloViews._render(self, doc, comm, root)
    522     if comm:
    523         kwargs['comm'] = comm
--> 525 return renderer.get_plot(self.object, **kwargs)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\plotting\bokeh\renderer.py:68, in BokehRenderer.get_plot(self_or_cls, obj, doc, renderer, **kwargs)
     61 @bothmethod
     62 def get_plot(self_or_cls, obj, doc=None, renderer=None, **kwargs):
     63     """
     64     Given a HoloViews Viewable return a corresponding plot instance.
     65     Allows supplying a document attach the plot to, useful when
     66     combining the bokeh model with another plot.
     67     """
---> 68     plot = super().get_plot(obj, doc, renderer, **kwargs)
     69     if plot.document is None:
     70         plot.document = Document() if self_or_cls.notebook_context else curdoc()

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\plotting\renderer.py:217, in Renderer.get_plot(self_or_cls, obj, doc, renderer, comm, **kwargs)
    214     raise SkipRendering(msg.format(dims=dims))
    216 # Initialize DynamicMaps with first data item
--> 217 initialize_dynamic(obj)
    219 if not renderer:
    220     renderer = self_or_cls

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\plotting\util.py:270, in initialize_dynamic(obj)
    268     continue
    269 if not len(dmap):
--> 270     dmap[dmap._initial_key()]

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\core\spaces.py:1216, in DynamicMap.__getitem__(self, key)
   1214 # Not a cross product and nothing cached so compute element.
   1215 if cache is not None: return cache
-> 1216 val = self._execute_callback(*tuple_key)
   1217 if data_slice:
   1218     val = self._dataslice(val, data_slice)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\core\spaces.py:983, in DynamicMap._execute_callback(self, *args)
    980     kwargs['_memoization_hash_'] = hash_items
    982 with dynamicmap_memoization(self.callback, self.streams):
--> 983     retval = self.callback(*args, **kwargs)
    984 return self._style(retval)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\core\spaces.py:581, in Callable.__call__(self, *args, **kwargs)
    578     args, kwargs = (), dict(pos_kwargs, **kwargs)
    580 try:
--> 581     ret = self.callable(*args, **kwargs)
    582 except KeyError:
    583     # KeyError is caught separately because it is used to signal
    584     # invalid keys on DynamicMap and should not warn
    585     raise

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\util\__init__.py:1034, in Dynamic._dynamic_operation.<locals>.dynamic_operation(*key, **kwargs)
   1032 def dynamic_operation(*key, **kwargs):
   1033     key, obj = resolve(key, kwargs)
-> 1034     return apply(obj, *key, **kwargs)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\util\__init__.py:1026, in Dynamic._dynamic_operation.<locals>.apply(element, *key, **kwargs)
   1024 def apply(element, *key, **kwargs):
   1025     kwargs = dict(util.resolve_dependent_kwargs(self.p.kwargs), **kwargs)
-> 1026     processed = self._process(element, key, kwargs)
   1027     if (self.p.link_dataset and isinstance(element, Dataset) and
   1028         isinstance(processed, Dataset) and processed._dataset is None):
   1029         processed._dataset = element.dataset

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\util\__init__.py:1008, in Dynamic._process(self, element, key, kwargs)
   1006 elif isinstance(self.p.operation, Operation):
   1007     kwargs = {k: v for k, v in kwargs.items() if k in self.p.operation.param}
-> 1008     return self.p.operation.process_element(element, key, **kwargs)
   1009 else:
   1010     return self.p.operation(element, **kwargs)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\core\operation.py:194, in Operation.process_element(self, element, key, **params)
    191 else:
    192     self.p = param.ParamOverrides(self, params,
    193                                   allow_extra_keywords=self._allow_extra_keywords)
--> 194 return self._apply(element, key)

File ~\miniconda3\envs\myenv\Lib\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 ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\operation\datashader.py:1528, in datashade._process(self, element, key)
   1527 def _process(self, element, key=None):
-> 1528     agg = rasterize._process(self, element, key)
   1529     shaded = shade._process(self, agg, key)
   1530     return shaded

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\operation\datashader.py:1504, in rasterize._process(self, element, key)
   1502 print({k for k in extended_kws.items()})
   1503 print(f"{list(transform.param)=}")
-> 1504 op = transform.instance(**{k:v for k,v in extended_kws.items()
   1505                             if k in transform.param})
   1506 op._precomputed = self._precomputed
   1507 element = element.map(op, predicate)

File ~\miniconda3\envs\myenv\Lib\site-packages\holoviews\operation\resample.py:115, in ResampleOperation2D.instance(self_or_cls, **params)
    112 @bothmethod
    113 def instance(self_or_cls,**params):
    114     filtered = {k:v for k,v in params.items() if k in self_or_cls.param}
--> 115     inst = super().instance(**filtered)
    116     inst._precomputed = {}
    117     return inst

File ~\miniconda3\envs\myenv\Lib\site-packages\param\parameterized.py:4459, in ParameterizedFunction.instance(self_or_cls, **params)
   4456     cls = self_or_cls.__class__
   4458 inst=Parameterized.__new__(cls)
-> 4459 Parameterized.__init__(inst,**params)
   4460 if 'name' in params:  inst.__name__ = params['name']
   4461 else:                 inst.__name__ = self_or_cls.name

File ~\miniconda3\envs\myenv\Lib\site-packages\param\parameterized.py:4188, in Parameterized.__init__(self, **params)
   4186 if self.param.name.default == self.__class__.__name__:
   4187     self.param._generate_name()
-> 4188 refs, deps = self.param._setup_params(**params)
   4189 object_count += 1
   4191 self._param__private.initialized = True

File ~\miniconda3\envs\myenv\Lib\site-packages\param\parameterized.py:1686, in as_uninitialized.<locals>.override_initialization(self_, *args, **kw)
   1684 original_initialized = parameterized_instance._param__private.initialized
   1685 parameterized_instance._param__private.initialized = False
-> 1686 ret = fn(self_, *args, **kw)
   1687 parameterized_instance._param__private.initialized = original_initialized
   1688 return ret

File ~\miniconda3\envs\myenv\Lib\site-packages\param\parameterized.py:1967, in Parameters._setup_params(self_, **params)
   1955         if ref:
   1956             warnings.warn(
   1957                 f"Parameter {name!r} on {pobj.owner} is being given a valid parameter "
   1958                 f"reference {val} but is implicitly allow_refs=False. "
   (...)
   1965                 stacklevel=4,
   1966             )
-> 1967     setattr(self, name, val)
   1968     continue
   1970 # Resolve references

File ~\miniconda3\envs\myenv\Lib\site-packages\param\parameterized.py:530, in instance_descriptor.<locals>._f(self, obj, val)
    528         instance_param.__set__(obj, val)
    529         return
--> 530 return f(self, obj, val)

File ~\miniconda3\envs\myenv\Lib\site-packages\param\parameterized.py:1498, in Parameter.__set__(self, obj, val)
   1490     if self.set_hook is not _identity_hook:
   1491         # PARAM3_DEPRECATION
   1492         warnings.warn(
   1493             'Number.set_hook has been deprecated.',
   1494             category=_ParamDeprecationWarning,
   1495             stacklevel=6,
   1496         )
-> 1498 self._validate(val)
   1500 _old = NotImplemented
   1501 # obj can be None if __set__ is called for a Parameterized class

File ~\miniconda3\envs\myenv\Lib\site-packages\param\parameters.py:1933, in Selector._validate(self, val)
   1930     self._ensure_value_is_in_objects(val)
   1931     return
-> 1933 self._validate_value(val)

File ~\miniconda3\envs\myenv\Lib\site-packages\param\parameters.py:1949, in Selector._validate_value(self, val)
   1947         break
   1948 items = '[' + ', '.join(items) + limiter
-> 1949 raise ValueError(
   1950     f"{_validate_error_prefix(self)} does not accept {val!r}; "
   1951     f"valid options include: {items!r}"
   1952 )

ValueError: ObjectSelector parameter 'trimesh_rasterize.interpolation' does not accept 'nearest'; valid options include: '[bilinear, linear, None, False]'
  • I may be interested in making a pull request to address this

Source of the error

I think the error is created at this line

op = transform.instance(**{k:v for k,v in extended_kws.items()

The transformations and the loop going through them

_transforms = [(Image, regrid),
(Polygons, geometry_rasterize),
(lambda x: (isinstance(x, (Path, Points)) and
'spatialpandas' in x.interface.datatype),
geometry_rasterize),
(TriMesh, trimesh_rasterize),
(QuadMesh, quadmesh_rasterize),
(lambda x: (isinstance(x, NdOverlay) and
issubclass(x.type, (Scatter, Points, Curve, Path))),
aggregate),
(Spikes, spikes_aggregate),
(Area, area_aggregate),
(Spread, spread_aggregate),
(Segments, segments_aggregate),
(Rectangles, rectangle_aggregate),
(Contours, contours_rasterize),
(Graph, aggregate),
(Scatter, aggregate),
(Points, aggregate),
(Curve, curve_aggregate),
(Path, aggregate),
(type(None), shade) # To handle parameters of datashade
]

for predicate, transform in self._transforms:
merged_param_values = dict(instance_params, **self.p)
# If aggregator or interpolation are 'default', pop parameter so
# datashader can choose the default aggregator itself
for k in ['aggregator', 'interpolation']:
if merged_param_values.get(k, None) == 'default':
merged_param_values.pop(k)
op_params = dict({k: v for k, v in merged_param_values.items()
if not (v is None and k == 'aggregator')},
dynamic=False)
extended_kws = dict(op_params, **self.p.extra_keywords())
all_supplied_kws |= set(extended_kws)
all_allowed_kws |= set(transform.param)
# Collect union set of consumed. Versus union of available.
op = transform.instance(**{k:v for k,v in extended_kws.items()

@hoxbro hoxbro added the type: bug Something isn't correct or isn't working label Aug 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't correct or isn't working
Projects
None yet
Development

No branches or pull requests

2 participants