Open In App

Interactive Controls in Jupyter Notebooks

Last Updated : 18 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

This article explains the significance of interactive controls in Jupyter Notebooks and presents a few different methods of adding them to the notebooks for Python programming language. A list of basic controls/widgets and finally examples are provided to demonstrate all that is presented throughout this article. This article expects basic familiarity with Python and Jupyter Notebooks.

Interactive Controls for Jupyter Notebooks

We often need to explore figures and data in Jupyter notebooks by observing it for different values of parameters involved. The obvious solution is to change the value of parameters in the code and then run it and repeat this process for the different values we are targeting. In practice, this process becomes inconvenient and frustrating as the number of parameters and the possible values for each parameter that we want to explore grows. One solution for this problem is Jupiter interactive controls which can be added by using Jupyter widgets.

Jupyter widgets can be used in a variety of situations:

  • Data/Figure exploration through altering parameters.
  • While presenting data in a jupyter notebook during the presentation.
  • Creating small data dashboards within jupyter notebooks.

Installations and setup required

To work out the programs presented in this article, one needs to install Python, Jupyterlab, ipywidgets, matplotlib, and numpy on the pc along with a browser (Chrome, Edge, Firefox, Safari, etc.). Once the Python interpreter is installed, others can be installed with any Python package manager like pip or conda. Here are the commands for pip –

For Windows:

py -m pip install --upgrade "jupyterlab", "matplotlib", "numpy", "ipywidgets"

For Linux/Mac:

python3 -m pip install --upgrade "jupyterlab", "matplotlib", "numpy", "ipywidgets"

Once all these are installed, go to the project folder/the folder in which you want to keep the jupyter files and open the command window (terminal/console) there. Run the following command to launch the jupyter notebook in browser with this folder as the project folder –

For Windows

py -m jupyter lab

For Linux/Mac

python3 -m jupyter lab

Basic Interactive widgets in Jupyter Notebooks

Lots of widgets are available in ipywidgets for jupyter notebooks. The complete list can be obtained here on the official documentation. This section provides the syntax and usage of few basic widgets –

IntSlider

Creates an integer slider.

To use with interact decorator, put the default value of the parameter to an integer (like 1, 0, -1, 2, etc.).

To use with interact function, here is the code for the widget –

Python3




widgets.IntSlider(
    value=7,
    min=0,
    max=10,
    step=1,
    description='Test:',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,
    readout_format='d'
)


Output:

Screenshot-2023-12-18-143741

FloatSlider

Creates a float slider.

To use with interact decorator, put the default value of the parameter to an integer (like 1.0, 0.5, -1.2, 2.001, etc.).

To use with interact function, here is the code for the widget –

Python3




