I am encountering many issues and I don’t know exactly where to start. I can give 2 mock-ups of what I have been investigating
Integrated workflow
Here I want to to highlight how many indirections are involved. What I am trying to code is something along the lines of:
import param
import panel
import xarray
import hvplot
import dataclasses
ds: xarray.Dataset = _get_dataset()
@dataclasses.dataclass
class Plotter:
ds: xarray.Dataset
"""Plot helper that I reuse across multiple jupyter cells"""
def plot_line(self, field: str, x: str, indexers: dict[str, Any]) -> param.rx:
da: xarray.DataArray = self.ds[field]
def select_and_plot(_data: xarray.DataArray, **_indexers: Any) -> holoviews.Curve:
plot_data = _data.sel(_indexers)
# Do some post-processing, e.g.
plot_data = plot_data.dropna(x, "all")
curve: holoviews.Curve = plot_data.hvplot(kind="line", x=x)
return curve
rx_curve = param.rx(select_and_plot)(data, **indexers)
return rx_curve
# Prepare widgets which have complex dependencies
# I am mixing panel and param.rx a lot in it
rx_I = panel.widgets.DiscreteSlider(name="Laser intensity", options=[1e-3, 1e-5])
def filter_run(I: float) -> list[str]:
runs = ds["run"]
runs = runs.where((runs.I == I), drop=True)
return [run.item() for run in runs]
run_list = param.rx(filter_run)(I=rx_I)
rx_run = panel.widgets.Select(name="Run", options=runs)
plot = Plotter(ds)
# Here is where the uncertainty and experimentation breaks down
layout = param.rx(holoviews.Layout())
# layout = holoviews.Layout()
for dim in ["x", "y"]:
overlay = param.rx(holoviews.Overlay())
# overlay = holoviews.Overlay()
overlay *= plot.plot_line("laser", x="t",
indexers={"run": rx_run})
overlay *= plot.plot_line("other_value", x="t",
indexers={"run": rx_run.rx, "dim": dim})
# The following does not work. There is a lot of experimentation between using .rx.value and
# not using param.rx on holviews.Layout/Overlay
# layout += overlay
layout += overlay.rx.value
# Automatic widgets are not picking up the intermediate dependent of rx_I
widgets = panel.WidgetBox(rx_I, rx_run)
panel.Row(widget, layout.rx.value)
After much experimentation, I might have figured how to work with the holoviews
composition, but I am not sure it is appropriate because I cannot get the whole thing to update and work appropriately
Some issues found
I have segregated some issues that I believe I am encountering
panel
and param.rx
do not update
import hvplot.xarray
import param
import panel
rx_I = panel.widgets.DiscreteSlider(name="Laser intensity", options=[1e-3, 1e-5])
val = param.rx()
val.rx.value = rx_I
panel.Row(rx_I, val)
Running this and updating the widget does not change the displayed text. I have tried splitting it across cells, adding param.rx
around the callers, but nothing helped
I have finally narrowed down the issues being with using .rx.value
, which apparently I should never be doing. I still have to use param.rx(holoviews.Layout)
otherwise I get:
ValueError: not enough values to unpack (expected 2, got 0)
This is not so bad because it is initially intuitive because we need to create reactive objects, but once you dig deeper into the indirection, it is no longer as intuitive since internal variables need to be the original data type, e.g. in order to use xarray.DataArray.sel()