Interactivity#

Jupyter Notebooks are excellent ways of communicating code and results. One of the nice features that makes them stand out in this regard is how easy it is to embed interactive “widgets” into the notebook.

This is easiest seen by example.

from ipywidgets import interact,interactive
import numpy as np

def f(x):
    print(f"x\u00b2 = {x**2}")
    return 

interact(f, x=(0.0, 10.0));
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Input In [1], in <cell line: 2>()
      1 from ipywidgets import interact,interactive
----> 2 import numpy as np
      4 def f(x):
      5     print(f"x\u00b2 = {x**2}")

ModuleNotFoundError: No module named 'numpy'

The idea is to provide a function which produces an output for each value of the slider. Here’s a more interesting example, where we plot a phase-plane for different values of a parameter \(k\). This ODE arises from a population model for spruce budworm, outbreaks of which have caused major deforestation in North America.

%matplotlib inline
# interactive plots work better "inline" rather than as "notebook" figures

import matplotlib.pyplot as plt
from ipywidgets import fixed


def vec_field(X, Y, r, k, c, a):
    U = np.ones((len(X), len(Y))) # the flow of time
    V = r*(1 - Y/k) * Y - c * Y**2/(a + Y**2) # the population change
    return U, V
    
x = np.linspace(0, 10, 100)
y = np.linspace(0, 10, 100) 
X, Y = np.meshgrid(x, y)

# interact will start with the 
def phase_plane(r = 0.3, k = 10, c = 1, a = 0.02):
    fig, ax = plt.subplots()
    U, V = vec_field(X, Y, r, k, c, a)
    ax.streamplot(X, Y, U, V)
    plt.title(f'Spruce budworm population with r={r}, k={k}')
    plt.xlabel('time')
    plt.ylabel('population')
    plt.show()

# Investigate "continuous_update" in the documentation linked below
# to avoid the plots lagging as the slider is dragged!
interactive(phase_plane,
            r = (0.2, 1.0),
            k = (8.0, 12.0),
            c = fixed(1),     # used "fixed" so there are no sliders for c or a
            a = fixed(0.02))

We have only shown a small number of the interactivity features in Jupyter Notebooks. More details on the interact function can be found here. Note that ipywidgets only work in Jupyter Notebooks, and not in other Python environments. More complex interactivity is possible using the other functions from the ipywidgets module, which we leave you to investigate for yourself if interested.

Similar interactive plots can be produced outside Jupyter Notebooks; the easiest way is through matplotlib widgets.