Search code examples
pythonfunctionmatplotlibsliderinteractive

How to plot two functions with two separate sliders?


I'm trying to improve my non-existing abilities with python, so I'm trying to replicate a simple plot that has two functions that I can interact with, basically two functions and two sliders. This is what i came up with:

%matplotlib inline
from ipywidgets import interactive
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, num=100)

def CovA(m):
    CA = m*x/(1+m*x)
    return CA
    plt.plot(x, CovA(m))
    plt.show()
    
def CovB(n):
    CB = n*x/(1+n*x)
    return CB
    plt.plot(x, CovB(n))
    plt.show()

PlotCovA = interactive(CovA, m=(-2.0, 2.0))
PlotCovB = interactive(CovB, n=(-2.0, 2.0))

But nothing shows up, I've also tried using sliders as that seem more professional but also harder. What I really what to replicate is this code written in mathematica: https://www.wolframcloud.com/objects/demonstrations/LangmuirIsothermsForABinaryMixture-source.nb this one uses two functions plotted in the same graph with 5 sliders changing the parameters inside the functions.


Solution

  • I managed to do it on my own, if anyone finds another way of doing this please tell me so i can learn.

    I would also like to use auxiliary variables so my function isn't so long and messy, but I couldn't do it. This is what I wrote:

    # Agregar bibliotecas
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.widgets import Slider, Button
    
    # Crear subplot
    fig, ax = plt.subplots()
    plt.subplots_adjust(bottom=0.2)
    
    # Ajustar el subplot para que quepan los sliders
    fig.subplots_adjust(left=0.15, bottom=0.5)
    
    # Crear variable independiente (Presion) y ctes
    x = np.linspace(0, 10, num=100)
    ko = 1e-08
    R = 8.314
    m = 1000
    
    # Crear funcion A
    koa = (ko*np.exp((50*m)/(R*300)))
    FA = (ko*np.exp((50*m)/(R*300)))*(x/(1+2))/(1+(ko*np.exp((50*m)/(R*300)))*(x/(1+2))+(ko*np.exp((80*m)/(R*300)))*(x*4*2/(1+2)))
    pFA, = plt.plot(x, FA, label='Cobertura de A')
    
    # Crear funcion B
    kob = (ko*np.exp((45*m)/(R*300)))
    FB = (ko*np.exp((80*m)/(R*300)))*(x*2/(1+2))/(1+(ko*np.exp((50*m)/(R*300)))*(x/(1+2))+(ko*np.exp((80*m)/(R*300)))*(x*4*2/(1+2)))
    pFB, = plt.plot(x, FB, label='Cobertura de B')
     
    # Crear axes para ubicar los sliders
    ax_TE = plt.axes([0.25, 0.35, 0.65, 0.03])
    ax_KA = plt.axes([0.25, 0.30, 0.65, 0.03])
    ax_KB = plt.axes([0.25, 0.25, 0.65, 0.03])
    ax_alf = plt.axes([0.25, 0.20, 0.65, 0.03])
    ax_sit = plt.axes([0.25, 0.15, 0.65, 0.03])
    
    # Crear primer slider desde 200 a 500
    # con valor inicial 300
    TE = Slider(ax_TE, 'Temperatura', 200, 500, 300)
    
    # Crear segundo slider desde 10 a 80
    # con valor inicial 50
    KA = Slider(ax_KA, 'Entalpia de A', 10.0, 80.0, 50)
     
    # Crear tercer slider desde 10 a 80
    # con valor inicial 45
    KB = Slider(ax_KB, 'Entalpia de B', 10.0, 80.0, 45)
    
    # Crear cuarto slider desde 0.0 a 10.0
    # con valor inicial 2
    AL = Slider(ax_alf, 'Razon presion PB/PA', 0.0, 10.0, 2)
    
    # Crear quinto slider desde 0.5 a 10.0
    # con valor inicial 1
    SI = Slider(ax_sit, 'Razon sitios nB/nA', 0.5, 10.0, 1)
    
    # Funcion que actualiza el valor de las fxes cuando se mueve el slider
    def update(val):
        a = KA.val
        b = KB.val
        c = AL.val
        d = SI.val
        e = TE.val
    
        pFA.set_ydata((ko*np.exp((a*m)/(R*e)))*(x/(1+c))/(1+(ko*np.exp((a*m)/(R*e)))*(x/(1+c))+(ko*np.exp((b*m)/(R*e)))*(x*d*c/(1+c))))
        pFB.set_ydata((ko*np.exp((b*m)/(R*e)))*(x*c/(1+c))/(1+(ko*np.exp((a*m)/(R*e)))*(x/(1+c))+(ko*np.exp((b*m)/(R*e)))*(x*d*c/(1+c))))
        
    # Llama a la funcion actualizadora
    KA.on_changed(update)
    KB.on_changed(update)
    AL.on_changed(update)
    SI.on_changed(update)
    TE.on_changed(update)
    
    # Crear boton de reseteo con 'matplotlib.widgets.Button'
    resetax = fig.add_axes([0.8, 0.05, 0.11, 0.05])
    button = Button(resetax, 'Resetear', hovercolor='0.975')
    
    def reset(event):
        KA.reset()
        KB.reset()
        AL.reset()
        SI.reset()
        TE.reset()
    
    button.on_clicked(reset)
    
    # Graficar
    
    #print("El valor de KA es: {}".format(koa))
    #print("El valor de KB es: {}".format(kob))
    
    plt.suptitle('Isoterma tipo Langmuir')
    ax.set_xlabel('Presion (PA+PB) [bar]')
    ax.set_ylabel('N de moleculas por sitio')
    ax.set_xlim([-0.25, 10.25])
    ax.set_ylim([0, 1.2])
    leg = ax.legend(loc="best", numpoints=1)
    leg.get_frame().set_linewidth(1.0)
    plt.show()