In many cases, it is useful to perform an initial simulation to allow the transient dynamics to dissipate, and then continue the simulation using the steady state obtained from the initial simulation as the initial conditions. The TVB web interface allows for this by 'branching' a loaded simulation. From a Python script, we need to handle the details ourselves. This demo shows how to do that for a region-level, stochastic simulation with the BOLD monitor.
%matplotlib inline
import matplotlib.pyplot as plt
import numpy
import pickle as cPickle
from tvb.simulator.lab import *
LOG = get_logger('demo')
First, we build and configure the initial simulator,
sim = simulator.Simulator(
model=models.Generic2dOscillator(),
connectivity=connectivity.Connectivity.from_file(),
coupling=coupling.Linear(a=numpy.array([0.0126])),
simulation_length=1e4,
integrator=integrators.HeunStochastic(
dt=2 ** -4,
noise=noise.Additive(nsig=numpy.array([0.001]))),
monitors=(
monitors.TemporalAverage(period=1.0),
monitors.Bold(period=500.0),
monitors.ProgressLogger(period=1e3)
)
).configure()
let it run,
(tavg_time, tavg_data), (bold_time, bold_data), _ = sim.run()
and plot the transient:
plt.figure(figsize=(10, 5))
plt.plot(bold_time * 1e-3, bold_data[:, 0, :, 0], 'k', alpha=0.3)
plt.title('Initial transient in BOLD')
plt.xlabel('Time (s)')
plt.grid(True);
To save the state of the simulator, we need to put a few arrays into files:
sim_state_fname = 'sim_state.pickle'
with open(sim_state_fname, 'wb') as file_descr:
cPickle.dump({
'history': sim.history.buffer,
'current_step': sim.current_step,
'current_state': sim.current_state,
'bold_inner': sim.monitors[1]._interim_stock,
'bold': sim.monitors[1]._stock,
'rng': sim.integrator.noise.random_stream.get_state()
}, file_descr)
The simulation state is now saved in the current folder:
!ls -lh sim_state.pickle
We are free to dispose of the simulator:
del sim
Now we want to continue the simulator above with the saved state. In different scenarios, this might be in a different script, on a different day, so we need to build the simulator object again:
sim = simulator.Simulator(
model=models.Generic2dOscillator(),
connectivity=connectivity.Connectivity.from_file(),
coupling=coupling.Linear(a=numpy.array([0.0126])),
simulation_length=1e4,
integrator=integrators.HeunStochastic(
dt=2 ** -4,
noise=noise.Additive(nsig=numpy.array([0.001]))),
monitors=(
monitors.TemporalAverage(period=1.0),
monitors.Bold(period=500.0),
monitors.ProgressLogger(period=1e3)
)
).configure()
load its state,
with open(sim_state_fname, 'rb') as file_descr:
state = cPickle.load(file_descr)
sim.history.buffer = state['history']
sim.current_step = state['current_step']
sim.current_state = state['current_state']
sim.monitors[1]._interim_stock = state['bold_inner']
sim.monitors[1]._stock = state['bold']
sim.integrator.noise.random_stream.set_state(state['rng'])
and run it again; note that the step and time start off where the old simulator stopped:
(tavg_time, tavg_data), (bold_time, bold_data), _ = sim.run()
plt.figure(figsize=(10, 5))
plt.plot(bold_time * 1e-3, bold_data[:, 0, :, 0], 'k', alpha=0.3)
plt.title('Continued BOLD')
plt.xlabel('Time (s)')
plt.grid(True);
The continued BOLD does not show the transient present in the initial simulation.