Hello,
In my application I have tabs which are dynamically populated. The tabs must be dynamic, because of performance issues. I also need a way to save tabs with all content. To achieve this I need to clone them, as philippjfr suggested in another topic (thanks!).
This cloning however leads to another problem, which can be illustrated with the following example:
import panel as pn
import holoviews as hv
import numpy as np
from bokeh.models import NumeralTickFormatter
hv.extension("bokeh")
def make_img(**opts):
ls = np.linspace(0, 10, 200)
xx, yy = np.meshgrid(ls, ls)
bounds=(-1,-1,1,1) # Coordinate system: (left, bottom, right, top)
return hv.Image(np.sin(xx)*np.cos(yy), bounds=bounds).opts(**opts)
img1 = make_img(xformatter=NumeralTickFormatter())
img2 = make_img(cmap="jet")
tabs = pn.Tabs(img1, img2, dynamic=True)
def save_tabs(event):
tabs.clone(dynamic=False).save("tmp.html", embed=True, resources="INLINE")
save_button = pn.widgets.Button(name="Save tabs")
save_button.on_click(save_tabs)
pn.Row(tabs, save_button)
On the first plot I need a custom tick formatter. When I switch to the second tab, and then click save button, the file gets saved correctly. However, when I try to come back to the first tab, I get the following error:
Traceback (most recent call last):
File "/opt/conda/lib/python3.7/site-packages/pyviz_comms/__init__.py", line 325, in _handle_msg
self._on_msg(msg)
File "/opt/conda/lib/python3.7/site-packages/panel/viewable.py", line 259, in _on_msg
doc.unhold()
File "/opt/conda/lib/python3.7/site-packages/bokeh/document/document.py", line 668, in unhold
self._trigger_on_change(event)
File "/opt/conda/lib/python3.7/site-packages/bokeh/document/document.py", line 1151, in _trigger_on_change
self._with_self_as_curdoc(event.callback_invoker)
File "/opt/conda/lib/python3.7/site-packages/bokeh/document/document.py", line 1169, in _with_self_as_curdoc
return f()
File "/opt/conda/lib/python3.7/site-packages/bokeh/util/callback_manager.py", line 155, in invoke
callback(attr, old, new)
File "/opt/conda/lib/python3.7/site-packages/panel/layout/tabs.py", line 92, in _comm_change
super(Tabs, self)._comm_change(doc, ref, comm, attr, old, new)
File "/opt/conda/lib/python3.7/site-packages/panel/reactive.py", line 216, in _comm_change
self._process_events({attr: new})
File "/opt/conda/lib/python3.7/site-packages/panel/reactive.py", line 187, in _process_events
self.param.set_param(**self._process_property_change(events))
File "/opt/conda/lib/python3.7/site-packages/param/parameterized.py", line 1472, in set_param
self_._batch_call_watchers()
File "/opt/conda/lib/python3.7/site-packages/param/parameterized.py", line 1611, in _batch_call_watchers
self_._execute_watcher(watcher, events)
File "/opt/conda/lib/python3.7/site-packages/param/parameterized.py", line 1573, in _execute_watcher
watcher.fn(*args, **kwargs)
File "/opt/conda/lib/python3.7/site-packages/panel/layout/tabs.py", line 107, in _update_active
self.param.trigger('objects')
File "/opt/conda/lib/python3.7/site-packages/param/parameterized.py", line 1541, in trigger
self_.set_param(**dict(params, **triggers))
File "/opt/conda/lib/python3.7/site-packages/param/parameterized.py", line 1472, in set_param
self_._batch_call_watchers()
File "/opt/conda/lib/python3.7/site-packages/param/parameterized.py", line 1611, in _batch_call_watchers
self_._execute_watcher(watcher, events)
File "/opt/conda/lib/python3.7/site-packages/param/parameterized.py", line 1573, in _execute_watcher
watcher.fn(*args, **kwargs)
File "/opt/conda/lib/python3.7/site-packages/panel/reactive.py", line 175, in _param_change
self._update_model(events, msg, root, model, doc, comm)
File "/opt/conda/lib/python3.7/site-packages/panel/layout/tabs.py", line 120, in _update_model
super(Tabs, self)._update_model(events, msg, root, model, doc, comm)
File "/opt/conda/lib/python3.7/site-packages/panel/layout/base.py", line 65, in _update_model
super(Panel, self)._update_model(events, msg, root, model, doc, comm)
File "/opt/conda/lib/python3.7/site-packages/panel/reactive.py", line 137, in _update_model
model.update(**msg)
File "/opt/conda/lib/python3.7/site-packages/bokeh/core/has_props.py", line 374, in update
setattr(self, k, v)
File "/opt/conda/lib/python3.7/site-packages/bokeh/core/has_props.py", line 278, in __setattr__
super().__setattr__(name, value)
File "/opt/conda/lib/python3.7/site-packages/bokeh/core/property/descriptors.py", line 539, in __set__
self._internal_set(obj, value, setter=setter)
File "/opt/conda/lib/python3.7/site-packages/bokeh/core/property/descriptors.py", line 763, in _internal_set
self._real_set(obj, old, value, hint=hint, setter=setter)
File "/opt/conda/lib/python3.7/site-packages/bokeh/core/property/descriptors.py", line 832, in _real_set
self._trigger(obj, old, value, hint=hint, setter=setter)
File "/opt/conda/lib/python3.7/site-packages/bokeh/core/property/descriptors.py", line 909, in _trigger
obj.trigger(self.name, old, value, hint, setter)
File "/opt/conda/lib/python3.7/site-packages/bokeh/model.py", line 662, in trigger
self._document._invalidate_all_models()
File "/opt/conda/lib/python3.7/site-packages/bokeh/document/document.py", line 1031, in _invalidate_all_models
self._recompute_all_models()
File "/opt/conda/lib/python3.7/site-packages/bokeh/document/document.py", line 1098, in _recompute_all_models
a._attach_document(self)
File "/opt/conda/lib/python3.7/site-packages/bokeh/model.py", line 674, in _attach_document
raise RuntimeError("Models must be owned by only a single document, %r is already in a doc" % (self))
RuntimeError: Models must be owned by only a single document, NumeralTickFormatter(id='3112', ...) is already in a doc
Could you help me with solving this?
My env: Python 3.7.6, panel==0.10.3, holoviews==1.14.0, bokeh==2.2.3
Thanks in advance,
Rafał