Widgets and interactive outputs

Widgets and interactive outputs#

Jupyter Notebooks have support for many kinds of interactive outputs. These should all be supported in MyST-NB by passing the output HTML through automatically. This page has a few common examples.[1]

First off, we’ll download a little bit of data and show its structure:

import plotly.express as px
data = px.data.iris()
data.head()
sepal_length sepal_width petal_length petal_width species species_id
0 5.1 3.5 1.4 0.2 setosa 1
1 4.9 3.0 1.4 0.2 setosa 1
2 4.7 3.2 1.3 0.2 setosa 1
3 4.6 3.1 1.5 0.2 setosa 1
4 5.0 3.6 1.4 0.2 setosa 1

Plotting libraries#

Altair#

Interactive outputs will work under the assumption that the outputs they produce have self-contained HTML that works without requiring any external dependencies to load. See the Altair installation instructions to get set up with Altair. Below is some example output.

import altair as alt
alt.Chart(data=data).mark_point().encode(
    x="sepal_width",
    y="sepal_length",
    color="species",
    size='sepal_length'
)

Plotly#

Plotly is another interactive plotting library that provides a high-level API for visualization. See the Plotly JupyterLab documentation to get started with Plotly in the notebook.

Below is some example output.

import plotly.io as pio
import plotly.express as px
import plotly.offline as py

df = px.data.iris()
fig = px.scatter(df, x="sepal_width", y="sepal_length", color="species", size="sepal_length")
fig

Important

You may need to supply the require.js for plotly to display; in your conf.py:

html_js_files = ["https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"]

Bokeh#

Bokeh provides several options for interactive visualizations, and is part of the PyViz ecosystem. See the Bokeh with Jupyter documentation to get started.

Below is some example output.

from bokeh.plotting import figure, show, output_notebook
output_notebook()
Loading BokehJS ...
from bokeh.plotting import figure, show, output_notebook
output_notebook()

p = figure()
p.circle(data["sepal_width"], data["sepal_length"], fill_color=data["species"], size=data["sepal_length"])
show(p)
Loading BokehJS ...
BokehDeprecationWarning: 'circle() method with size value' was deprecated in Bokeh 3.4.0 and will be removed, use 'scatter(size=...) instead' instead.

ipywidgets#

Note

IPyWidgets uses a special JS package @jupyter-widgets/html-manager for rendering Jupyter widgets outside notebooks. myst-nb loads a specific version of this package, which may be incompatible with your installation of IPyWidgets. If this is the case, you might need to specify the appropriate nb_ipywidgets_js config value, e.g. for 0.20.0

sphinx:
  recursive_update: true
  config:
    nb_ipywidgets_js:
        # Load IPywidgets bundle for embedding.
        "https://cdn.jsdelivr.net/npm/@jupyter-widgets/html-manager@0.20.0/dist/embed-amd.js":
            "data-jupyter-widgets-cdn": "https://cdn.jsdelivr.net/npm/"
            "crossorigin": "anonymous"

To determine which version of @jupyter-widgets/html-manager is required, find the html-manager JS package in the ipywidgets repo, and identify its version.

You may also run code for Jupyter Widgets in your document, and the interactive HTML outputs will embed themselves in your side. See the ipywidgets documentation for how to get set up in your own environment.

Widgets often need a kernel

Note that ipywidgets tend to behave differently from other interactive viz libraries. They interact both with Javascript, and with Python. Some functionality in ipywidgets may not work in rendered pages (because no Python kernel is running). You may be able to get around this with tools for remote kernels, like thebelab.

Here are some simple widget elements rendered below.

import ipywidgets as widgets
widgets.IntSlider(
    value=7,
    min=0,
    max=10,
    step=1,
    description='Test:',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='d'
)
tab_contents = ['P0', 'P1', 'P2', 'P3', 'P4']
children = [widgets.Text(description=name) for name in tab_contents]
tab = widgets.Tab()
tab.children = children
for ii in range(len(children)):
    tab.set_title(ii, f"tab_{ii}")
tab

You can find a list of possible Jupyter Widgets in the jupyter-widgets documentation.