holoviz / hvplot

A high-level plotting API for pandas, dask, xarray, and networkx built on HoloViews
https://hvplot.holoviz.org
BSD 3-Clause "New" or "Revised" License
1.14k stars 109 forks source link

Explorers raises error when data type changes #964

Open hoxbro opened 2 years ago

hoxbro commented 2 years ago

The sliders used for xlim/ylim are very sensitive to the initial data type .An example of this is if ylim sliders are calculated based on a number array, and then y is changed to a datetime array, it will raise an error.

https://user-images.githubusercontent.com/19758978/201969509-d8a33899-4468-490f-9686-10167ee65624.mp4

import numpy as np
import pandas as pd

data = dict(
    x=np.arange(10),
    y=np.arange(10) + 10,
    t=pd.date_range("2020-01-01", freq="1d", periods=10),
)
df = pd.DataFrame(data)

hvplot.explorer(df)
Traceback (most recent call last):
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/pyviz_comms/__init__.py", line 346, in _handle_msg
    self._on_msg(msg)
  File "/home/shh/Development/holoviz/repos/panel/panel/viewable.py", line 297, in _on_msg
    doc.unhold()
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/bokeh/document/document.py", line 799, in unhold
    self.callbacks.unhold()
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 396, in unhold
    self.trigger_on_change(event)
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 373, in trigger_on_change
    invoke_with_curdoc(doc, event.callback_invoker)
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/bokeh/document/callbacks.py", line 408, in invoke_with_curdoc
    return f()
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/bokeh/util/callback_manager.py", line 191, in invoke
    callback(attr, old, new)
  File "/home/shh/Development/holoviz/repos/panel/panel/reactive.py", line 403, in _comm_change
    state._handle_exception(e)
  File "/home/shh/Development/holoviz/repos/panel/panel/io/state.py", line 406, in _handle_exception
    raise exception
  File "/home/shh/Development/holoviz/repos/panel/panel/reactive.py", line 401, in _comm_change
    self._schedule_change(doc, comm)
  File "/home/shh/Development/holoviz/repos/panel/panel/reactive.py", line 383, in _schedule_change
    self._change_event(doc)
  File "/home/shh/Development/holoviz/repos/panel/panel/reactive.py", line 379, in _change_event
    self._process_events(events)
  File "/home/shh/Development/holoviz/repos/panel/panel/reactive.py", line 318, in _process_events
    self.param.update(**self_events)
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 1898, in update
    self_._batch_call_watchers()
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 2059, in _batch_call_watchers
    self_._execute_watcher(watcher, events)
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 2021, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/home/shh/Development/holoviz/repos/panel/panel/param.py", line 496, in link_widget
    self.object.param.update(**{p_name: change.new})
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 1898, in update
    self_._batch_call_watchers()
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 2059, in _batch_call_watchers
    self_._execute_watcher(watcher, events)
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 2021, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 669, in caller
    return function()
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 407, in _depends
    return func(*args, **kw)
  File "/home/shh/Development/holoviz/repos/hvplot/hvplot/ui.py", line 189, in _update_ranges
    self.param.ylim.bounds = ylim
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 1137, in __setattr__
    self.owner.param._call_watcher(watcher, event)
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 2039, in _call_watcher
    self_._execute_watcher(watcher, (event,))
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 2021, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/home/shh/Development/holoviz/repos/panel/panel/param.py", line 588, in link
    widget.param.update(**updates)
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 1898, in update
    self_._batch_call_watchers()
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 2059, in _batch_call_watchers
    self_._execute_watcher(watcher, events)
  File "/home/shh/Development/holoviz/repos/param/param/parameterized.py", line 2021, in _execute_watcher
    watcher.fn(*args, **kwargs)
  File "/home/shh/Development/holoviz/repos/panel/panel/reactive.py", line 308, in _param_change
    self._apply_update(named_events, msg, model, ref)
  File "/home/shh/Development/holoviz/repos/panel/panel/reactive.py", line 240, in _apply_update
    self._update_model(events, msg, root, model, doc, comm)
  File "/home/shh/Development/holoviz/repos/panel/panel/widgets/slider.py", line 95, in _update_model
    return super()._update_model(events, msg, root, model, doc, comm)
  File "/home/shh/Development/holoviz/repos/panel/panel/reactive.py", line 263, in _update_model
    model.update(**msg)
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/bokeh/core/has_props.py", line 413, in update
    setattr(self, k, v)
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/bokeh/core/has_props.py", line 230, in __setattr__
    return super().__setattr__(name, value)
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/bokeh/core/property/descriptors.py", line 283, in __set__
    value = self.property.prepare_value(obj, self.name, value)
  File "/home/shh/miniconda3/envs/holoviz/lib/python3.10/site-packages/bokeh/core/property/bases.py", line 365, in prepare_value
    raise ValueError(f"failed to validate {obj_repr}.{name}: {error}")
ValueError: failed to validate RangeSlider(id='13053', ...).start: expected a value of type Real, got 2020-01-01T00:00:00.000000000 of type datetime64
maximlt commented 1 year ago

Just got hit by this bug too.

maximlt commented 1 year ago

Param doesn't complain when the bounds of a Range Parameter is set with weird values.

import param

class X(param.Parameterized):
    xlim = param.Range(bounds=('a', 'b'))

x = X()

Same when the bounds are being updated. In the OP the bounds are updated with np.datetime64 values.

hoxbro commented 1 year ago

I have opened two issues related to this bug: https://github.com/holoviz/panel/issues/4127 and https://github.com/holoviz/param/issues/660

I Will submit a PR with a workaround I talked with @maximlt about to avoid the error and have some of the functionality needed.