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:
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:
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:
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:
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:
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:
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:
Interactive Controls in Jupyter Notebooks
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.
Contact Us