Interactive matplotlib widget not updating with scipy ode solver
<p>I have been using the interactive matplotlib widgets to visualise the solution of differential equations. I have got it working with the odeint function in scipy, however have not managed to get it to update with the ode class. I would rather use the latter as it has greater control over which solver is used.</p>

<p>The following code is used to solve a differential that is an exponential decay. The y0 is the amplitude of the decay. The code stops working when solver.integrate(t1) is called inside the update function. I'm not sure why this is.</p>

<pre><code>from scipy.integrate import ode

# solve the system dy/dt = f(t, y)
def f(t, y):
    return -y / 10

# Array to save results to
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 the 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)
</code></pre>

<p><em>For next time, please post the complete code with all imports etc. such that people can actually reproduce your problem.</em></p>

<p>Comming to the question: I guess it's always wise to seperate calculations from plotting. Therefore first try to solve the ODE with some given initial conditions. Once that works, try the plotting and interactive stuff.</p>

<p>In your case we would build a function that solves the ODE and then use this function with different initial conditions also in the plotting updates.</p>

<pre><code>import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
import numpy as np
from scipy.integrate import ode


# solve the system dy/dt = f(t, y)
def f(t, y):
    a = np.zeros((1,1))
    a[0] = -y / 10.
    return a

#define a function to solve the ODE with 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() and k &lt; steps:
        solver.integrate(solver.t + dt)
        t[k] = solver.t
        Y[k] = solver.y[0]
        k += 1
    return t, Y

# set the ODE integrator   
solver = ode(f).set_integrator("dopri5")  
# Initial conditions
y0 = 1.  # Initial amplitude
t0 = 0.      # Start time
t1 = 20.    # End time
#solve once for 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()
</code></pre>

python matplotlib scipy