# Import modules
import ipywidgets as widgets31 Widgets
widgets, interactivity, ipywidgets
Adding interactivity to Jupyter notebooks can be a great way of improving exploratory data analysis and real-time interactive data visualization. The ipywidgets library provides a powerful toolset for creating interactive widget elements like sliders, dropdowns, and buttons in Jupyter notebooks.
The following examples will demonstrate:
- the basic syntax to create widgets and set custom parameters
- how to define a function that ingests widget values
- how to connect the widget and the function
The widgets may not appear in the online version of the tutorial. Either copy the code and run it in your local Jupyter notebook or download the notebook from the Github repository.
Example 1: Convert bushels to metric tons
A common task in agronomy is to convert grain yields from bushels to metric tons. We will use ipywidgets to create interactive dropdowns and slider widgets to facilitate the convertion between these two units for common crops.
# Define widget
crop_dropdown = widgets.Dropdown(options=['Barley','Corn','Sorghum','Soybeans','Wheat'],
                                 value='Wheat', description='Crop')
bushels_slider = widgets.FloatSlider(value=40, min=0, max=200, step=1,
                                    description='Bushels/acre')
# Define function
def bushels_to_tons(crop, bu):
    """Function that converts bushels to metric tons for common crops.
       Source: https://grains.org/
    """
    # Define constants
    lbs_per_ton = 0.453592/1000
    acres_per_ha = 2.47105
    
    # Convert bu -> lbs -> tons
    if crop == 'Barley':
        tons =  bu * 48 * lbs_per_ton 
        
    elif crop == 'Corn' or crop == 'Sorghum':
        tons =  bu * 56 * lbs_per_ton
        
    elif crop == 'Wheat' or crop == 'Soybeans':
        tons = bu * 60 * lbs_per_ton
        
    # Convert acre -> hectares
    tons = round(tons * acres_per_ha, 2)
    return widgets.FloatText(value=tons, description='Tons/ha', disabled=True)
# Define interactivity
widgets.interact(bushels_to_tons, crop=crop_dropdown, bu=bushels_slider);Example 2: Runoff-Precipitation
Widgets are also a great tool to explore and learn how models representing real-world processes respond to input changes. In this example we will explore how the curve number of a soil is related to the amount of runoff for a range of precipitation amounts.
import ipywidgets as widgets
import matplotlib.pyplot as plt
import numpy as np
plt.style.use('ggplot')# Create widget
cn_slider = widgets.IntSlider(50, min=1, max=100, description='Curve number')
# Create function
def estimate_runoff(cn):
    """Function that computes runoff based on the 
    curve number method proposed by the Soil Conservation Service
    Source: https://www.wikiwand.com/en/Runoff_curve_number
    Inputs
    cn : Curve number. 0 means fully permeable and 100 means fully impervious.
    
    Returns
    Figure of runoff as a function of precipitation
    """
    P = np.arange(0, 12, step=0.01) # Precipitation in inches
    RO = np.zeros_like(P)
    S = 1000/cn - 10
    Ia = S * 0.05 # Initial abstraction (inches)
    idx = P > Ia
    RO[idx] = (P[idx] - Ia)**2 / (P[idx] - Ia + S)
    # Create figure
    plt.figure(figsize=(6,4))
    plt.plot(P,RO,'--k')
    plt.title('Curve Number Method')
    plt.xlabel('Precipitation (inches)')
    plt.ylabel('Runoff (inches)')
    plt.xlim([0,12])
    plt.ylim([0,12])
    return plt.show()
# Define interactivity
widgets.interact(estimate_runoff, cn=cn_slider);