How to get interactive bokeh in Jupyter notebook

前端 未结 1 973
暗喜
暗喜 2020-12-28 10:35

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 exam

相关标签:
1条回答
  • 2020-12-28 11:15

    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 Application
    from bokeh.application.handlers import FunctionHandler
    .
    .
    <your code here>
    .
    .
    #add server-related code inside this modify_doc function
    def 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 -- BOKEH
    import bokeh.plotting.figure as bk_figure
    from bokeh.io import curdoc, show
    from bokeh.layouts import row, widgetbox
    from bokeh.models import ColumnDataSource
    from bokeh.models.widgets import Slider, TextInput
    from bokeh.io import output_notebook # enables plot interface in J notebook
    import numpy as np
    # init bokeh
    
    from bokeh.application import Application
    from bokeh.application.handlers import FunctionHandler
    
    
    output_notebook()
    ############ END BOILERPLATE ############
    
    # Set up data
    N = 200
    x = np.linspace(0, 4*np.pi, N)
    y = np.sin(x)
    source = ColumnDataSource(data=dict(x=x, y=y))
    
    # Set up plot
    plot = 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 widgets
    text = 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 callbacks
    def update_title(attrname, old, new):
        plot.title.text = text.value
    
    
    
    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 document
    inputs = 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)
    
    0 讨论(0)
提交回复
热议问题