I have spent some time on making a served dashboard based on bokeh app with callback triggering updates on the figures.
Now comes a point where I feel some limitations of Bokeh, namely for example plotting histograms are not easy, matrices of scatter plots need to be coded by hand…
So I have naturally bent towards the direction of Holoview, which offers this type of more elaborate figures and based on Bokeh. But I am a bit puzzled on how to incorporate the whole holoview machinery in a Bokeh app. Especially the way how I could integrate callbacks to update figures with it…
I would appreciate if somebody could tell me what is the best strategy to include HV figures that updates with click event callbacks — besides telling me to refactor the whole dashboard using Holoviews
the solution 2. is not compatible with callback and updates, am I correct?
HoloViews is very deliberately written to avoid writing callbacks with side-effects. In theory you could modify the resulting bokeh model yourself using callbacks once you’ve set them up but you lose much of the power of HoloViews that way.
I guess I’d have to know more about what you’re trying to achieve to make concrete recommendations.
Would you or anyone else be kind enough to explain this interaction between Panel, HoloViews, and Bokeh?
Sure. So for a very long time HoloViews was an entirely independent project which could render to Bokeh but didn’t treat Bokeh in any special way. We had some options for deploying on Bokeh server but those were somewhat limited. In the HoloViews 1.13 release however we switched HoloViews widgets and rendering entirely over to Panel in the background so now all the widgets you see and all the rendering is done by Panel.
This also simplified the story behind interacting with Jupyter and Bokeh server, all the setting up of bi-directional communication channels could now simply be handled by Panel and HoloViews wouldn’t worry about it. So let’s look at the three scenarios you called out in your blog post:
In the Jupyter Notebook comms can be globally accessed on the Jupyter.notebook.kernel object making it possible to easily set up bi-directional communication channels. In JupyterLab on the other hand it is not as simple and we proxy the CommManager object using the @pyviz/jupyterlab_pyviz extension. Otherwise things work basically the same, both HoloViews and Panel set up communication channels via this mechanism.
On the bokeh server communication is handled by the Bokeh Websocket. The easiest way to set this up from HoloViews is indeed what you describe, i.e. using pn.panel(hv_obj).servable(). This sets things up so that panel serve ... or bokeh serve ... will work. Alternatively you can also create a simple script which launches a server using the pn.serve function, so you simply run python script_with_pn_serve.py.
Voila currently does not follow the classic notebook API, i.e. making Jupyter.notebook.kernel available, but also does not support JupyterLab extension which means the standard communication channels will not work out of the box. Therefore I initially prototyped ipybokeh as part of a Jupyter dashboarding workshop last year, which eventually migrated to jupyter_bokeh. Using this it is possible to wrap a bokeh (or Panel) object in an ipywidget which is supported in Voila. You can activate this in Panel by doing:
pn.config.comms = 'ipywidget'
or explicitly calling pn.ipywidget(hv_or_panel_obj). However currently throttling is not yet enabled so you will end up with a lot of events being generated. Starting in Panel 0.10.0 throttling will be enabled and you should be able to use Panel/Bokeh objects in Voila just like any other ipywidgets based object.