I have a PointDraw
stream instance that gets updated on a vdim, but that does not trigger an event, like when I update the coordinate.
See the recording
When I change the table entry, the plot and the stream do get updated, but the method depending on the PointDraw.data is not called, i.e. I cannot rely on it (in the sense of param.depends
).
I am on holoviews 1.15.4
import param
import holoviews as hv
import panel as pn
hv.extension('bokeh')
import numpy as np
from holoviews.plotting.links import DataLink
from datetime import datetime
class AnnotatorInspired(param.Parameterized):
_points_stream = param.ClassSelector(class_=hv.streams.PointDraw)
_plot = param.ClassSelector(class_=hv.Points)
_labels = param.ClassSelector(class_=hv.Labels)
_table = param.ClassSelector(class_=hv.Table)
_force_update = param.Event(label='Force update')
_log = param.List(default=[])
def __init__(self, df):
args = dict(data=df, kdims=['x','y'], vdims=['name'])
plot = hv.Points(**args).opts(tools=["hover"],size=10, active_tools=['point_draw'])
labels = hv.Labels(**args)
table = hv.Table(**args).opts(editable=True)
DataLink(plot, table)
DataLink(plot, labels)
points_stream = hv.streams.PointDraw(data=df,source=plot,)
super().__init__(
_plot = plot,
_labels = labels,
_table = table,
_points_stream = points_stream,
_log = self._log
)
self.t0 = datetime.now()
self._log += [f"Object created at {self.t0}"]
@param.depends("_points_stream.data", watch=True)
def _update(self):
self._log += [f"points_stream.data triggered at {datetime.now()-self.t0}"]
#
@param.depends("_force_update",watch=True)
def _update1(self):
self._log += [f"force_update event triggered at {datetime.now()-self.t0}"]
show_log = pn.panel("")
button = pn.widgets.Button(name='Show Log', button_type='primary')
def fn(event,):
global A
# first three elements of the log are always created
show_log.object = "<pre>" + "\n".join(A._log[3:]) + "</pre>"
button.on_click(fn)
show_points_stream_data = pn.panel("")
def fn1(event,):
global A
data = A._points_stream.data
show_points_stream_data.object = "<pre>PointDraw stream content:\n" + "\n".join([
f'"x":\t{list(np.round(data["x"],3))}',
f'"y":\t{list(np.round(data["y"],3))}',
f'"name":\t{list(data["name"])}',
]) + "</pre>"
button.on_click(fn1)
A = AnnotatorInspired({'x':[0.,.1],'y':[1.,.9],"name":['far','near']})
button.clicks += 1
main = pn.Column(
pn.panel(A.param._force_update, width=30),
A._table.opts(height=100, width=300),
show_points_stream_data,
button,
show_log,
)
main = pn.Row(main, A._plot*A._labels,)
main.servable()