代码基于: https://github.com/bokeh/bokeh/blob/master/examples/app/sliders.py https://docs.bokeh.org/en/latest /docs/user_guide/notebook.html ############ START BOILERPLATE ################ Interactivity -- BOKEHimport bokeh.plotting.figure as bk_figurefrom bokeh.io import curdoc, showfrom bokeh.layouts import row, widgetboxfrom bokeh.models import ColumnDataSourcefrom bokeh.models.widgets import Slider, TextInputfrom bokeh.io import output_notebook # enables plot interface in J notebook# init bokehoutput_notebook()############ END BOILERPLATE ############# Set up dataN = 200x = np.linspace(0, 4*np.pi, N)y = np.sin(x)source = ColumnDataSource(data=dict(x=x, y=y))# Set up plotplot = bk_figure(plot_height=400, plot_width=400, title="my sine wave", tools="crosshair,pan,reset,save,wheel_zoom", x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)# Set up widgetstext = TextInput(title="title", value='my sine wave')offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0, step=0.1)phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1)# Set up callbacksdef update_title(attrname, old, new): plot.title.text = text.valuetext.on_change('value', update_title)def update_data(attrname, old, new): # Get the current slider values a = amplitude.value b = offset.value w = phase.value k = freq.value # Generate the new curve x = np.linspace(0, 4*np.pi, N) y = a*np.sin(k*x + w) + b source.data = dict(x=x, y=y) ### I thought I might need a show() here, but it doesn't make a difference if I add one # show(layout)for w in [offset, amplitude, phase, freq]: w.on_change('value', update_data)# Set up layouts and add to documentinputs = widgetbox(text, offset, amplitude, phase, freq)layout = row(plot, widgetbox(text, offset, amplitude, phase, freq))curdoc().add_root(row(inputs, layout, width=800))curdoc().title = "Sliders"show(layout)我生成如下图,但是当滑块移动时图形也不会更新(标题文本也不会更新)非常感谢您的任何建议. PS.我试图使这段代码尽可能地接近我可以在服务器上使用.py文件实现的代码,从而避免使用像push_notebook这样的jupyter专用变通办法.解决方案(作为用户)我同意docs在此方面可能会更好.我必须进行大量搜索才能找到该过程,但是当您找到它时就不那么困难了!我修改了您的代码,您可以在Jupyter笔记本中运行它.诀窍是:from bokeh.application import Applicationfrom bokeh.application.handlers import FunctionHandler..<your code here>..#add server-related code inside this modify_doc functiondef modify_doc(doc): #use doc as you use curdoc() in bokeh server doc.add_root(<your_layout>) doc.on_change(...) doc.add_periodic_callback(...)handler = FunctionHandler(modify_doc)app = Application(handler)show(app)和代码的修改版本:############ START BOILERPLATE ################ Interactivity -- BOKEHimport bokeh.plotting.figure as bk_figurefrom bokeh.io import curdoc, showfrom bokeh.layouts import row, widgetboxfrom bokeh.models import ColumnDataSourcefrom bokeh.models.widgets import Slider, TextInputfrom bokeh.io import output_notebook # enables plot interface in J notebookimport numpy as np# init bokehfrom bokeh.application import Applicationfrom bokeh.application.handlers import FunctionHandleroutput_notebook()############ END BOILERPLATE ############# Set up dataN = 200x = np.linspace(0, 4*np.pi, N)y = np.sin(x)source = ColumnDataSource(data=dict(x=x, y=y))# Set up plotplot = bk_figure(plot_height=400, plot_width=400, title="my sine wave", tools="crosshair,pan,reset,save,wheel_zoom", x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)# Set up widgetstext = TextInput(title="title", value='my sine wave')offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0, step=0.1)phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1)# Set up callbacksdef update_title(attrname, old, new): plot.title.text = text.valuedef update_data(attrname, old, new): # Get the current slider values a = amplitude.value b = offset.value w = phase.value k = freq.value # Generate the new curve x = np.linspace(0, 4*np.pi, N) y = a*np.sin(k*x + w) + b source.data = dict(x=x, y=y) ### I thought I might need a show() here, but it doesn't make a difference if I add one # show(layout)for w in [offset, amplitude, phase, freq]: w.on_change('value', update_data)# Set up layouts and add to documentinputs = widgetbox(text, offset, amplitude, phase, freq)layout = row(plot, widgetbox(text, offset, amplitude, phase, freq))def modify_doc(doc): doc.add_root(row(layout, width=800)) doc.title = "Sliders" text.on_change('value', update_title)handler = FunctionHandler(modify_doc)app = Application(handler)show(app)I'm gearing up towards using bokeh for an interactive online implementation of some python models I've written.Step 1 is understanding some basic interactive examples, but I can't get the introductory examples running INTERACTIVELY in a Jupyter notebook. I'm hoping someone can correct my misunderstanding of what is a copy-paste of bokeh's own example code.I'm aware that the Bokeh documentation isn't perfect (I fixed an outdated reference to bokeh.plotting.show rather than io.show), but I think the basic structure I'm using should be close to correct.code is based off:https://github.com/bokeh/bokeh/blob/master/examples/app/sliders.pyhttps://docs.bokeh.org/en/latest/docs/user_guide/notebook.html############ START BOILERPLATE ################ Interactivity -- BOKEHimport bokeh.plotting.figure as bk_figurefrom bokeh.io import curdoc, showfrom bokeh.layouts import row, widgetboxfrom bokeh.models import ColumnDataSourcefrom bokeh.models.widgets import Slider, TextInputfrom bokeh.io import output_notebook # enables plot interface in J notebook# init bokehoutput_notebook()############ END BOILERPLATE ############# Set up dataN = 200x = np.linspace(0, 4*np.pi, N)y = np.sin(x)source = ColumnDataSource(data=dict(x=x, y=y))# Set up plotplot = bk_figure(plot_height=400, plot_width=400, title="my sine wave", tools="crosshair,pan,reset,save,wheel_zoom", x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)# Set up widgetstext = TextInput(title="title", value='my sine wave')offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0, step=0.1)phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1)# Set up callbacksdef update_title(attrname, old, new): plot.title.text = text.valuetext.on_change('value', update_title)def update_data(attrname, old, new): # Get the current slider values a = amplitude.value b = offset.value w = phase.value k = freq.value # Generate the new curve x = np.linspace(0, 4*np.pi, N) y = a*np.sin(k*x + w) + b source.data = dict(x=x, y=y) ### I thought I might need a show() here, but it doesn't make a difference if I add one # show(layout)for w in [offset, amplitude, phase, freq]: w.on_change('value', update_data)# Set up layouts and add to documentinputs = widgetbox(text, offset, amplitude, phase, freq)layout = row(plot, widgetbox(text, offset, amplitude, phase, freq))curdoc().add_root(row(inputs, layout, width=800))curdoc().title = "Sliders"show(layout)I generate a plot as below, but the figure doesn't update when the sliders are moved (nor when the title text is updated)Many thanks for any suggestions.PS. I'm trying to keep this code as close as possible to something I can implement with .py files on a server, thus avoiding jupyter-specific workarounds like push_notebook. 解决方案 I agree (as a user) that docs could be better on this. I had to search a lot to find the procedure, but when you find it it's not that hard! I modified your code, you can run this inside Jupyter notebook.The trick is:from bokeh.application import Applicationfrom bokeh.application.handlers import FunctionHandler..<your code here>..#add server-related code inside this modify_doc functiondef modify_doc(doc): #use doc as you use curdoc() in bokeh server doc.add_root(<your_layout>) doc.on_change(...) doc.add_periodic_callback(...)handler = FunctionHandler(modify_doc)app = Application(handler)show(app)and the modified version of your code:############ START BOILERPLATE ################ Interactivity -- BOKEHimport bokeh.plotting.figure as bk_figurefrom bokeh.io import curdoc, showfrom bokeh.layouts import row, widgetboxfrom bokeh.models import ColumnDataSourcefrom bokeh.models.widgets import Slider, TextInputfrom bokeh.io import output_notebook # enables plot interface in J notebookimport numpy as np# init bokehfrom bokeh.application import Applicationfrom bokeh.application.handlers import FunctionHandleroutput_notebook()############ END BOILERPLATE ############# Set up dataN = 200x = np.linspace(0, 4*np.pi, N)y = np.sin(x)source = ColumnDataSource(data=dict(x=x, y=y))# Set up plotplot = bk_figure(plot_height=400, plot_width=400, title="my sine wave", tools="crosshair,pan,reset,save,wheel_zoom", x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)# Set up widgetstext = TextInput(title="title", value='my sine wave')offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0, step=0.1)phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1, step=0.1)# Set up callbacksdef update_title(attrname, old, new): plot.title.text = text.valuedef update_data(attrname, old, new): # Get the current slider values a = amplitude.value b = offset.value w = phase.value k = freq.value # Generate the new curve x = np.linspace(0, 4*np.pi, N) y = a*np.sin(k*x + w) + b source.data = dict(x=x, y=y) ### I thought I might need a show() here, but it doesn't make a difference if I add one # show(layout)for w in [offset, amplitude, phase, freq]: w.on_change('value', update_data)# Set up layouts and add to documentinputs = widgetbox(text, offset, amplitude, phase, freq)layout = row(plot, widgetbox(text, offset, amplitude, phase, freq))def modify_doc(doc): doc.add_root(row(layout, width=800)) doc.title = "Sliders" text.on_change('value', update_title)handler = FunctionHandler(modify_doc)app = Application(handler)show(app) 这篇关于如何在Jupyter Notebook中获得交互式bokeh的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 09-05 07:08