How to make two sliders in matplotlib

2019-02-26 09:21发布

问题:

I would like to make two sliders in matplotlib to manually change N and P values in my predator-prey model:

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint

def lotka(x,t,params):
    N, P = x 
    alpha, beta, gamma, delta = params 
    derivs = [alpha*N - beta*N*P, gamma*N*P - delta*P] 
    return derivs

N=2
P=1
alpha=3
beta=0.5
gamma=0.4
delta=3

params = [alpha, beta, gamma, delta]
x0=[N,P]
maxt = 20
tstep = 0.01

t=np.arange(0,maxt,tstep)
equation=odeint(lotka, x0, t, args=(params,))

plt.plot(t,equation)
plt.xlabel("Time")
plt.ylabel("Population size")
plt.legend(["Prey", "Predator"], loc="upper right")

plt.title('Prey & Predator Static Model')
plt.grid(color="b", alpha=0.5, linestyle="dashed", linewidth=0.5)

This is my code which produces a graph for fixed initial values of N and P. However, I'd like to change them to see how the plot changes. And for this, I'd like to use sliders like: http://matplotlib.org/users/screenshots.html#slider-demo but I do not know how to add this into my code...

Could anyone please give me any direction? Many thanks!! xx

回答1:

From the example, hope the comments help you understand what's what:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
from scipy.integrate import odeint

# Function to draw
def lotka(x, t, params):
    N, P = x
    alpha, beta, gamma, delta = params 
    derivs = [alpha*N - beta*N*P, gamma*N*P - delta*P] 
    return derivs

# Parameters
Nmin = 1
Nmax = 100
Pmin = 1
Pmax = 100
N0 = 2
P0 = 1
alpha = 3
beta = 0.5
gamma = 0.4
delta = 3

params = [alpha, beta, gamma, delta]
x0=[N0,P0]
maxt = 20
tstep = 0.01

# Initial function values
t = np.arange(0, maxt, tstep)
prey, predator = odeint(lotka, x0, t, args=(params,)).T
# odeint returne a shape (2000, 2) array, with the value for
# each population in [[n_preys, n_predators], ...]
# The .T at the end transponses the array, so now we get each population
# over time in each line of the resultint (2, 2000) array.

# Create a figure and an axis to plot in:
fig = plt.figure()
ax = fig.add_axes([0.10, 0.3, 0.8, 0.6])
prey_plot = ax.plot(t, prey, label="Prey")[0]
predator_plot = ax.plot(t, predator, label="Predator")[0]

ax.set_xlabel("Time")
ax.set_ylabel("Population size")
ax.legend(loc="upper right")
ax.set_title('Prey & Predator Static Model')
ax.grid(color="b", alpha=0.5, linestyle="dashed", linewidth=0.5)
ax.set_ylim([0, np.max([prey, predator])])

# create a space in the figure to place the two sliders:
axcolor = 'lightgoldenrodyellow'
axis_N = fig.add_axes([0.10, 0.1, 0.8, 0.03], facecolor=axcolor)
axis_P = fig.add_axes([0.10, 0.15, 0.8, 0.03], facecolor=axcolor)
# the first argument is the rectangle, with values in percentage of the figure
# size: [left, bottom, width, height]

# create each slider on its corresponding place:
slider_N = Slider(axis_N, 'N', Nmin, Nmax, valinit=N0)
slider_P = Slider(axis_P, 'P', Pmin, Pmax, valinit=P0)

def update(val):
    # retrieve the values from the sliders
    x = [slider_N.val, slider_P.val]
    # recalculate the function values
    prey, predator = odeint(lotka, x, t, args=(params,)).T
    # update the value on the graph
    prey_plot.set_ydata(prey)
    predator_plot.set_ydata(predator)
    # redraw the graph
    fig.canvas.draw_idle()
    ax.set_ylim([0, np.max([prey, predator])])

# set both sliders to call update when their value is changed:
slider_N.on_changed(update)
slider_P.on_changed(update)

# create the reset button axis (where its drawn)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
# and the button itself
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')

def reset(event):
    slider_N.reset()
    slider_P.reset()

button.on_clicked(reset)

Notice, however, you should have shown how you tried to adapt the example to what you had and how it was misbehaving.

Nevertheless, welcome to Stackoverflow.



回答2:

So, I have tried with this code:

from scipy import integrate
from matplotlib.widgets import Slider, Button, RadioButtons

fig, ax = plt.subplots()
plt.subplots_adjust(left=0.25, bottom=0.25)
plt.xlabel("Time")
plt.ylabel("Population size")
plt.legend(["Prey", "Predator"], loc="upper right")

plt.title('Prey & Predator Static Model')
plt.grid(color="b", alpha=0.5, linestyle="dashed", linewidth=0.5)

l1, l2 = plt.plot(t, equation)

axcolor = 'b'
ax_N = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
ax_P = plt.axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)

sN = Slider(ax_N, 'N', 0, 80, valinit=1)
sP = Slider(ax_P, 'P', 0, 80, valinit=1)


def update(val):
    N = N*sN.val
    P = P*sP.val
    x = equation
    fig.canvas.draw_idle()
    l1, l2.set_ydata(y)    
    ax.set_ylim(y.min(), y.max())  
    draw()

sN.on_changed(update)
sP.on_changed(update)

plt.show()

I could not manipulate the sliders. Thank you so much @berna1111