Normally, I am able to replace parts of a panel via pop
and insert
, which updates any existing panels automatically. However, if these are triggered from a bokeh selected.on_change
callback,
existing panels do not update.
For example, running the following in JupyterLab works
from bokeh.plotting import figure
from bokeh.sampledata.iris import flowers
from bokeh.models import ColumnDataSource
import panel as pn
pn.extension()
def create_figure():
src = ColumnDataSource(flowers)
p = figure(height=200, width=200, tools='box_select')
p.circle("petal_length", "petal_width", source=src)
return p
pnl = pn.panel(pn.Row(create_figure, create_figure))
pnl
The displayed panel will update as expected when I run the following in the next cell:
pnl.pop(0)
pnl.insert(0, figure)
However, if I do the same thing via a callback when the selection of the column data source changes, the panel does not update as I select data points in the plot:
def replace_plot(attr, old, new):
pnl.objects.pop(0)
pnl.objects.insert(0, figure)
def create_figure():
src = ColumnDataSource(flowers)
p = figure(height=200, width=200, tools='box_select')
p.circle("petal_length", "petal_width", source=src)
src.selected.on_change('indices', replace_plot)
return p
pnl = pn.panel(pn.Row(create_figure, create_figure))
pnl
What does work is to replace the entire pnl.objects
with a new list:
def replace_plot(attr, old, new):
pnl.objects = [figure]
Strangely, this only work when I call pnl.show()
to display the panel in a new browser tab, in the notebook I need to display the panel again in a new cell to see the update. I tried replacing individual items in the objects
list via indexing, but this worked the same as pop
and insert
, the panel did not update automatically.
Is there a way to replace parts of a panel vi a selected.on_change
callback and have it refresh automatically (preferably inside the notebook but via show
also works)?
Versions:
-----
bokeh 2.0.1
pandas 1.0.3
panel 0.9.5
-----
IPython 6.5.0
jupyter_client 5.2.3
jupyter_core 4.6.3
jupyterlab 2.1.0
notebook 5.6.0
-----
Python 3.7.6 | packaged by conda-forge | (default, Mar 23 2020, 23:03:20) [GCC 7.3.0]
Linux-5.6.13-arch1-1-x86_64-with-arch
4 logical CPU cores
-----
Session information updated at 2020-05-21 18:38
Turns out this is a bug in panel, now being tracked at https://github.com/holoviz/panel/issues/1368. For the time being, the following snippet works around the problem:
from panel.io.notebook import push
def replace_plot(attr, old, new):
for ref in pnl._models:
_, _, doc, comm = pn.state._views[ref]
doc.hold()
pnl[0] = 1
push(doc, comm)
for ref in pnl._models:
_, _, doc, comm = pn.state._views[ref]
doc.unhold()