I need to listen to client-side events on plots made with hvplot.line but am not having success. I have tried:
import pandas as pd
import holoviews as hv
def update_handler(e):
print(e)
df = pd.DataFrame([[1,2],[3,4]])
plot = df.hvplot.line()
plot.on_event('rangesupdate', update_handler)
the above code results in
AttributeError: 'NdOverlay' object has no attribute 'on_event'
Help is appreciated
With some digging around I have a solution. The NdOverlay is part of a rich hierarchy of objects. I found this resource very helpful: Building Composite Objects ā HoloViews v1.16.0
I had to set up a stream and then bind the client-side event Iām interested (changes in the x_range) to a server-side python function. Here is a working implementation:
import numpy as np
import pandas as pd
import holoviews as hv
import panel as pn
import hvplot.pandas
hv.extension('bokeh')
pn.extension()
def x_range_changed(xr):
value = f"x_range changed to: ({xr[0]:.3f}, {xr[1]:.3f})" if xr else None
print(value)
num_pts = 1000
df1 = pd.DataFrame({'x': np.linspace(0, 100, num_pts),
'y1': np.cumsum(np.random.randn(num_pts)),
'y2': np.cumsum(np.random.randn(num_pts))})
overlay = df1.hvplot.line(x='x', y=['y1', 'y2']) # return type is NdOverlay
# however note that the following returns a Curve
hvObject = df1.hvplot.line(x='x', y=['y1'])
print(type(hvObject)) # <class 'holoviews.element.chart.Curve'>
# get the underlying curve
curve = next(iter(overlay.data.values())) # grab the first Curve object
rng = hv.streams.RangeX(source=curve)
client_to_server_link = pn.bind(x_range_changed, xr=rng.param.x_range)
column = pn.Column(overlay, client_to_server_link)
column.servable()
1 Like