Python中ODE模型的交互式连续绘图

问题描述:

我想创建一个集成ode模型的脚本,这样我就可以更改参数之一,并查看系统对此更改的响应.例如,如果有,我有一个Lotka-Volterra模型(摘自以下示例):

I would like to create a script that integrates an ode model, such that I can change one of the parameters and see the response of the systems to this change. If for, for example, I have a Lotka-Volterra model (as taken from this example):

import numpy as np
from scipy import integrate
a = 1.
b = 0.1
c = 1.5
d = 0.75

def dX_dt(X, t=0):
    """ Return the growth rate of fox and rabbit populations. """
    return array([ a*X[0] -   b*X[0]*X[1] ,  
                  -c*X[1] + d*b*X[0]*X[1] ])

t = np.linspace(0, 15,  1000)              # time
X0 = np.array([10, 5])    # initials conditions: 10 rabbits and 5 foxes  

X, infodict = integrate.odeint(dX_dt, X0, t, full_output=True)

我想为参数ac创建一个滑块,如 matplotlib的Slider_demo 或任何其他工具.该图应显示始终跨越[t_current - delta_t ,t_current]的某个时间窗口.因此,通过更改参数的滑块,我将能够连续探索参数空间.

I would like to create a slider for parameters a and c, as in the slider_demo of matplotlib, or any other tool. The plot should display a certain window of time that always spans [t_current - delta_t ,t_current]. And so I will be able to explore the parameters space continuously by changing the sliders of the parameters.

该怎么做?

您已经掌握了所有内容,基本上只是更改了窗口小部件中的更新方法

You have all the pieces, basically just change the update method in the widget example to recalculate the integral of dX_dt using the new value based on the sliders and then use this to set the y line values. The code would look like:

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

b = 0.1
d = 0.75
a=1
c=1.5
def dX_dt(X, t=0, a=1, c=1.5):
    """ Return the growth rate of fox and rabbit populations. """
    return np.array([ a*X[0] -   b*X[0]*X[1] ,  
                     -c*X[1] + d*b*X[0]*X[1] ])


t = np.linspace(0, 15,  1000)              # time
X0 = np.array([10, 5])          # initials conditions: 10 rabbits and 5 foxes  

fig, ax = plt.subplots()
plt.subplots_adjust(left=0.25, bottom=0.25)

l1, l2 = plt.plot(t, integrate.odeint(dX_dt, X0, t, (a, c)))

axcolor = 'black'
ax_a = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
ax_c = plt.axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)

sa = Slider(ax_a, 'a', 0.1, 10.0, valinit=1)
sc = Slider(ax_c, 'c', 0.1, 10.0, valinit=1.5)


def update(val):
    a = sa.val
    c = sc.val
    x = integrate.odeint(dX_dt, X0, t, (a, c))
    l1.set_ydata(x[:,0])
    l2.set_ydata(x[:,1])
    fig.canvas.draw_idle()

sa.on_changed(update)
sc.on_changed(update)

plt.show()