Temporarily prevent Bokeh update/redraw, and re-enable it later (for Jupyter with ipywidgets)?

Ok, I looked into this a bit more; and there seemingly, two general options for this:

So, maybe I should have been more specific: not that I just want to use Jupyter notebooks, but I also want to use ipywidgets (will update the title soon)

Anyways, I finally wrote a proper runnable example, which will hopefully demonstrate the sluggishness I’m trying to demonstrate:

import bokeh.plotting as bplt
from jupyter_bokeh.widgets import BokehModel
import bokeh.io
import numpy as np
import pandas as pd
import requests
import random
from ipywidgets import widgets, Layout
from IPython.display import display

# for the ipython notebook
bplt.output_notebook()

CSSNAMESLINK="https://gist.githubusercontent.com/ek/913fe6905da054977ab9ebc00fc43470/raw/4294f90b9dee884a1146e40e7fc57ada62eb82a0/html-color-names-keywords-list.txt"
css_response = requests.get(CSSNAMESLINK)
cssnames = css_response.text.split()

# generate simulated data
numvals = 1000 # 10000
#numvals = 10
xcol = np.arange(0, numvals, 1)
df = pd.DataFrame(dtype=np.int64)
for iser in range(0, 3):
    for ix in xcol:
        irow = iser*len(xcol)+ix
        df.at[irow, 0] = int(iser)
        df.at[irow, 1] = int(ix)
        df.at[irow, 2] = int( ix*(iser+2)*0.3 )
df = df.rename(columns={0: "ser", 1: "xcol", 2: "ycol"})
df = df.astype(np.int64) # without this, getting floats

# prepare plot
datachans = df["ser"].unique()
mycolors = random.sample(cssnames, len(datachans))
print(mycolors)

myfig = bplt.figure(plot_height=300, tools="pan,wheel_zoom,box_zoom,hover,reset", sizing_mode="stretch_width")
traces_l = []
for ichan in datachans:
    # use .circle here instead of .line, as it meeds more drawing/is more sluggish
    line = myfig.circle([0,0], [0,0], line_width=2, line_color=mycolors[ichan])
    traces_l.append(line)
myfig.x_range.start = 0 ; myfig.x_range.end = numvals
myfig.y_range.start = 0 ; myfig.y_range.end = numvals

the_slider = widgets.IntSlider(min=0, max=len(datachans), description='Test:')

myfig_model = BokehModel(myfig)
#handle_myfig = bokeh.io.show(myfig, notebook_handle=True) # direct in VBox: TraitError: The 'children' trait of a VBox instance contains an Instance of a TypedTuple which expected a Widget, not the CommsHandle 
#myfig_model = BokehModel(handle_myfig) # AssertionError: isinstance(model, LayoutDOM) 

the_ui = widgets.VBox([the_slider, myfig_model])
#the_ui = widgets.VBox([the_slider, handle_myfig])

def update_plot(newval):
    for ichan in datachans:
        this_ch_data = df[df["ser"]==ichan]
        traces_l[ichan].data_source.data={ 'x': this_ch_data["xcol"].values, 'y': this_ch_data["ycol"].values+newval }

def on_slider_change(change):
    if change['type'] == 'change' and change['name'] == 'value': # prevent multiple hits upon single value change
        update_plot(change['new']*0.1*numvals)
        # "Next tick callbacks only work within the context of a Bokeh server session. This function will no effect when Bokeh outputs to standalone HTML or Jupyter notebook cells."
        #bplt.curdoc().add_next_tick_callback(update_plot)
the_slider.observe(on_slider_change)


display(the_ui)
on_slider_change({'type': 'change', 'name': 'value', 'new': 0 }) # initial call

I am also aware there is also ipywidgets's interact (as described in “Jupyter interactors”) - unfortunately, my UI is a bit more complex than what can be (readably) fit in a single interact call, which is why I feel it’s needed to code the Bokeh plot as a ipywidgets GUI element.