Search code examples
ipywidgets

Cursor of FloatSlide widget doesn't move


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.


Solution

  • 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'))