I guess my issue is either a bug or is very easy to solve, if someone knows how:
Above you see a mini app created by belows self-contained minimal example:
it creates some dummy histograms and shows a DropDown widget to select and visualize a single histogram.
Further, each Histogram object has the Boolean param.Parameter normed
.
Changing normed
triggers a new histogram calculation (norming the y-axis/density) and updates the plot correspondingly. (I love param+panel+holoviews)
Each Histogram has it’s own normed
Parameter, but what I need is a “global” normed
, affecting all Histogram() instances.
Trying that with the per_instance=False
flag and/or with param.shared_parameters()
achieves this but prevents param.depends("normed")
from triggering the corresponding function and updating the DynamicMap.
How can I achieve aboves working behaviour WITH a global normed
Parameter?
It still is important to me, that normed
is a Parameter of the Histogram() class!
The following code produces aboves minimal example.
Add per_instance=False
in the normed
param.Boolean definition and re-run the code, to see what I mean by " prevents param.depends("normed")
from triggering".
import numpy as np
import holoviews as hv
import param
import panel as pn
hv.extension("bokeh")
pn.extension()
class Histogram(param.Parameterized):
normed: bool = param.Boolean(True) #! PUTTING per_instance=False HERE, PREVENTS Histogram.show() TO BE TRIGGERED
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.data = np.random.normal(loc=0, scale=5, size=1000)
def calculate_histogram(self):
np_hist = np.histogram(self.data, bins=50, density=self.normed)
y_label = "Frequency (normed)" if self.normed else "Frequency"
return hv.Histogram(np_hist).opts(ylabel=y_label, framewise=True)
@param.depends("normed")
def show(self, **kwargs):
return hv.DynamicMap(self.calculate_histogram)
class HistogramContainer:
def __init__(self, num_histograms=10):
with param.shared_parameters(): # Having this context manager or not does not change anything
self.histograms = {f"Histogram_{i+1}": Histogram() for i in range(num_histograms)}
def histogram_explorer(histogram_container: HistogramContainer):
select_histogram = pn.widgets.Select(
options=[name for name in histogram_container.histograms.keys()],
name="Histograms",
width=220,
)
@pn.depends(hist=select_histogram)
def show_hist(hist):
histogram_of_interest = histogram_container.histograms[hist]
return pn.Column(histogram_of_interest.param.normed, pn.Pane(histogram_of_interest.show))
return pn.Column(select_histogram, show_hist).servable()
my_histograms = HistogramContainer()
histogram_explorer(my_histograms)
Thank you! I appreciate the HoloViz community support a lot.