Ipywidgets#
If you publish widgets in a jupyter book they might (depending on your implementation) require an active python kernel for the output to be interactive. Using the thebe-integration, this is possible. Note: You can circumvent the use of a kernel by using packages which don’t need such a kernel, for example the non-kernel-based widgets using Plotly.
matplotlib
widgets#
When you’d like to use ipywidgets
in combinations with a matplotlib
figure, import the following packages:
import ipywidgets as widgets
import micropip
await micropip.install("ipympl")
Activate the correct output format:
%matplotlib widget
Write the code which generates your plot in a function:
fig = plt.figure() # Define the figure once
ax = fig.add_subplot(1,1,1) # Define the axis once
def update_plot(input_variables_from_widget):
ax.clear() # Clear the existing plot
ax.plot(x,y) # Plot your actual data
plt.draw() # Update the plot whenever this function is executed
Initiate the widget:
input_slider = widgets.FloatSlider(value=0, min=0, max=10, step=1, description='Input variable:') # Defines a widget, more options than just FloatSlider
widgets.interact(update_plot, input_variable_from_widget = input_slider);
Please note:
You might want to hide the output before the thebe has been activated.
You can hide the code by adding a custom-made tag:
thebe-remove-input-init
.You can automatically start the thebe functionality when you add
auto-execute-page
to a cell.
Example#
The code below shows an example of the strain energy in a structure and work done by a force for different trial functions. Because of the actual python code, the plot ‘refreshes’ upon updating a widgets. This can be avoided by updating the current figure instead of plotting a new figure. Remember, first press –> Live Code and then wait until all cells are executed:
import sympy as sp
F = 10
EI = 20e3
L = 3
# Polynomial trial function
x, C1, C2, C3, C4, F, u0= sp.symbols('x, C1, C2, C3, C4, F, u0')
w = C1*x**3+C2*x**2+C3*x + C4
eq1 = sp.Eq(w.subs(x,0),0)
eq2 = sp.Eq(w.diff(x).subs(x,0),0)
eq3 = sp.Eq((-w.diff(x,2)*EI).subs(x,L),0)
eq4 = sp.Eq(w.subs(x,L),u0)
sol = sp.solve((eq1, eq2,eq3,eq4),(C1,C2,C3,C4))
w_sol = sp.nsimplify(w.subs(sol))
w_numpy_polynomial = sp.lambdify((u0,x),w_sol)
M_sol_polynomial = sp.nsimplify(EI * w_sol.diff(x,2))
Ev_polynomial = sp.integrate(sp.nsimplify(M_sol_polynomial**2/(EI*2)),(x,0,3))
Ev_numpy_polynomial = sp.lambdify(u0,Ev_polynomial)
V_polynomial = Ev_polynomial - 10 * u0
V_numpy_polynomial = sp.lambdify(u0,V_polynomial)
#cosine trial function
w_sol = u0*sp.sin(x/12*2*sp.pi-sp.pi/2)+u0
w_numpy_sin = sp.lambdify((u0,x),w_sol)
M_sol_sin = sp.nsimplify(EI * w_sol.diff(x,2))
Ev_sin = sp.integrate(sp.nsimplify(M_sol_sin**2/(EI*2)),(x,0,3))
Ev_numpy_sin = sp.lambdify(u0,Ev_sin)
V_sin = Ev_sin - 10 * u0
V_numpy_sin = sp.lambdify(u0,V_sin)
#sin trial function
w_sol = 2*u0*(sp.cosh(x/sp.pi))-2*u0
w_numpy_cosh = sp.lambdify((u0,x),w_sol)
M_sol_cosh = sp.nsimplify(EI * w_sol.diff(x,2))
Ev_cosh = sp.integrate(sp.nsimplify(M_sol_cosh**2/(EI*2)),(x,0,3))
Ev_numpy_cosh = sp.lambdify(u0,Ev_cosh)
V_cosh = Ev_cosh - 10 * u0
V_numpy_cosh = sp.lambdify(u0,V_cosh)
import matplotlib.pylab as plt
import numpy as np
from ipywidgets import widgets, interact
def func(u,trial_function):
fig, axs = plt.subplots(2, 2, figsize=(10, 6))
x = np.linspace(0,3,100)
if trial_function == 'Polynomial':
w_numpy = w_numpy_polynomial
Ev_numpy = Ev_numpy_polynomial
V_numpy = V_numpy_polynomial
elif trial_function == 'cos':
w_numpy = w_numpy_sin
Ev_numpy = Ev_numpy_sin
V_numpy = V_numpy_sin
elif trial_function == 'cosh':
w_numpy = w_numpy_cosh
Ev_numpy = Ev_numpy_cosh
V_numpy = V_numpy_cosh
axs[0,0].plot(x,w_numpy(u,x))
axs[0,0].set_xlim([-0.2,3.2])
axs[0,0].set_ylim([-0.003,0.01])
axs[0,0].invert_yaxis()
axs[0,0].annotate(text='', xy=(3,w_numpy(u,3)), xytext=(3,0), arrowprops=dict(arrowstyle='fancy'))
axs[0,0].text(3.1,w_numpy(u,3),'$u_0$')
axs[0,0].axis('off')
axs[0,1].axis('off')
axs[0,1].set_xlim([-0.2,3.2])
axs[0,1].set_ylim([-0.003,0.01])
axs[0,1].annotate(text='', xy=(1.5,w_numpy(u,3)), xytext=(1.5,w_numpy(u,3)-0.003), arrowprops=dict(arrowstyle='simple'))
axs[0,1].invert_yaxis()
x_axis= ['$E_v$','$A_F$','$E_v - A_F$']
y_axis = [Ev_numpy(u),w_numpy(u,3)*10,Ev_numpy(u)-w_numpy(u,3)*10]
axs[1,0].bar(x_axis,y_axis,color=('blue','green','orange'))
axs[1,0].set_ylim([-0.03,0.1])
axs[1,0].set_yticklabels([])
axs[1,0].set_yticks([])
u_range=np.linspace(-0.0015,0.01,100)
axs[1,1].plot(u_range,Ev_numpy(u_range),label='$E_v$',color='blue')
axs[1,1].plot(u_range,w_numpy(u_range,3)*10,label='$F_A$',color='green')
axs[1,1].plot(u_range,V_numpy(u_range),label='$E_v - A_F$',color='orange')
axs[1,1].legend()
axs[1,1].plot(u,Ev_numpy(u),'o',color='blue')
axs[1,1].plot(u,w_numpy(u,3)*10,'o',color='green')
axs[1,1].plot(u,Ev_numpy(u)-w_numpy(u,3)*10,'o',color='orange')
axs[1,1].set_ylim([-0.03,0.1])
axs[1,1].set_xlim([-0.0015,0.01])
axs[1,1].set_xlabel('$u_0$')
axs[1,1].set_xticks([])
axs[1,1].set_xticklabels([])
axs[1,1].set_yticks([])
plt.show()
The graph will appear below in interactive mode:
interact(func, u = widgets.FloatSlider(min=-0.001, max=0.01, value=0, step=0.0002, description="Displacement u_0",readout_format='.4f',style= {'description_width': '180px'},layout = {'width': '400px'}),
trial_function = widgets.ToggleButtons(options=['Polynomial', 'cos', 'cosh']));