python - Interactive matplotlib widget not updating with scipy ode solver -
i have been using interactive matplotlib widgets visualise solution of differential equations. have got working odeint function in scipy, have not managed update ode class. rather use latter has greater control on solver used.
the following code used solve differential exponential decay. y0 amplitude of decay. code stops working when solver.integrate(t1) called inside update function. i'm not sure why is.
from scipy.integrate import ode # solve system dy/dt = f(t, y) def f(t, y): return -y / 10 # array save results def solout(t, y): sol.append([t, *y]) solver = ode(f).set_integrator('dopri5') solver.set_solout(solout) # initial conditions y0 = [1] # initial amplitude t0 = 0 # start time t1 = 20 # end time fig = plt.figure(figsize=(10, 6)) fig.subplots_adjust(left=0.25, bottom=0.4) ax = plt.subplot(111) # solve des solver.set_initial_value(y0, t0) sol = [] solver.integrate(t1) sol = np.array(sol) t = sol[:, 0] y = sol[:, 1] l, = plt.plot(t, y, lw=2, color='red') plt.axis([0, 20, 0, 1.1]) plt.xlabel('time (ms)') plt.ylabel('n1(t)') plt.grid() axcolor = 'lightgoldenrodyellow' axn1 = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor) sn1 = slider(axn1, 'y(0)', 0, 1.0, valinit=1) def update(val): y0 = [sn1.val] solver.set_initial_value(y0, t0) sol = [] solver.integrate(t1) sol = np.array(sol) t = sol[:, 0] y = sol[:, 1] l.set_data(t, y) plt.draw() sn1.on_changed(update)
i guess it's wise separate calculations plotting. therefore first try solve ode given initial conditions. once works, try plotting , interactive stuff.
in case build function solves ode , use function different initial conditions in plotting updates.
import matplotlib.pyplot plt matplotlib.widgets import slider import numpy np scipy.integrate import ode # solve system dy/dt = f(t, y) def f(t, y): = np.zeros((1,1)) a[0] = -y / 10. return #define function solve ode initial conditions def solve(t0, t1, y0, steps=210): solver.set_initial_value([y0], t0) dt = (t1 - t0) / (steps - 1) solver.set_initial_value([y0], t0) t = np.zeros((steps, 1)) y = np.zeros((steps, 1)) t[0] = t0 y[0] = y0 k = 1 while solver.successful() , k < steps: solver.integrate(solver.t + dt) t[k] = solver.t y[k] = solver.y[0] k += 1 return t, y # set ode integrator solver = ode(f).set_integrator("dopri5") # initial conditions y0 = 1. # initial amplitude t0 = 0. # start time t1 = 20. # end time #solve once given initial amplitude t, y = solve(t0, t1, y0) fig = plt.figure(figsize=(10, 6)) fig.subplots_adjust(left=0.25, bottom=0.4) ax = plt.subplot(111) l, = plt.plot(t, y, lw=2, color='red') plt.axis([0, 20, 0, 1.1]) plt.xlabel('time (ms)') plt.ylabel('n1(t)') plt.grid() axn1 = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg='#e4e4e4') sn1 = slider(axn1, 'y(0)', 0, 1.0, valinit=1) def update(val): #solve again each time t, y = solve(t0, t1, sn1.val) l.set_data(t, y) plt.draw() sn1.on_changed(update) plt.show()
Comments
Post a Comment