-
Notifications
You must be signed in to change notification settings - Fork 246
Closed
Description
Issue statement
I fail to simulate an LIF network with 2 neurons for a long duration run (1e6*second) in cpp_standalone mode. NO warning or error appears, and no data of spike trains is generated.
However, if I switch to a shorter run duration, like 1e5*second, the code works fine. And also, if I split the whole run duration into multiple pieces, such as replacing run(duration)
with
for _ in range(10):
run(duration/10)
the code works fine. I'm wondering is there a maximum run duration value in Brian2 cpp_standalone mode, or is it due to the data type issue? Could you please give me some help?
I attach my code below, and the command to run the simulation case I mentioned is below.
python simulate_LIF.py -T 1e6 --ref 0 -v 20 -g 10 -f 0.4 -u 0.1 --verbose
Versions
- python: 3.7.7
- brian2: 2.3.0.2
# %%
if __name__ == '__main__':
# %%
import numpy as np
import sys, os
import subprocess as sp
from utils import save2bin
from brian2 import *
import argparse
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-T", type=float, default=10000, help="simulation period, ms", )
parser.add_argument("--ref", type=float, default=2, help="refractory period", )
parser.add_argument('-v', "--tauv", type=float, default=20, help="time constant of v", )
parser.add_argument('-g', "--taug", type=float, default=5, help="time constant of g", )
parser.add_argument("-f", type=float, default=0.4, help="Poisson strength", )
parser.add_argument("-u", type=float, default=0.4, help="Poisson rate, in kHz", )
parser.add_argument("--verbose", action='store_true', help="show progress bar", )
args = parser.parse_args()
class ProgressBar(object):
def __init__(self, toolbar_width=40):
self.toolbar_width = toolbar_width
self.ticks = 0
def __call__(self, elapsed, complete, start, duration):
if complete == 0.0:
# setup toolbar
sys.stdout.write("[%s]" % (" " * self.toolbar_width))
sys.stdout.flush()
sys.stdout.write("\b" * (self.toolbar_width + 1)) # return to start of line, after '['
else:
ticks_needed = int(round(complete * self.toolbar_width))
if self.ticks < ticks_needed:
sys.stdout.write("=" * (ticks_needed-self.ticks))
sys.stdout.flush()
self.ticks = ticks_needed
if complete == 1.0:
sys.stdout.write("\n")
pid = os.getpid()
directory = f"standalone{pid}"
set_device('cpp_standalone', directory=directory, build_on_run=False)
prefs.devices.cpp_standalone.extra_make_args_unix = ['-j1']
N = 2
Vr = -65*mV
theta = -40*mV
tau_v = args.tauv*ms
tau_g = args.taug*ms
delay = 0*ms
ref = args.ref*ms
duration = args.T*second
J = 2e-2
ffwd_J = args.f
freq = args.u*kHz
muext = 25*mV
sigmaext = 1*mV
E_Na = 0*mV
eqs = """
dV/dt = (-(V-Vr) - g*(V-E_Na))/tau_v : volt (unless refractory)
dg/dt = -g/tau_g : 1
"""
# %%
start_scope()
group = NeuronGroup(N, eqs, threshold='V>theta',
reset='V=Vr', refractory=ref, method='euler')
group.V = Vr
group.g = 0.
conn = Synapses(group, group, on_pre='g += J', delay=delay)
for idx in [(0,1)]: #, (1,2), (0,3), (1,3), (0,4)]:
conn.connect(i=idx[0], j=idx[1])
adjmat = np.eye(2, k=1, dtype=float)
P = PoissonGroup(N, freq, name='ffwd_Poisson')
ffwd_conn = Synapses(P, group, on_pre='g += ffwd_J')
ffwd_conn.connect('i==j')
M = SpikeMonitor(group)
# V = StateMonitor(group, 'V', record=0)
report_func = '''
int remaining = (int)((1-completed)/completed*elapsed+0.5);
if (completed == 0.0)
{
std::cout << "Starting simulation at t=" << start << " s for duration " << duration << " s"<<std::flush;
}
else
{
int barWidth = 70;
std::cout << "\\r[";
int pos = barWidth * completed;
for (int i = 0; i < barWidth; ++i) {
if (i < pos) std::cout << "=";
else if (i == pos) std::cout << ">";
else std::cout << " ";
}
std::cout << "] " << int(completed * 100.0) << "% completed. | "<<int(remaining) <<"s remaining"<<std::flush;
}
'''
if args.verbose:
# for _ in range(10):
# run(duration/10, report=report_func, report_period=1*second)
run(duration, report=ProgressBar(), report_period=1*second)
device.build(directory=directory, compile=True, run=True, debug=False,)
else:
# for _ in range(10):
# run(duration/10)
run(duration)
device.build(directory=directory, compile=True, run=True, debug=False,)
try:
assert M.i.shape[0] > 0
print('\nMfr : ', M.i.shape[0]*1.0/N/duration)
except AssertionError:
print('\nNo spike is generated.')
spk_data = np.vstack((M.t/ms, M.i)).T
# %%
data_out = np.vstack((M.t/ms, M.i)).T
save2bin(
f"LIFp=0.25s={J:.3f}" +\
f"ref={ref/ms:.1f}" +\
f"tauv={tau_v/ms:.1f}" +\
f"taug={tau_g/ms:.1f}" +\
f"f={ffwd_J:.3f}" +\
f"u={freq/kHz:.3f}" +\
"_spike_train.dat", data_out, verbose=True)
save2bin(f"connect_matrix-p=0.250.dat", adjmat)
# %%
# delete tmp folder
sp.run(['rm', '-rf', directory])