Jupyter#

Working in notebooks#

Jupyter notebooks are computable documents often used for exploratory work, data analysis, teaching, and demonstration. A notebook is a series of input cells that can execute individually to immediately display their output. In addition to Classic notebooks, there are also notebooks for the newer JupyterLab project. Bokeh can embed both standalone and Bokeh server content with either.

Standalone output#

Standalone Bokeh content doesn’t require a Bokeh server and can be embedded directly in classic Jupyter notebooks as well as in JupyterLab.

Classic notebooks#

To display Bokeh plots inline in a classic Jupyter notebook, use the output_notebook() function from bokeh.io instead of (or in addition to) the output_file() function. No other modifications are required. When you call show(), the plot will display inline in the next notebook output cell. See a screenshot of Jupyter below:

Screenshot of a Jupyter notebook displaying a Bokeh scatterplot inline after calling show().

To have a single notebook output cell display multiple plots, call show() multiple times in the input cell. The plots will display in order.

Screenshot of a Jupyter notebook displaying multiple Bokeh scatterplots inline after calling show() multiple times.

JupyterLab#

To use JupyterLab with Bokeh, you should at least use version 3.0 of JupyterLab. Enabling Bokeh visualizations in JupyterLab also requires the jupyter_bokeh extension to be installed.

After installing JupyterLab, you can use either pip or conda to install jupyter_bokeh:

Installing with conda

Make sure you have either Anaconda or Miniconda installed. Use this command to install jupyter_bokeh:

conda install jupyter_bokeh

Installing with pip

Use this command to install jupyter_bokeh:

pip install jupyter_bokeh

For instructions on installing jupyter_bokeh with versions of JupyterLab older than 3.0, see the README in the GitHub repository of jupyter_bokeh.

Once you have jupyter_bokeh installed, you can use Bokeh just like you would with a classic notebook.

Screenshot of Jupyterlab with a Bokeh ridgeplot displayed inline.

Bokeh server applications#

You can also embed full Bokeh server applications connecting plot events and Bokeh’s built-in widgets directly to Python callback code. See Bokeh server for general information about Bokeh server applications. For a complete example of a Bokeh application embedded in a Jupyter notebook, refer to the following notebook:

JupyterHub#

When running notebooks from your own JupyterHub instance, some additional steps are necessary to embed Bokeh server applications and to enable network connectivity between the client browser and the Bokeh server running in a JupyterLab cell. This is because your browser needs to connect to the port the Bokeh server is listening on. However, JupyterHub is acting as a reverse proxy between your browser and your JupyterLab container. Follow all the JupyterLab instructions above, then continue with the following steps:

  1. Install the jupyter-server-proxy package and enable the server extension as follows:

    pip install jupyter-server-proxy && jupyter serverextension enable --py jupyter-server-proxy
    

    If you intend to work with JupyterLab you need to install the corresponding extension, either from the GUI or with the following command:

    jupyter labextension install @jupyterlab/server-proxy
    
  2. Define a function to help create the URL for the browser to connect to the Bokeh server.

    See below for a reference implementation. You’ll have to either modify this code or assign the URL of your JupyterHub installation to the environment variable EXTERNAL_URL. JupyterHub defaults to JUPYTERHUB_SERVICE_PREFIX in this case.

    def remote_jupyter_proxy_url(port):
        """
        Callable to configure Bokeh's show method when a proxy must be
        configured.
    
        If port is None we're asking about the URL
        for the origin header.
        """
        base_url = os.environ['EXTERNAL_URL']
        host = urllib.parse.urlparse(base_url).netloc
    
        # If port is None we're asking for the URL origin
        # so return the public hostname.
        if port is None:
            return host
    
        service_url_path = os.environ['JUPYTERHUB_SERVICE_PREFIX']
        proxy_url_path = 'proxy/%d' % port
    
        user_url = urllib.parse.urljoin(base_url, service_url_path)
        full_url = urllib.parse.urljoin(user_url, proxy_url_path)
        return full_url
    
  3. Pass the function you defined in step 2 to the show() function as the notebook_url keyword argument. Bokeh then calls this function when it sets up the server and creates the URL to load a graph:

    show(obj, notebook_url=remote_jupyter_proxy_url)
    

You may need to restart your server after this, and then Bokeh content should load and execute Python callbacks defined in your Jupyter environment.

Trusting notebooks#