widgets.FloatSlider(
    value=7.5,
    min=0,
    max=10.0,
    step=0.1,
    description='Test:',
    disabled=False,
    continuous_update=False,
    orientation='horizontal',
    readout=True,


Output:

Screenshot-2023-12-18-143751

Text

An entry box for text.

To use with interact decorator, put the default value of the parameter to a string.

To use with interact function, here is the code for the widget –

Python3




widgets.Text(
    value='Hello World',
    placeholder='Type something',
    description='String:',
    disabled=False  
)


Output:

Screenshot-2023-12-18-143803

Dropdown

Creates a dropdown menu.

To use with interact decorator, put the default value of the parameter to a sequence (like list or tuple).

To use with the interact function, here is the code for the widget –

Python3




widgets.Dropdown(
    options=['1', '2', '3'],
    value='2',
    description='Number:',
    disabled=False,
)


Output:

Screenshot-2023-12-18-143903

DropBox

Checkbox

Creates a checkbox for boolean values (True/False).

To use with interact decorator, put the default value of the parameter to True or False.

To use with the interact function, here is the code for the widget –

Python3




widgets.Checkbox(
    value=False,
    description='Check me',
    disabled=False,
    indent=False
)


Output:

Screenshot-2023-12-18-143911

Checkbox

We use some of these widgets in the proceeding examples. To know more about these widgets and all the other jupyter widgets, visit the link to official documentation.

Apart from the widgets discussed here, backends for matplotlib, plotly and bokeh libraries are available to allow implementing their specific interactive plotting widgets. This is covered in the following article – How to Use JupyterLab Inline Interactive Plots

Methods for Interactive controls in Jupyter Notebooks

To add interactive controls, we need to follow the following steps –

  • Step 1: Wrap the code which you want to be interactive inside a function with parameters that you want to alter. Now use these parameter variables inside the code to set the properties or whatever needs to be done using the parameters.
  • Step 2: Use the interact or interact_manual functions from ipywidgets module to call this function.

The interact and interact_manual methods are same except for one difference that the output auto updates as we change the parameters through widgets in case of interact while in case of interact_manual a button is provided to update the output.

Hence use interact_manual when it is computationally expensive to produce the output (so you update only when you are ready to) otherwise use interact.

Custom Interactive Controls in jupyter notebooks

1. using @interact decorator

This is the easiest way to add interactive widgets. Import the interact function from ipywidgets. Wrap the code you want to be interactive in a function with the parameters having a default value. Put @interact decorator above this function. On execution, the interact decorator creates widgets for each of the parameters of the wrapper function. The default values for the parameters are necessary because the interact decorator inferences the widget type using these values.

In this example, we plot a circle and provide interactive widgets to alter its linewidth, boundary color and radius. We start with putting %matplotlib widget which specifies that we want an interactive matplotlib figure (which can be zoomed, panned and saved). Next we import the necessary libraries and objects and define a function named circle to plot the circle. It contains arguments/parameters which we want to alter with interactive widgets and they have default values to be used with the interact decorator as described in earlier sections. Now we define the code to plot the circle inside this function and use these parameters wherever the alterable property is to be specified. Finally decorate the circle function with @interact.

Python3




%matplotlib widget
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, widgets
 
@interact
def circle(radius=1.0, linewidth=1, color = ['red', 'blue', 'green']):
    angles = np.linspace(0,2*np.pi,100)
    fig, ax = plt.subplots()
    ax.set_aspect(1)
    ax.set_xlim(-10,10)
    ax.set_ylim(-10,10)
    ax.plot(radius*np.cos(angles), radius*np.sin(angles), linewidth = linewidth, c = color)
    plt.show()


Output:

ezgif-4-6197df5e7c

2. using interact function call

This example improves the last example by using interact function call (instead of decorator) which allows greater flexibility as it allows specifying a widget for each parameter. We can remove the default arguments here. We use the interact function as shown earlier. Using this flexibility, we improve certain things like setting max and min for radius and linewidth. Earlier example provided a slider for linewidth which can be slided below 0. This is not desirable since specifying linewidth below 0 is meaningless, hence we specify the min of its slider to 0. Also, instead of a list of colors, we provided a color picker widget which allows the user to pick just any color.

Python3




%matplotlib widget
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, widgets
 
def circle(radius, linewidth, color):
    angles = np.linspace(0,2*np.pi,100)
    fig, ax = plt.subplots()
    ax.set_aspect(1)
    ax.set_xlim(-10,10)
    ax.set_ylim(-10,10)
    ax.plot(radius*np.cos(angles), radius*np.sin(angles), linewidth = linewidth, c = color)
    plt.title('Circle of radius {} units'.format(radius))
    plt.show()
 
interact(
    circle,
    radius = widgets.FloatSlider(min = 0, max = 10, value = 1),
    linewidth = widgets.IntSlider(min = 0, max = 5, value = 1),
    color = widgets.ColorPicker()
)


Output:

ezgif-5-80b3ace929

Using the interact_manual function/decorator

When you want to turn off auto-update, just replace the interact decorator or function with interact_manual keeping rest of the things unchanged. Auto update will be turned off and you will get an update button as shown in this example –

Python3




import matplotlib.pyplot as plt
from ipywidgets import interact_manual, widgets
 
@interact_manual
def wrapperFunction(x = 5,y = 4):
    plt.xlim(0,10)
    plt.ylim(0,10)
    plt.plot(x,y,marker = 'o')
    plt.show()


Output:

Example of interactive controls in Jupyter Notebook using interact_manual from ipywidgets.

Example of interactive controls in Jupyter Notebook using interact_manual from ipywidgets.

Notice that “Run Interact” button in the output. It should be clicked to update the output.

Note: We used matplotlib here, but one can use any plotting library that jupyter supports like plotly, bokeh, etc. inside the wrapper function because the code inside the wrapper function doesn’t matter for the interactive widgets.

Interactive scatter plot with IPywidgets controls

It is an interactive 3D scatter plot using IPywidgets and Matplotlib. It will display three sliders that allow you to interactively adjust the limits of the 3D scatter plot along the X, Y, and Z axes. The plot updates dynamically as you move the sliders, providing an interactive exploration of the 3D scatter plot.

Python3




import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import ipywidgets as widgets
from IPython.display import display
 
# Generate random data for the 3D scatter plot
np.random.seed(42)
x_data = np.random.rand(50)
y_data = np.random.rand(50)
z_data = np.random.rand(50)
 
# Create 3D scatter plot function
def create_3d_scatter_plot(x_limit, y_limit, z_limit):
    fig = plt.figure(figsize=(10, 8))
    ax = fig.add_subplot(111, projection='3d')
    ax.scatter(x_data, y_data, z_data, label='Scatter Plot', c='red', marker='o')
    ax.set_title('Interactive 3D Scatter Plot')
    ax.set_xlabel('X-axis')
    ax.set_ylabel('Y-axis')
    ax.set_zlabel('Z-axis')
    ax.set_xlim(0, x_limit)
    ax.set_ylim(0, y_limit)
    ax.set_zlim(0, z_limit)
    ax.legend()
    plt.show()
 
# Define interactive controls using IPywidgets
x_limit_slider = widgets.FloatSlider(value=1.0, min=0.1, max=2.0, step=0.1, description='X-axis Limit:')
y_limit_slider = widgets.FloatSlider(value=1.0, min=0.1, max=2.0, step=0.1, description='Y-axis Limit:')
z_limit_slider = widgets.FloatSlider(value=1.0, min=0.1, max=2.0, step=0.1, description='Z-axis Limit:')
 
# Define update function for the 3D scatter plot
def update_plot(change):
    create_3d_scatter_plot(x_limit_slider.value, y_limit_slider.value, z_limit_slider.value)
 
# Attach the update function to the sliders' value change event
x_limit_slider.observe(update_plot, 'value')
y_limit_slider.observe(update_plot, 'value')
z_limit_slider.observe(update_plot, 'value')
 
# Display the interactive controls
display(x_limit_slider)
display(y_limit_slider)
display(z_limit_slider)
 
# Initial 3D scatter plot
create_3d_scatter_plot(x_limit_slider.value, y_limit_slider.value, z_limit_slider.value)


Output:

ezgif-2-230ae8272d

Browsing images using IPython widgets

We can put in the name of a folder and the file dropdown will list all the image files (ending with .png, .jpg, .jpeg and .gif). We can select an image to show. Moreover, one can choose to apply the blur radius using checkbox and select the blur radius through the slider. We need flexibility in deciding and defining widgets so we naturally use the method of calling interact function explicitly here. The code structure is almost similar to the last example except that we observe any changes in value of folder input widget. Whenever its value changes, we update the file selection (dropdown) widget to list all the image files in that folder and show the first one by default. To work with the image we need to install pillow library which must be installed using pip as all the other modules were installed earlier.

Python3




%matplotlib widget
import matplotlib.pyplot as plt
from ipywidgets import interact, widgets
import numpy as np
import os
from PIL import Image, ImageFilter
 
def imageEditor(folder, filename, blur, blurRadius):   
    # Opens a image in RGB mode
    im = Image.open('{}\\{}'.format(folder, filename))
 
    if(blur == True):
        # blur only if checkbox checked
        im = im.filter(ImageFilter.GaussianBlur(blurRadius))
         
    # show the image
    plt.imshow(im)
    plt.axis('off')
    plt.show()
 
# creating the widgets
folderWidget = widgets.Text(value = os.getcwd() + '\\images\\pngFiles')
fileWidget = widgets.Dropdown(options = os.listdir(folderWidget.value))
 
# update function to update fileslist when folder name changes
def updateFilesList(*args):
    filesList = [file for file in os.listdir(folderWidget.value) if file.endswith(('.png', '.jpg', '.jpeg','.gif'))]
    fileWidget.options = filesList
    fileWidget.value = filesList[0]
 
# observer folder widget and call updateFilesList whenever its value changes
folderWidget.observe(updateFilesList, 'value')
 
interact(
    imageEditor,
    filename = fileWidget,
    folder = folderWidget,
    blur = widgets.Checkbox(value = False),
    blurRadius = widgets.FloatSlider(min = 0, max = 5, description = "Blur Radius")
)


Output:

ezgif-2-29615872b6

Interactive Paraboloid

Now the reader has enough knowledge to understand the code for the paraboloid example shown in the cover video. Here is the code for the paraboloid with interactive controls shown in cover video –

Python3




from ipywidgets import interact
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
 
 
def plot_paraboloid(height=1.0, radius=1.0, rotation=5.0, colormap='viridis'):
    u = np.linspace(0, 1, 20)
    v = np.linspace(0, 2 * np.pi, 20)
    u, v = np.meshgrid(u, v)
 
    x = radius * ((u / height) ** 0.5) * np.cos(v)
    y = radius * ((u / height) ** 0.5) * np.sin(v)
    z = u
 
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.set_aspect('equal')
    ax.set_xlim(-1.5, 1.5)
    ax.set_ylim(-1.5, 1.5)
    ax.set_zlim(0, 1)
    ax.plot_surface(x, y, z, cmap=colormap)
    ax.view_init(elev=20, azim=rotation)
    plt.show()
 
 
interact(plot_paraboloid, height=(0.1, 2.0), radius=(0.1, 2.0),
         rotation=(-180, 180), colormap=['viridis', 'Blues', 'magma_r'])


Output:

ezgif-2-b0596dad6e

Interactive 3D Surface Plot

It creates an interactive 3D surface plot using IPywidgets and Matplotlib. The sliders for adjusting the values of a, b, and c, as well as a dropdown menu for selecting different colormaps. The 3D surface plot dynamically updates as you interact with the sliders and colormap menu.

Python3




from ipywidgets import interact
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
 
def surface_plot(a=1, b=1, c=1, colormap='viridis'):
    x = np.linspace(-5, 5, 100)
    y = np.linspace(-5, 5, 100)
    x, y = np.meshgrid(x, y)
    z = a * np.exp(-(x**2 + y**2) / (2*c**2))
 
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.plot_surface(x, y, z, cmap=colormap)
    ax.set_xlabel('X-axis')
    ax.set_ylabel('Y-axis')
    ax.set_zlabel('Z-axis')
    ax.set_title('3D Surface Plot')
    plt.show()
 
interact(surface_plot, a=(0.1, 2.0), b=(0.1, 2.0), c=(0.1, 2.0), colormap=['viridis', 'Blues', 'magma_r'])


Output:

ezgif-2-232df9926d

Conclusion

Interactive controls can be easily added in jupyter notebooks using jupyter widgets to conveniently explore and handle the changing parameters. We can do so using interact and interact_manual functions from the ipywidgets module. The difference between them is that interact auto updates the output while interact_manual provides a button to update it. Both can be used as decorators and as function calls. Decorators automatically create the widgets by inferencing from the default values of the parameters given to the wrapper function, hence are easier to use. Function call is more useful when we want flexibility and want to explicitly control what widget to use and its properties.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads