Recently, I have been trying to use widgets to interact with my plots. I have created a function that takes in two parameters to make my plots and it works perfectly, producing different plots depending on the value of the given parameters.
However, when I try to create FloatSlider widgets for these parameters, only one of them works. The other sort of "gets stuck" - I just can't move the slider (here is a link of a GIF showing what happens when I try to move the cursor of the slider).
Do you guys have any idea on what could be causing this issue?
Here is the code I'm using:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import ipywidgets as widgets
import matplotlib.ticker as mtick
def plot_2_2(v_0=0,dt=7e-7):
D = 1.5e-6 # diâmetro da gota de óleo [m]
rho = 840 # densidade do líquido [kg/m^3]
g = 9.8 # aceleração da gravidade [m/s^2]
V = np.pi/6*D**3 # volume da gota [m^3]
m = rho*V # massa da partícula [kg]
beta = 1.6e-4 # viscosidade dinâmica do ar [kg/ms]
b = beta*D # coeficiente de atrito linear [kg/s]
t_0 = 0 # tempo [s]
v_0 = v_0 # velocidade inicial da gota [m/s]
n_i = 0 # número de iterações
dt = dt # intervalo de tempo entre iterações [s]
fig = plt.figure(constrained_layout=True, figsize=[14,8])
spec = gridspec.GridSpec(ncols=1,nrows=2,figure=fig)
ax1 = fig.add_subplot(spec[0,0])
ax2 = fig.add_subplot(spec[1,0])
t = np.array([t_0])
v = np.array([v_0])
while v[-1] < (1-1e-4)*m*g/b or n_i < 100:
t = np.append(t,t[-1]+dt) # Passo no tempo
v = np.append(v,v[-1]+(m*g-b*v[-1])*(dt)/m) # Cálculo da velocidade no tempo seguinte
n_i += 1 # Aumento do contador de iterações
l11, = ax1.plot(t,v,'r--') # Solução numérica
l12, = ax1.plot(t,v_0*np.exp(-b/m*t)-(-m*g/b)*(1-np.exp(-b/m*t)),'kx') # Solução analítica
l2, = ax2.plot(t,100*abs(v_0*np.exp(-b/m*t)-(-m*g/b)*(1-np.exp(-b/m*t))),'c--') # Erro relativo
ax1.set_xlabel('Tempo [s]')
ax1.set_ylabel('Velocidade da Gota [m/s]')
ax1.set_ylim(bottom=-0.5e-4,top=1.5e-4)
ax1.ticklabel_format(axis="y", style="sci", scilimits=(0,0))
ax1.set_title("Evolução Velocidade da Gota")
ax1.grid(linestyle='-.')
# ax1.legend([l11,l12],['Solução Numérica','Solução Analítica - $v(t) = v_0 \cdot \exp^{-\dfrac{b}{m}t}$'])
ax2.yaxis.set_major_formatter(mtick.PercentFormatter())
ax2.set_xlabel('Tempo [s]')
ax2.set_ylabel('Erro Relativo')
ax2.set_title("Solução Numérica vs Solução Analítica")
ax2.grid(linestyle='-.')
plt.show(fig)
widgets.interact(plot_2_2, v_0=widgets.FloatSlider(min=0,max=10e-5,step=1e-5,readout_format='.1e'), dt=widgets.FloatSlider(min=5e-7,max=10e-7,step=1e-7,readout_format='.1e'))
Thanks, appreciate the help.
First, thankyou for the complete runnable example (with imports!)
I think this might be to do with the minimum value or step size the float widget can support.
Try to move this widget, I can't get it to change:
widgets.FloatSlider(min=5e-7,max=10e-7,step=1e-7,readout_format='.1e')
I wonder whether this is simply due to floating point rounding down small numbers to zero.
I tried having the input as integer, and applying the scale factor in the body of the code and it seemed to work fine. Would this work as an alternative:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import ipywidgets as widgets
import matplotlib.ticker as mtick
def plot_2_2(v_0=0,dt=7e-7):
dt = dt/10_000_000
D = 1.5e-6 # diâmetro da gota de óleo [m]
rho = 840 # densidade do líquido [kg/m^3]
g = 9.8 # aceleração da gravidade [m/s^2]
V = np.pi/6*D**3 # volume da gota [m^3]
m = rho*V # massa da partícula [kg]
beta = 1.6e-4 # viscosidade dinâmica do ar [kg/ms]
b = beta*D # coeficiente de atrito linear [kg/s]
t_0 = 0 # tempo [s]
v_0 = v_0 # velocidade inicial da gota [m/s]
n_i = 0 # número de iterações
dt = dt # intervalo de tempo entre iterações [s]
fig = plt.figure(constrained_layout=True, figsize=[14,8])
spec = gridspec.GridSpec(ncols=1,nrows=2,figure=fig)
ax1 = fig.add_subplot(spec[0,0])
ax2 = fig.add_subplot(spec[1,0])
t = np.array([t_0])
v = np.array([v_0])
while v[-1] < (1-1e-4)*m*g/b or n_i < 100:
t = np.append(t,t[-1]+dt) # Passo no tempo
v = np.append(v,v[-1]+(m*g-b*v[-1])*(dt)/m) # Cálculo da velocidade no tempo seguinte
n_i += 1 # Aumento do contador de iterações
l11, = ax1.plot(t,v,'r--') # Solução numérica
l12, = ax1.plot(t,v_0*np.exp(-b/m*t)-(-m*g/b)*(1-np.exp(-b/m*t)),'kx') # Solução analítica
l2, = ax2.plot(t,100*abs(v_0*np.exp(-b/m*t)-(-m*g/b)*(1-np.exp(-b/m*t))),'c--') # Erro relativo
ax1.set_xlabel('Tempo [s]')
ax1.set_ylabel('Velocidade da Gota [m/s]')
ax1.set_ylim(bottom=-0.5e-4,top=1.5e-4)
ax1.ticklabel_format(axis="y", style="sci", scilimits=(0,0))
ax1.set_title("Evolução Velocidade da Gota")
ax1.grid(linestyle='-.')
# ax1.legend([l11,l12],['Solução Numérica','Solução Analítica - $v(t) = v_0 \cdot \exp^{-\dfrac{b}{m}t}$'])
ax2.yaxis.set_major_formatter(mtick.PercentFormatter())
ax2.set_xlabel('Tempo [s]')
ax2.set_ylabel('Erro Relativo')
ax2.set_title("Solução Numérica vs Solução Analítica")
ax2.grid(linestyle='-.')
plt.show(fig)
widgets.interact(plot_2_2, v_0=widgets.FloatSlider(min=0,max=10e-5,step=1e-5,readout_format='.1e'), dt=widgets.FloatSlider(min=5,max=10,step=1,readout_format='.1e'))