Depending on the version of the notebook you are using, you may have to trust the notebook for Bokeh plots to re-render when the notebook is closed and re- opened. The Trust Notebook option is typically located under the File menu:

Screenshot of the Jupyter File menu expanded to show the Trust Notebook option.

Notebook slides#

You can use a notebook with Reveal.js to generate slideshows from cells. You can also include standalone (i.e. non-server) Bokeh plots in such sideshows. However, you will need to take a few extra steps to display the output correctly. Particularly, make sure that the cell containing the output_notebook is not be skipped.

Rendered cell output of the output_notebook call ensures that the BokehJS library loads. Otherwise, Bokeh plots will not work. If this cell’s type is set to “skip”, BokehJS will not load, and Bokeh plots will not display. If you want to hide this cell, assign it the “notes” slide type.

Notebook handles#

You can update a displayed plot without reloading it. To do so, pass the notebook_handle=True argument to show() for it to return a handle object. You can use this handle object with the push_notebook() function to update the plot with any recent changes to plots properties, data source values, etc.

This notebook handle functionality is only supported in classic Jupyter notebooks and is not implemented in JupyterLab or Zeppelin yet.

The following screenshots illustrate basic usage of notebook handles:

  1. Import standard functions and push_notebook():

Screenshot of Jupyter showing Bokeh push_notebook being imported .
  1. Create some plots and pass notebook_handle=True to show():

Screenshot of Jupyter with Bokeh content created with notebook comms enabled.
  1. Check that the handle is associated with the output cell for In[2] just displayed:

Screenshot of Jupyter showing the representation of a notebook comms handle in an output cell.
  1. Update some properties of the plot, then call push_notebook() with the handle:

Screenshot of Jupyter input cell modifying Bokeh properties and calling push_notebook.
  1. Note that the output cell for In[2] has changed (without being re-executed):

Screenshot of Jupyter showing the previous plot updated in place, with glyph color white now.

See the following notebooks for more detailed examples of notebook handle use:

Jupyter interactors#

You can use notebook widgets, known as interactors, to update Bokeh plots. The key to doing this is the push_notebook() function. The update callback for the interactors calls this function to update the plot from widget values. See a screenshot of the examples/output/jupyter/push_notebook/Jupyter Interactors.ipynb example notebook below:

Screenshot of Jupyter showing a Bokeh plot together with ipywidget sliders.

More example notebooks#

You can find many more examples of notebook use in the bokeh-notebook repository:

  1. Clone the repository locally:

    git clone https://github.com/bokeh/bokeh-notebooks.git
    
  2. Launch the Jupyter notebooks in your web browser.

Alternatively, Binder hosts live notebooks that you can run online.

The main Bokeh repository also includes some notebook comms examples:

IPyWidgets outside the notebook#

Now that you know how to use Bokeh in the JupyterLab and classical notebook environments, you might want to take advantage of the vibrant Jupyter ecosystem outside of these environments. You can do so with the ipywidgets_bokeh extension for Bokeh:

$ conda install -c bokeh ipywidgets_bokeh

or

$ pip install ipywidgets_bokeh

This extension lets you use IPyWidgets in Bokeh. Simply wrap a widget in an IPyWidget model and add the wrapper to a document or include it in a layout. You don’t have to install or enable any other extensions.

Example#

Follow these steps to build an application with a single Jupyter slider that logs its adjustments to the console:

  1. Start by constructing a widget and configuring an observer:

    from ipywidgets import FloatSlider
    angle = FloatSlider(min=0, max=360, value=0, step=1, description="Angle")
    
    def on_change(change):
        print(f"angle={change['new']} deg")
    angle.observe(on_change, names="value")
    
  2. To integrate the widget with Bokeh, wrap it in IPyWidget:

    from ipywidgets_bokeh import IPyWidget
    ipywidget = IPyWidget(widget=angle)
    
  3. Add the wrapper to a Bokeh document:

    from bokeh.plotting import curdoc
    doc = curdoc()
    doc.add_root(ipywidget)
    

To run the app, enter bokeh serve ipy_slider.py, where ipy_slider.py is the name of the application (see Bokeh server for details). This application is available at http://localhost:5006/ipy_slider.

You can build on the above to create more complex layouts and include advanced widgets, such as ipyleaflet and ipyvolume. For more examples, see examples/howto/ipywidgets in the Bokeh repository.