Hello HoloVizzers!
I am making an application which plots large datasets (datashader enabled) of lat/lon points, and each lat/lon point has many different vdims. I want to allow the user to switch between the vdim that’s actively being colormapped using a panel widget. The user might also want to hide the data and unhide it.
I’ve built a little toy to that can do both of these things separately:
import panel as pn
import holoviews as hv
import datashader
import holoviews.operation.datashader
import numpy as np
hv.extension('bokeh')
pn.extension()
def plot_my_points():
x = np.linspace(-4, 4, 100)
y = x**2
a = np.arange(0, len(x))
d = np.flip(np.arange(0, len(x)))
r = np.random.rand(*x.shape)
points = hv.Points((x, y, a, d, r), kdims=['x', 'y'], vdims=['ascending', 'descending', 'random'])
return points
def change_color_callback(pts_shaded, color_var):
pts_shaded.callback.operation_kwargs.update({'aggregator' : datashader.reductions.max(color_var)})
pts_shaded.callback.operation_kwargs.update({'cmap' : 'viridis'})
drop_down = pn.widgets.Select(name='Color By', options=['ascending', 'descending', 'random'], value='ascending')
datashade_switch = pn.widgets.Switch(value=True)
pts = plot_my_points()
pts_shaded = hv.operation.datashader.datashade(pts, aggregator=datashader.max('ascending'), cmap='viridis', dynamic=True)
pn.bind(pts_shaded.opts, visible=datashade_switch, watch=True)
pn.bind(change_color_callback, pts_shaded=pts_shaded, color_var=drop_down, watch=True)
col = pn.Column(pts_shaded, drop_down, datashade_switch)
pn.serve(col)
I can run this and the colormapping changes and the hide switch both work, however, they require the user to slightly move the axes limits before changes take effect. Additionally, upon setting .opts(visibility=False)
, the “aggregator” key disappears from the .callback.operation_kwargs
of my datashaded plot object, and is replaced by a kwargs: {}
. when this is set back to .opts(visibility=True)
, future changes to the aggregator keyword argument are ignored by HoloViews.
So I have two questions about this, which may or may not be solved by the same answer:
- Is there a way to get datashader to re-render a plot programmatically, as if the user had bumped the axes limits, but without actually requiring user interaction?
2a. I want to change the aggregator on a datashaded plot after it’s already been served. Is there a better way of doing this other than setting theaggregator
key of thepts_shaded.callback.operation_kwargs
dictionary?
2b. If the answer to 2a is “yes that’s the way to do it”, then is there a workaround for that functionality breaking upon setting the plot invisible and then visible again?