Say I have the following code, which switches between two holoviews Points plots based on a Radio Button. If you click on one of the points, a corresponding timeseries plot pops up to the right.
import pandas as pd
import holoviews as hv
import panel as pn
import numpy as np
hv.extension('bokeh')
####Create example data - just copy and past this part####
##########################################################
df = pd.DataFrame(data = {'id':['w', 'x', 'y', 'z'], 'value':[1,2,3,4], 'x':range(4), 'y':range(4)})
#create another dataset, same as the example but with the values flipped
df_qc = df.copy()
df_qc['value'] = df_qc['value'].to_list()[::-1]
#create timeseries for each ID
df_w = pd.DataFrame(data = {'id':['w']*5, 'hour':range(5), 'value':np.random.random(5)})
df_x = pd.DataFrame(data = {'id':['x']*5, 'hour':range(5), 'value':np.random.random(5)})
df_y = pd.DataFrame(data = {'id':['y']*5, 'hour':range(5), 'value':np.random.random(5)})
df_z = pd.DataFrame(data = {'id':['z']*5, 'hour':range(5), 'value':np.random.random(5)})
df_ts = pd.concat([df_w, df_x, df_y, df_z])
df_ts = df_ts.set_index(['id', 'hour'])
#create another set of timeseries, same as the first but with values flipped
df_ts_qc = df_ts.copy()
for id in df_ts_qc.index.unique('id'):
df_ts_qc.loc[id, 'value'] = df_ts_qc.loc[id, 'value'].to_list()[::-1]
##########################################################
def plot_points(df, df_ts):
points = hv.Points(data=df, kdims=['x', 'y'], vdims = ['id', 'value'])
stream = hv.streams.Selection1D(source=points).rename(index="index")
empty_curve = hv.Curve(df_ts.loc['w']).opts(visible = False)
def tap_station_curve(index):
if not index:
curve = empty_curve
elif index:
id = df.iloc[index[0]]['id']
curve = hv.Curve(df_ts.loc[id], label = str(id))
return curve
ts_curve = hv.DynamicMap(tap_station_curve, kdims=[], streams=[stream])
point_options = hv.opts.Points(size = 10, color = 'value', tools = ['tap'])
panel = pn.Row((points).opts(point_options), ts_curve)
return panel
radio_button = pn.widgets.RadioButtonGroup(options=['df', 'df_qc'])
@pn.depends(radio_button.param.value)
def update_plot(option):
if option == 'df':
plot = plot_points(df, df_ts)
else:
plot = plot_points(df_qc, df_ts_qc)
return plot
pn.Column(radio_button, update_plot)
It works fine, but there is one thing I'd like to change. Right now, when I switch between df
and df_qc
with the Radio button, the zoom level/axis limits reset. If the user has zoomed in on the plot before switching, I want that zoom level/axis limits to stay constant when switching to the other Points plot.
I assume there is some way to do this with storing the current axis limits, and then setting the axis limits to the old one when switching plots...but I can't quite figure it out.
Thanks!