Description of problem
For the time being, Brian2 is able to compute the population averages. But what I want is the average values over time. The simplest way is to monitor the states every timestep. However, in my simulation, I have to run for a long time range. Storing the net states at every timestep will consume a lot of time, memory, and disk space. So I prefer to compute the time average on the fly. And I monitor the states every 5 timesteps to keep the store file not so huge, which made me inable to get the state at every timestep.
In this case, I implemented my average with the following code:
# v and all v_prev have been defined in equations
neuron.run_regularly('''
v_prev3 = v_prev2
v_prev2 = v_prev1
v_prev1 = v
''', when='before_groups')
run(1*sec)
vs = np.vstack((neuron.v, neuron.v_prev1, neuron.v_prev2, neuron.v_prev3))
v_mean = vs.mean(axis=0)
This is feasible, but very awkward. If I want to average over 100 timesteps, I have to define 99 v_prev
s, extract them respectively, which is very clumsy.
So I tried another way. I defined a deque with a fixed length. In each timestep, I compute the average of the deque:
from collections import deque
vs = deque([0] * 5, maxlen=5)
@check_units(v=mV, result=mV)
def var_avg(v):
global deque
deque.append(v)
return sum(v) / 5
eqs = """
...
v_avg = var_avg(v) : volt
"""
Then I ran into the error:
SyntaxError: The subexpression âv_avgâ refers to a stateful function (e.g. rand()). Such expressions should only be evaluated once per timestep, add the âconstant over dtâ flag.
All right, then I added the flag:
eqs = """
...
v_avg = var_avg(v) : volt (constant over dt)
"""
Another error occured this time:
NotImplementedError: Cannot use function âvar_avgâ: "No implementation available for target âcythonâ. Available implementations: "
So I wonder if there is a better way to obtain the time average values.
Minimal code to reproduce problem
from brian2 import *
start_scope()
N = 1000
tau = 10 * ms
vr = -70 * mV
vt0 = -50 * mV
delta_vt0 = 5 * mV
tau_t = 100 * ms
sigma = 0.5 * (vt0 - vr)
v_drive = 2 * (vt0 - vr)
duration = 20 * ms
from collections import deque
vs = deque([0] * 5, maxlen=5)
@check_units(v=mV, result=mV)
def var_avg(v):
global deque
deque.append(v)
return sum(v) / 5
eqs = '''
# dv/dt = (v_drive+vr-v)/tau : volt
dv/dt = (v_drive+vr-v)/tau + sigma*xi*tau**-0.5 : volt
dvt/dt = (vt0-vt)/tau_t : volt
v_avg = var_avg(v) : volt (constant over dt)
'''
reset = '''
v = vr
vt += delta_vt0
'''
G = NeuronGroup(N, eqs, threshold='v>vt',
reset=reset, refractory=5 * ms, method='euler')
G.v = 'rand()*(vt0-vr)+vr'
G.vt = vt0
run(1*ms)
What you have aready tried
- average v, v_prev1, âŚ, v_prevN (clusmy)
- use a deque (error encountered)
as described inDescription of problem