def simulate(tau): b2.start_scope() if standalone_mode: b2.get_device().reinit() b2.get_device().activate(build_on_run=False, directory=directory_name) net = b2.Network() P = b2.PoissonGroup(num_inputs, rates=input_rate) G = b2.NeuronGroup(1, eqs, threshold='v>1', reset='v=0', method='euler') S = b2.Synapses(P, G, on_pre='v += weight') S.connect() M = b2.SpikeMonitor(G) net.add(P) net.add(G) net.add(S) net.add(M) net.run(1000 * b2.ms) if standalone_mode: b2.get_device().build(directory=directory_name, compile=True, run=True, debug=False) return M
def set_in_poisson(self, target): """ Set poissonian input to a group of neurons target: list of targert groups N_p: # of poissons inputs f_p: frequency of P sp: sparseness of connections coef_ep: factor of ep conductance to g_exc """ ## somehow PoissonInput is way slower! also leads to diff behaviour #for gr in target: #inp_poisson = bb.PoissonInput(gr,N=100,rate=f_p, #weight=2.*self.g_ee,state='ge') #self.network.add(inp_poisson) N_p = self.ext_input['N_p'] f_p = self.ext_input['f_p'] sp = self.ext_input['sp'] coef_ep = self.ext_input['coef_ep'] self.P_poisson = bb.PoissonGroup(N_p, f_p, clock=self.network.clock) self.network.add(self.P_poisson) for gr in target: #Cep = bb.Connection(self.P_poisson, gr,'ge', # weight=coef_ep*self.g_ee, sparseness=sp) Cep = bb.Synapses(self.P_poisson, gr, model='w:siemens', pre='ge+=w') Cep.connect(p=sp) Cep.w = coef_ep * self.g_ee self.network.add(Cep)
def main4(plot=True): # what if we want to keep the input spike exactly the same throughout different taus? # Solution: We run PoissonGroup once, store all the spikes, and use the stored spikes across the multiple runs bs.start_scope() num_inputs = 100 input_rate = 10 * bs.Hz w = 0.1 tau_range = bs.linspace(1, 10, 30) * bs.ms output_rates = [] P = bs.PoissonGroup(num_inputs, rates=input_rate) p_monitor = bs.SpikeMonitor(P) one_second = 1 * bs.second """ Note that in the code above, we created Network objects. The reason is that in the loop, if we just called run it would try to simulate all the objects, including the Poisson neurons P, and we only want to run that once. We use Network to specify explicitly which objects we want to include. """ net = bs.Network(P, p_monitor) net.run(one_second) # keeps a copy of the spikes that are generated by the PoissonGroup during that explicit run earlier spikes_i = p_monitor.i spikes_t = p_monitor.t # Construct network that we run each time sgg = bs.SpikeGeneratorGroup(num_inputs, spikes_i, spikes_t) eqs = ''' dv/dt = -v/tau : 1 ''' G = bs.NeuronGroup(1, eqs, threshold='v>1', reset='v=0', method='exact') S = bs.Synapses(sgg, G, on_pre='v += w') S.connect() # fully connected network g_monitor = bs.SpikeMonitor(G) # store the current state of the network net = bs.Network(sgg, G, S, g_monitor) net.store() for tau in tau_range: net.restore() net.run(one_second) output_rates.append(g_monitor.num_spikes / bs.second) if plot: plt.clf() plt.plot(tau_range / bs.ms, output_rates) plt.xlabel(r'$\tau$ (ms)') plt.ylabel('Firing Rate (spikes/s)') # there is much less noise compared to before where we used different PoissonGroup everytime plt.show()
def simulate(tau): # These two lines are needed to start a new standalone simulation: b2.device.reinit() b2.device.activate() eqs = ''' dv/dt = -v/tau : 1 ''' net = b2.Network() P = b2.PoissonGroup(num_inputs, rates=input_rate) G = b2.NeuronGroup(1, eqs, threshold='v>1', reset='v=0', method='euler') S = b2.Synapses(P, G, on_pre='v += weight') S.connect() M = b2.SpikeMonitor(G) net.add([P, G, S, M]) net.run(1000 * b2.ms) return M
def main3(plot=True): # even faster # will not always work # Since there is only single output neuron in the model above, # we can make multiple output neurons and make each time constants a parameter of the grop bs.start_scope() num_inputs = 100 input_rate = 10 * bs.Hz w = 0.1 tau_range = bs.linspace(1, 10, 30) * bs.ms num_tau = len(tau_range) P = bs.PoissonGroup(num_inputs, rates=input_rate) eqs = """ dv/dt = -v/tau : 1 tau : second """ # set output neurons with the same number of taus that you want to try with G = bs.NeuronGroup(num_tau, eqs, threshold='v>1', reset='v=0', method='exact') # set the taus for each individual neurons separately # (didn't know that this was possible) G.tau = tau_range S = bs.Synapses(P, G, on_pre='v += w') S.connect() spike_monitor = bs.SpikeMonitor(G) # Now we can just run once with no loop bs.run(1 * bs.second) # and each counts correspond to neuron with different taus output_rates = spike_monitor.count / bs.second # firing rate is count/duration if plot: plt.plot(tau_range / bs.ms, output_rates) plt.xlabel(r'$\tau$ (ms)') plt.ylabel('Firing rate (sp/s)') plt.show()
def main2(plot=True): # Optimizing the code from main1 by only making the networks just once before the loop # running multiple separate simulations bs.start_scope() num_inputs = 100 input_rate = 10 * bs.Hz weight = 0.1 # range of time constants tau_range = bs.linspace(start=1, stop=10, num=30) * bs.ms # storing output rates output_rates = [] P = bs.PoissonGroup(num_inputs, rates=input_rate) eqs = """ dv/dt = -v/tau : 1 """ G = bs.NeuronGroup(1, eqs, threshold='v>1', reset='v=0', method='exact') # connect the external spike source with the neurons # instead of connecting the same neurons like in previous examples S = bs.Synapses(P, G, on_pre='v += weight') S.connect() # visualise_connectivity(S) spike_monitor = bs.SpikeMonitor(source=G) bs.store() # stores the current state of the network for tau in tau_range: # calling this allows for resetting of the network to its original state bs.restore() bs.run(1 * bs.second) n_spikes = spike_monitor.num_spikes output_rates.append(n_spikes / bs.second) if plot: plt.clf() plt.plot(tau_range / bs.ms, output_rates) plt.xlabel(r'$\tau$ (ms)') plt.ylabel('Firing Rate (spikes/s)') plt.show()
def main1(plot=True): # running multiple separate simulations # this simulation checks to see the effect that different time constant have in LIF neuron firing given poisson spikes bs.start_scope() num_inputs = 100 input_rate = 10 * bs.Hz weight = 0.1 # range of time constants tau_range = bs.linspace(start=1, stop=10, num=30) * bs.ms # storing output rates output_rates = [] for tau in tau_range: # introducing some external spike source P = bs.PoissonGroup(num_inputs, rates=input_rate) eqs = """ dv/dt = -v/tau : 1 """ G = bs.NeuronGroup(1, eqs, threshold='v>1', reset='v=0', method='exact') # connect the external spike source with the neurons # instead of connecting the same neurons like in previous examples S = bs.Synapses(P, G, on_pre='v += weight') S.connect() spike_monitor = bs.SpikeMonitor(source=G) bs.run(1 * bs.second) n_spikes = spike_monitor.num_spikes output_rates.append(n_spikes / bs.second) if plot: plt.plot(tau_range / bs.ms, output_rates) plt.xlabel(r'$\tau$ (ms)') plt.ylabel('Firing Rate (spikes/s)') plt.show()
Apre += dApre * (w_max-w)**mu w = clip(w + Apost, 0, w_max) ''' on_post = ''' Apost += dApost * w**mu w = clip(w + Apre, 0, w_max) ''' N_in = 2000 N_out = 100 N_bins = 100 default_rate = F * (1000 / N_in) postsyn_rates = b2.linspace(0.1, 99, N_out) * b2.Hz if __name__ == '__main__': input_neurons = b2.PoissonGroup(N=N_in, rates=default_rate, name='inputgroup') output_neurons_rates = b2.PoissonGroup(N=N_out, rates=postsyn_rates, name='outputgroup_rates') output_neurons_mu = b2.NeuronGroup(N_out, eqs_neurons, threshold='v>vt', reset='v = vr', method='linear') # output_neurons_mu = b2.PoissonGroup( # N=N_out, # rates=default_rate, # name='outputgroup_mu' # )
def simulate(): common_params = { # Parameters common to all neurons. 'C': 100 * b2.pfarad, 'tau_m': 10. * b2.ms, 'EL': -60 * b2.mV, 'DeltaT': 2 * b2.mV, 'Vreset': -65, # *b2.mV 'VTmean': -50 * b2.mV, 'VTsd': 2 * b2.mV } common_params['gL'] = common_params['C'] / common_params['tau_m'] param_I_syn = { "Erev_x": 0.0 * b2.mV, "Tau_x": 4.0 * b2.ms, "w_x": 1.1, #*b2.nsiemens, # 0.1, "p_x": 1.0, "p_rate": 400. * b2.Hz, } I_cell_params = { 'Ncells': num_I_cells, 'IXmean': 0. * b2.pA, 'IXsd': 0 * b2.pA } eqs = """ VT : volt IX : amp Im = IX + gL * (EL - vm) + gL * DeltaT * exp((vm - VT) / DeltaT) : amp dvm/dt = (Im + I_syn_x) / C : volt ds_x/dt = -s_x / Tau_x : siemens dg_syn_x/dt = (s_x - g_syn_x) / Tau_x : siemens I_syn_x = g_syn_x * (Erev_x - vm): amp """ I_cells = b2.NeuronGroup(I_cell_params['Ncells'], model=eqs, dt=dt0, method=integration_method, threshold="vm > 0.*mV", reset="vm={}*mV".format(common_params['Vreset']), refractory="vm > 0.*mV", namespace={ **common_params, **param_I_syn, }) Poisson_to_I = b2.PoissonGroup(I_cell_params['Ncells'], rates=param_I_syn["p_rate"]) cIX = b2.Synapses( Poisson_to_I, I_cells, # 'w: siemens (shared)' dt=dt0, method=integration_method, on_pre="s_x += {}*nS".format(param_I_syn["w_x"]), ) cIX.connect(i=0, j=0) # Initialise random parameters. I_cells.VT = [common_params['VTmean']] * I_cell_params["Ncells"] I_cells.IX = (randn(len(I_cells)) * I_cell_params['IXsd'] + I_cell_params['IXmean']) I_cells.vm = randn(len(I_cells)) * 10 * b2.mV - 60 * b2.mV spike_monitor_I = b2.SpikeMonitor(I_cells) state_monitor_I = None if record_volrages: state_monitor_I = b2.StateMonitor(I_cells, ["vm", "g_syn_x", "I_syn_x"], record=True, dt=dt0) net = b2.Network(I_cells) if record_volrages: net.add(state_monitor_I) net.add(spike_monitor_I) net.add(cIX) # Randomise initial membrane potentials. print('Simulation running...') start_time = time.time() b2.run(sim_duration * b2.ms) duration = time.time() - start_time print('Simulation time:', duration, 'seconds') return spike_monitor_I, state_monitor_I
weightMatrix = get_matrix_from_file(data_path + 'random/AiAe.npy', n_i, n_e) connections['AiAe'] = b.Synapses(neuron_groups['Ai'], neuron_groups['Ae'], model='w : 1', on_pre='gi_post += w') connections['AiAe'].connect(True) # all-to-all connection connections['AiAe'].w = weightMatrix[connections['AiAe'].i, connections['AiAe'].j] print 'create monitors for Ae' spike_counters['Ae'] = b.SpikeMonitor(neuron_groups['Ae']) #------------------------------------------------------------------------------ # create input population and connections from input populations #------------------------------------------------------------------------------ input_groups['Xe'] = b.PoissonGroup(n_input, 0 * Hz) print 'create connections between X and A' if test_mode: weightMatrix = get_matrix_from_file(data_path + 'weights/XeAe.npy', n_input, n_e) else: weightMatrix = get_matrix_from_file(data_path + 'random/XeAe.npy', n_input, n_e) model = 'w : 1' pre = 'ge_post += w' post = '' if not test_mode: print 'create STDP for connection XeAe' model += eqs_stdp_ee
# round-robin-stimuli-gen.py import brian2 as b import matplotlib.pyplot as plt import numpy as np print("\nLibraries loaded.") b.start_scope() time_per_neuron = 400 * b.ms n_times = 100 n_neurons = 2 freq = 50 * b.Hz P = b.PoissonGroup(1, freq) M = b.SpikeMonitor(P) b.store() print("Simulating-1...", end='', flush=True) spike_times = [] spike_indices = [] start_time = 0 for k in range(n_times): for n in range(n_neurons): b.restore() b.run(time_per_neuron) percentage = 100.0 * (k * n_neurons + n) / (n_times * n_neurons + 0.0) print("\rSimulating-1... t={}%".format(round(percentage, 2)), end='', flush=True)
print('create monitors for', name) rate_monitors[name+'e'] = b2.PopulationRateMonitor(neuron_groups[name+'e']) rate_monitors[name+'i'] = b2.PopulationRateMonitor(neuron_groups[name+'i']) spike_counters[name+'e'] = b2.SpikeMonitor(neuron_groups[name+'e']) if record_spikes: spike_monitors[name+'e'] = b2.SpikeMonitor(neuron_groups[name+'e']) spike_monitors[name+'i'] = b2.SpikeMonitor(neuron_groups[name+'i']) #------------------------------------------------------------------------------ # create input population and connections from input populations #------------------------------------------------------------------------------ pop_values = [0,0,0] for i,name in enumerate(input_population_names): input_groups[name+'e'] = b2.PoissonGroup(n_input, 0*Hz) rate_monitors[name+'e'] = b2.PopulationRateMonitor(input_groups[name+'e']) for name in input_connection_names: print('create connections between', name[0], 'and', name[1]) for connType in input_conn_names: connName = name[0] + connType[0] + name[1] + connType[1] weightMatrix = get_matrix_from_file(weight_path + connName + ending + '.npy') model = 'w : 1' pre = 'g%s_post += w' % connType[0] post = '' if ee_STDP_on: print('create STDP for connection', name[0]+'e'+name[1]+'e') model += eqs_stdp_ee pre += '; ' + eqs_stdp_pre_ee post = eqs_stdp_post_ee
post2before : 1 dpre/dt = -pre/(tc_pre_ee) : 1 (event-driven) dpost1/dt = -post1/(tc_post_1_ee) : 1 (event-driven) dpost2/dt = -post2/(tc_post_2_ee) : 1 (event-driven) ''' eqs_stdp_pre_ee = 'ge+=w; pre = 1.; w = (w>0)*clip(w - nu_ee_pre * post1 , wmin_ee, wmax_ee)' eqs_stdp_post_ee = 'post2before = post2; w = (w>0)*clip(w + nu_ee_post * pre * post2before, wmin_ee, wmax_ee); post1 = 1.; post2 = 1.' #create empty dict neuron_groups = {} connections = {} spike_counters = {} net = {} #create neuron group neuron_groups['X1'] = b.PoissonGroup(n_input, 0 * b.hertz) neuron_groups['A1'] = b.NeuronGroup(neuron_num, neuron_eqs_e, method='euler', threshold=thresh_e, refractory=refrac_e, reset=scr_e) neuron_groups['A1'].v = v_rest_e - 40. * b.mV neuron_groups['A1'].theta = np.ones((neuron_num)) * 20.0 * b.mV #create connections AA start = time.time() weightMatrix = np.zeros((neuron_num, neuron_num)) mark = 0 for kernel in range(kernel_num): feature_map_size = feature_map_size_each_kernel[kernel]
def simulate(IXmean=30. * b2.pA, p_rate=100 * b2.Hz): common_params = { # Parameters common to all neurons. 'C': 100 * b2.pfarad, 'tau_m': 10 * b2.ms, 'EL': -60 * b2.mV, 'DeltaT': 2 * b2.mV, 'Vreset': -65, # *b2.mV 'VTmean': -50 * b2.mV, 'VTsd': 2 * b2.mV } common_params['gL'] = common_params['C'] / common_params['tau_m'] E_cell_params = dict( common_params, **{ 'Ncells': num_E_cells, 'IXmean': IXmean, # 30 'IXsd': 20 * b2.pA }) eqs = Equations(""" Im = IX + gL * (EL - vm) + gL * DeltaT * exp((vm - VT) / DeltaT) - gx * (vm - Erev_x) : amp dgx/dt = -gx/Tau_x : siemens VT : volt IX : amp dvm/dt = Im / C : volt """) param_E_syn = { "Erev_x": 0.0 * b2.mV, "Tau_x": 4.0 * b2.ms, "w_x": 1.4, # *b2.nsiemens, # Peak conductance } if state == "beta": param_E_syn['w_x'] = 0.55 * b2.nS param_E_syn['Tau_x'] = 12 * b2.ms E_cells = b2.NeuronGroup(E_cell_params['Ncells'], model=eqs, method=integration_method, threshold="vm > 0.*mV", reset="vm={}*mV".format(E_cell_params['Vreset']), refractory="vm > 0.*mV", namespace={ **common_params, **param_E_syn, }) Poisson_to_E = b2.PoissonGroup(E_cell_params['Ncells'], rates=p_rate) cEX = b2.Synapses(Poisson_to_E, E_cells, method=integration_method, on_pre="gx += {}*nsiemens".format(param_E_syn["w_x"])) cEX.connect(j='i') # Initialise random parameters. E_cells.VT = E_cell_params['VTmean'] E_cells.IX = E_cell_params['IXmean'] spike_monitor_E = b2.SpikeMonitor(E_cells) state_monitor_E = None if record_voltages: state_monitor_E = b2.StateMonitor(E_cells, "vm", record=True, dt=dt0) net = b2.Network(E_cells) if record_voltages: net.add(state_monitor_E) net.add(spike_monitor_E) net.add(cEX) # Randomise initial membrane potentials. E_cells.vm = -60 * b2.mV print('Simulation running...') start_time = time.time() b2.run(sim_duration) duration = time.time() - start_time print('Simulation time:', duration, 'seconds') return spike_monitor_E, state_monitor_E
if params.stimulus.stim_type == "continuous": Gc.Iswitch = params.stimulus.strength * params.stimulus.input_factor_c Gu.Iswitch = params.stimulus.strength * params.stimulus.input_factor_e Gi.Iswitch = 0 @b2.network_operation(dt=dt) def set_inputs(t): G.Iext = stim[int(10 * (t / b2.ms))] # create external drive fExc = params.drive.fExc * np.ones(Ne) fInh = params.drive.fInh * np.ones(Ni) f = np.concatenate([fExc, fInh]) * b2.Hz P = b2.PoissonGroup(Ntotal, f, dt=dt) Sdrive = b2.Synapses(P, G, model='w:1', pre='IsynE+=w', connect='i==j', dt=dt) Sdrive.w = params.drive.str_factor * psp_to_current(Jee, tauE / tauSynE) print "Wee:" print Wee # initialize neurons np.random.seed(params.simulation.init_seed) r = 0.5 #theta = params.neurons.theta G.theta = params.neurons.theta * (1 + r * (2 * np.random.rand(Ntotal) - 1)) #G.theta = params.neurons.theta reset = params.neurons.reset #G.x = 0.5*np.random.rand(Ntotal)
def simulation( test_mode=True, runname=None, num_epochs=None, progress_interval=None, progress_assignments_window=None, progress_accuracy_window=None, record_spikes=False, monitoring=False, permute_data=False, size=400, resume=False, stdp_rule="original", custom_namespace=None, timer=None, tc_theta=None, total_input_weight=None, use_premade_weights=False, supervised=False, feedback=False, profile=False, clock=None, store=None, **kwargs, ): metadata = get_metadata(store) if not resume: metadata.nseen = 0 metadata.nprogress = 0 if test_mode: random_weights = False use_premade_weights = True ee_STDP_on = False if num_epochs is None: num_epochs = 1 if progress_interval is None: progress_interval = 1000 if progress_assignments_window is None: progress_assignments_window = 0 if progress_accuracy_window is None: progress_accuracy_window = 1000000 else: random_weights = not resume ee_STDP_on = True if num_epochs is None: num_epochs = 3 if progress_interval is None: progress_interval = 1000 if progress_assignments_window is None: progress_assignments_window = 1000 if progress_accuracy_window is None: progress_accuracy_window = 1000 log.info("Brian2STDPMNIST/simulation.py") log.info("Arguments =============") metadata["args"] = record_arguments(currentframe(), locals()) log.info("=======================") # load MNIST training, testing = get_labeled_data() config.classes = np.unique(training["y"]) config.num_classes = len(config.classes) # configuration np.random.seed(0) modulefilename = getframeinfo(currentframe()).filename config.data_path = os.path.dirname(os.path.abspath(modulefilename)) config.random_weight_path = os.path.join(config.data_path, "random/") runpath = os.path.join("runs", runname) config.weight_path = os.path.join(runpath, "weights/") os.makedirs(config.weight_path, exist_ok=True) if test_mode: log.info("Testing run {}".format(runname)) elif resume: log.info("Resuming training run {}".format(runname)) else: log.info("Training run {}".format(runname)) if test_mode: config.output_path = os.path.join(runpath, "output_test/") else: config.output_path = os.path.join(runpath, "output/") os.makedirs(config.output_path, exist_ok=True) if test_mode: data = testing else: data = training if permute_data: sample = np.random.permutation(len(data["y"])) data["x"] = data["x"][sample] data["y"] = data["y"][sample] num_examples = int(len(data["y"]) * num_epochs) n_input = data["x"][0].size n_data = data["y"].size if num_epochs < 1: n_data = int(np.ceil(n_data * num_epochs)) data["x"] = data["x"][:n_data] data["y"] = data["y"][:n_data] # ------------------------------------------------------------------------- # set parameters and equations # ------------------------------------------------------------------------- # log.info('Original defaultclock.dt = {}'.format(str(b2.defaultclock.dt))) if clock is None: clock = 0.5 b2.defaultclock.dt = clock * b2.ms metadata["dt"] = b2.defaultclock.dt log.info("defaultclock.dt = {}".format(str(b2.defaultclock.dt))) n_neurons = { "Ae": size, "Ai": size, "Oe": config.num_classes, "Oi": config.num_classes, "Xe": n_input, "Ye": config.num_classes, } metadata["n_neurons"] = n_neurons single_example_time = 0.35 * b2.second resting_time = 0.15 * b2.second total_example_time = single_example_time + resting_time runtime = num_examples * total_example_time metadata["total_example_time"] = total_example_time input_population_names = ["X"] population_names = ["A"] connection_names = ["XA"] config.save_conns = ["XeAe"] config.plot_conns = ["XeAe"] forward_conntype_names = ["ee"] recurrent_conntype_names = ["ei_rec", "ie_rec"] stdp_conn_names = ["XeAe"] # TODO: add --dc15 option total_weight = {} if total_input_weight is None: total_weight[ "XeAe"] = n_neurons["Xe"] / 10.0 # standard dc15 value was 78.0 else: total_weight["XeAe"] = total_input_weight theta_init = {} if supervised: input_population_names += ["Y"] population_names += ["O"] connection_names += ["YO", "AO"] config.save_conns += ["YeOe", "AeOe"] config.plot_conns += ["AeOe"] stdp_conn_names += ["AeOe"] total_weight["AeOe"] = n_neurons["Ae"] / 5.0 # TODO: refine? theta_init["O"] = 15.0 * b2.mV if feedback: connection_names += ["OA"] config.save_conns += ["OeAe"] config.plot_conns += ["OeAe"] stdp_conn_names += ["OeAe"] total_weight["OeAe"] = n_neurons["Oe"] / 5.0 # TODO: refine? delay = {} # TODO: potentially specify by connName? delay["ee"] = (0 * b2.ms, 10 * b2.ms) delay["ei"] = (0 * b2.ms, 5 * b2.ms) delay["ei_rec"] = (0 * b2.ms, 0 * b2.ms) delay["ie_rec"] = (0 * b2.ms, 0 * b2.ms) input_intensity = 2.0 if test_mode: input_label_intensity = 0.0 else: input_label_intensity = 10.0 initial_weight_matrices = get_initial_weights(n_neurons) # TODO: put all configuration/setup variables in config object # and save to the store for future reference # metadata["config"] = config neuron_groups = {} connections = {} spike_monitors = {} state_monitors = {} network_operations = [] # ------------------------------------------------------------------------- # create network population and recurrent connections # ------------------------------------------------------------------------- for subgroup_n, name in enumerate(population_names): log.info(f"Creating neuron group {name}") subpop_e = name + "e" subpop_i = name + "i" const_theta = False neuron_namespace = {} if name == "A" and tc_theta is not None: neuron_namespace["tc_theta"] = tc_theta * b2.ms if name == "O": neuron_namespace["tc_theta"] = 1e6 * b2.ms if test_mode: const_theta = True if name == "O": # TODO: move to a config variable neuron_namespace["tc_theta"] = 1e5 * b2.ms const_theta = False nge = neuron_groups[subpop_e] = DiehlAndCookExcitatoryNeuronGroup( n_neurons[subpop_e], const_theta=const_theta, timer=timer, custom_namespace=neuron_namespace, ) ngi = neuron_groups[subpop_i] = DiehlAndCookInhibitoryNeuronGroup( n_neurons[subpop_i]) if not random_weights: theta_saved = load_theta(name) if len(theta_saved) != n_neurons[subpop_e]: raise ValueError( f"Requested size of neuron population {subpop_e} " f"({n_neurons[subpop_e]}) does not match size of " f"saved data ({len(theta_saved)})") neuron_groups[subpop_e].theta = theta_saved elif name in theta_init: neuron_groups[subpop_e].theta = theta_init[name] for connType in recurrent_conntype_names: log.info(f"Creating recurrent connections for {connType}") preName = name + connType[0] postName = name + connType[1] connName = preName + postName conn = connections[connName] = DiehlAndCookSynapses( neuron_groups[preName], neuron_groups[postName], conn_type=connType) conn.connect() # all-to-all connection minDelay, maxDelay = delay[connType] if maxDelay > 0: deltaDelay = maxDelay - minDelay conn.delay = "minDelay + rand() * deltaDelay" # TODO: the use of connections with fixed zero weights is inefficient # "random" connections for AeAi is matrix with zero everywhere # except the diagonal, which contains 10.4 # "random" connections for AiAe is matrix with 17.0 everywhere # except the diagonal, which contains zero # TODO: these weights appear to have been tuned, # we may need different values for the O layer weightMatrix = None if use_premade_weights: try: weightMatrix = load_connections(connName, random=random_weights) except FileNotFoundError: log.info( f"Requested premade {'random' if random_weights else ''} " f"weights, but none found for {connName}") if weightMatrix is None: log.info("Using generated initial weight matrices") weightMatrix = initial_weight_matrices[connName] conn.w = weightMatrix.flatten() log.debug(f"Creating spike monitors for {name}") spike_monitors[subpop_e] = b2.SpikeMonitor(nge, record=record_spikes) spike_monitors[subpop_i] = b2.SpikeMonitor(ngi, record=record_spikes) if monitoring: log.debug(f"Creating state monitors for {name}") state_monitors[subpop_e] = b2.StateMonitor( nge, variables=True, record=range(0, n_neurons[subpop_e], 10), dt=0.5 * b2.ms, ) if test_mode and supervised: # make output neurons more sensitive neuron_groups["Oe"].theta = 5.0 * b2.mV # TODO: refine # ------------------------------------------------------------------------- # create TimedArray of rates for input examples # ------------------------------------------------------------------------- input_dt = 50 * b2.ms n_dt_example = int(round(single_example_time / input_dt)) n_dt_rest = int(round(resting_time / input_dt)) n_dt_total = int(n_dt_example + n_dt_rest) input_rates = np.zeros((n_data * n_dt_total, n_neurons["Xe"]), dtype=np.float16) log.info("Preparing input rate stream {}".format(input_rates.shape)) for j in range(n_data): spike_rates = data["x"][j].reshape(n_neurons["Xe"]) / 8 spike_rates *= input_intensity start = j * n_dt_total input_rates[start:start + n_dt_example] = spike_rates input_rates = input_rates * b2.Hz stimulus_X = b2.TimedArray(input_rates, dt=input_dt) total_data_time = n_data * n_dt_total * input_dt # ------------------------------------------------------------------------- # create TimedArray of rates for input labels # ------------------------------------------------------------------------- if "Y" in input_population_names: input_label_rates = np.zeros((n_data * n_dt_total, n_neurons["Ye"]), dtype=np.float16) log.info("Preparing input label rate stream {}".format( input_label_rates.shape)) if not test_mode: label_spike_rates = to_categorical(data["y"], dtype=np.float16) else: label_spike_rates = np.ones(n_data) label_spike_rates *= input_label_intensity for j in range(n_data): start = j * n_dt_total input_label_rates[start:start + n_dt_example] = label_spike_rates[j] input_label_rates = input_label_rates * b2.Hz stimulus_Y = b2.TimedArray(input_label_rates, dt=input_dt) # ------------------------------------------------------------------------- # create input population and connections from input populations # ------------------------------------------------------------------------- for k, name in enumerate(input_population_names): subpop_e = name + "e" # stimulus is repeated for duration of simulation # (i.e. if there are multiple epochs) neuron_groups[subpop_e] = b2.PoissonGroup( n_neurons[subpop_e], rates=f"stimulus_{name}(t % total_data_time, i)") log.debug(f"Creating spike monitors for {name}") spike_monitors[subpop_e] = b2.SpikeMonitor(neuron_groups[subpop_e], record=record_spikes) for name in connection_names: log.info(f"Creating connections between {name[0]} and {name[1]}") for connType in forward_conntype_names: log.debug(f"connType {connType}") preName = name[0] + connType[0] postName = name[1] + connType[1] connName = preName + postName stdp_on = ee_STDP_on and connName in stdp_conn_names nu_factor = 10.0 if name in ["AO"] else None conn = connections[connName] = DiehlAndCookSynapses( neuron_groups[preName], neuron_groups[postName], conn_type=connType, stdp_on=stdp_on, stdp_rule=stdp_rule, custom_namespace=custom_namespace, nu_factor=nu_factor, ) conn.connect() # all-to-all connection minDelay, maxDelay = delay[connType] if maxDelay > 0: deltaDelay = maxDelay - minDelay conn.delay = "minDelay + rand() * deltaDelay" weightMatrix = None if use_premade_weights: try: weightMatrix = load_connections(connName, random=random_weights) except FileNotFoundError: log.info( f"Requested premade {'random' if random_weights else ''} " f"weights, but none found for {connName}") if weightMatrix is None: log.info("Using generated initial weight matrices") weightMatrix = initial_weight_matrices[connName] conn.w = weightMatrix.flatten() if monitoring: log.debug(f"Creating state monitors for {connName}") state_monitors[connName] = b2.StateMonitor( conn, variables=True, record=range(0, n_neurons[preName] * n_neurons[postName], 1000), dt=5 * b2.ms, ) if ee_STDP_on: @b2.network_operation(dt=total_example_time, order=1) def normalize_weights(t): for connName in connections: if connName in stdp_conn_names: # log.debug( # "Normalizing weights for {} " "at time {}".format(connName, t) # ) conn = connections[connName] connweights = np.reshape( conn.w, (len(conn.source), len(conn.target))) colSums = connweights.sum(axis=0) ok = colSums > 0 colFactors = np.ones_like(colSums) colFactors[ok] = total_weight[connName] / colSums[ok] connweights *= colFactors conn.w = connweights.flatten() network_operations.append(normalize_weights) def record_cumulative_spike_counts(t=None): if t is None or t > 0: metadata.nseen += 1 for name in population_names + input_population_names: subpop_e = name + "e" count = pd.DataFrame(spike_monitors[subpop_e].count[:][None, :], index=[metadata.nseen]) count = count.rename_axis("tbin") count = count.rename_axis("neuron", axis="columns") store.append(f"cumulative_spike_counts/{subpop_e}", count) @b2.network_operation(dt=total_example_time, order=0) def record_cumulative_spike_counts_net_op(t): record_cumulative_spike_counts(t) network_operations.append(record_cumulative_spike_counts_net_op) def progress(): log.debug("Starting progress") starttime = time.process_time() labels = get_labels(data) log.info("So far seen {} examples".format(metadata.nseen)) store.append( f"nseen", pd.Series(data=[metadata.nseen], index=[metadata.nprogress])) metadata.nprogress += 1 assignments_window, accuracy_window = get_windows( metadata.nseen, progress_assignments_window, progress_accuracy_window) for name in population_names + input_population_names: log.debug(f"Progress for population {name}") subpop_e = name + "e" csc = store.select(f"cumulative_spike_counts/{subpop_e}") spikecounts_present = spike_counts_from_cumulative( csc, n_data, metadata.nseen, n_neurons[subpop_e], start=-accuracy_window) n_spikes_present = spikecounts_present["count"].sum() if n_spikes_present > 0: spikerates = ( spikecounts_present.groupby("i")["count"].mean().astype( np.float32)) # this reindex no longer necessary? spikerates = spikerates.reindex(np.arange(n_neurons[subpop_e]), fill_value=0) spikerates = add_nseen_index(spikerates, metadata.nseen) store.append(f"rates/{subpop_e}", spikerates) store.flush() fn = os.path.join(config.output_path, "spikerates-summary-{}.pdf".format(subpop_e)) plot_rates_summary(store.select(f"rates/{subpop_e}"), filename=fn, label=subpop_e) if name in population_names: if not test_mode: spikecounts_past = spike_counts_from_cumulative( csc, n_data, metadata.nseen, n_neurons[subpop_e], end=-accuracy_window, atmost=assignments_window, ) n_spikes_past = spikecounts_past["count"].sum() log.debug( "Assignments based on {} spikes".format(n_spikes_past)) if name == "O": assignments = pd.DataFrame({ "label": np.arange(n_neurons[subpop_e], dtype=np.int32) }) else: assignments = get_assignments(spikecounts_past, labels) assignments = add_nseen_index(assignments, metadata.nseen) store.append(f"assignments/{subpop_e}", assignments) else: assignments = store.select(f"assignments/{subpop_e}") if n_spikes_present == 0: log.debug( "No spikes in present interval - skipping accuracy estimate" ) else: log.debug( "Accuracy based on {} spikes".format(n_spikes_present)) predictions = get_predictions(spikecounts_present, assignments, labels) accuracy = get_accuracy(predictions, metadata.nseen) store.append(f"accuracy/{subpop_e}", accuracy) store.flush() accuracy_msg = ( "Accuracy [{}]: {:.1f}% ({:.1f}–{:.1f}% 1σ conf. int.)\n" "{:.1f}% of examples have no prediction\n" "Accuracy excluding non-predictions: " "{:.1f}% ({:.1f}–{:.1f}% 1σ conf. int.)") log.info( accuracy_msg.format(subpop_e, *accuracy.values.flat)) fn = os.path.join(config.output_path, "accuracy-{}.pdf".format(subpop_e)) plot_accuracy(store.select(f"accuracy/{subpop_e}"), filename=fn) fn = os.path.join(config.output_path, "spikerates-{}.pdf".format(subpop_e)) plot_quantity( spikerates, filename=fn, label=f"spike rate {subpop_e}", nseen=metadata.nseen, ) theta = theta_to_pandas(subpop_e, neuron_groups, metadata.nseen) store.append(f"theta/{subpop_e}", theta) fn = os.path.join(config.output_path, "theta-{}.pdf".format(subpop_e)) plot_quantity( theta, filename=fn, label=f"theta {subpop_e} (mV)", nseen=metadata.nseen, ) fn = os.path.join(config.output_path, "theta-summary-{}.pdf".format(subpop_e)) plot_theta_summary(store.select(f"theta/{subpop_e}"), filename=fn, label=subpop_e) if not test_mode or metadata.nseen == 0: for conn in config.save_conns: log.info(f"Saving connection {conn}") conn_df = connections_to_pandas(connections[conn], metadata.nseen) store.append(f"connections/{conn}", conn_df) for conn in config.plot_conns: log.info(f"Plotting connection {conn}") subpop = conn[-2:] if "O" in conn: assignments = None else: try: assignments = store.select( f"assignments/{subpop}", where="nseen == metadata.nseen") assignments = assignments.reset_index("nseen", drop=True) except KeyError: assignments = None fn = os.path.join(config.output_path, "weights-{}.pdf".format(conn)) plot_weights( connections[conn], assignments, theta=None, filename=fn, max_weight=None, nseen=metadata.nseen, output=("O" in conn), feedback=("O" in conn[:2]), label=conn, ) if monitoring: for km, vm in spike_monitors.items(): states = vm.get_states() with open( os.path.join(config.output_path, f"saved-spikemonitor-{km}.pickle"), "wb", ) as f: pickle.dump(states, f) for km, vm in state_monitors.items(): states = vm.get_states() with open( os.path.join(config.output_path, f"saved-statemonitor-{km}.pickle"), "wb", ) as f: pickle.dump(states, f) log.debug("progress took {:.3f} seconds".format(time.process_time() - starttime)) if progress_interval > 0: @b2.network_operation(dt=total_example_time * progress_interval, order=2) def progress_net_op(t): # if t < total_example_time: # return None progress() network_operations.append(progress_net_op) # ------------------------------------------------------------------------- # run the simulation and set inputs # ------------------------------------------------------------------------- log.info("Constructing the network") net = b2.Network() for obj_list in [ neuron_groups, connections, spike_monitors, state_monitors ]: for key in obj_list: net.add(obj_list[key]) for obj in network_operations: net.add(obj) log.info("Starting simulations") net.run(runtime, report="text", report_period=(60 * b2.second), profile=profile) b2.device.build(directory=os.path.join("build", runname), compile=True, run=True, debug=False) if profile: log.debug(b2.profiling_summary(net, 10)) # ------------------------------------------------------------------------- # save results # ------------------------------------------------------------------------- log.info("Saving results") progress() if not test_mode: record_cumulative_spike_counts() save_theta(population_names, neuron_groups) save_connections(connections)
plt.subplot(3, 1, 3) plt.plot(second_mon.t / br.ms, second_mon.v[0], label='2st Neuron') plt.xlabel('Time (ms)') plt.ylabel('2nd Neuron') plt.hlines(y=1, xmin=0, xmax=run_time, color='r', linestyles='dashed') plt.hlines(y=-1, xmin=0, xmax=run_time, color='r', linestyles='dashed') plt.savefig('figures/static.png', bbox_inches='tight') ######## #positive poisson input ######## br.start_scope() P = br.PoissonGroup(no_neurons, poisson_rate * br.Hz) first = br.NeuronGroup(no_neurons, eqs, threshold='v>' + str(threshold_val) + ' or v<-' + str(threshold_val) + '', reset='v = 0', method='euler') second = br.NeuronGroup(no_neurons, eqs, threshold='v>' + str(threshold_val) + ' or v<-' + str(threshold_val) + '', reset='v = 0', method='euler') first.tau = [tau_val] * br.ms
def simulation1(): bs.start_scope() rates = [10, 20, 30] bs.store() train1 = generate_gaussian_spike_train(mean=2.5, std=0.5) train2 = generate_gaussian_spike_train(mean=3, std=1.2) # exit(0) train_len = train1.shape[0] # train_len = 10 total_time = None total_spikes = None for i in range(train_len): r1 = train1[i] r2 = train2[i] place_cell = bs.NeuronGroup(1, model=lif, reset=reset_eq, threshold=threshold_eq, method="euler") place_cell.tau_m = TAU_M place_cell.tau_s = TAU_S place_cell.v = -80.0 * bs.mV print(f"Rates: {r1, r2}") # bs.restore() input = bs.PoissonGroup(2, rates=np.array([r1, r2]) * bs.Hz) # connect input poisson spike generator to the input cells (grid and boundary vector) S1 = bs.Synapses(input, place_cell, on_pre=synaptic_update) S1.connect = S1.connect(i=[0, 1], j=0) step_per_time = 100 place_cell_v_monitor = bs.StateMonitor(place_cell, 'v', record=True, dt=(dt / step_per_time) * bs.second) place_cell_monitor = bs.SpikeMonitor(source=place_cell) bs.run(dt * bs.second) spikes_i = place_cell_monitor.i spikes_t = place_cell_monitor.t print(spikes_i) print(spikes_t) if total_spikes is None: total_spikes = spikes_t / bs.ms else: total_spikes = np.concatenate( [total_spikes, (i * step_per_time) + spikes_t / bs.ms]) print("time", place_cell_v_monitor.t / bs.ms) if total_time is None: total_time = place_cell_v_monitor.t / bs.ms else: total_time = np.concatenate([ total_time, (i * step_per_time) + place_cell_v_monitor.t / bs.ms ]) total_time = interp_based(total_time, N=10) print(type(total_time)) print(total_time.shape) print(total_time) print(total_spikes) plt.figure() _, ind, _ = np.intersect1d(total_time, total_spikes, assume_unique=True, return_indices=True) spikes = np.zeros_like(total_time) spikes[ind] = 1 plt.plot(total_time, spikes) plt.xlabel('Time (ms)') plt.ylabel('v') plt.title(f"Spikes") plt.show()
def bernoulli_poisson(run_time, poisson_rate, threshold_val, tau_val, mu, eqs, spike_size, no_neurons, graph): br.start_scope() P = br.PoissonGroup(no_neurons, poisson_rate * br.Hz) input_neuron = br.NeuronGroup(no_neurons, eqs, threshold='v>0 or v<-0', reset='v = 0', method='euler') first = br.NeuronGroup(no_neurons, eqs, threshold='v>' + str(threshold_val) + ' or v<-' + str(threshold_val) + '', reset='v = 0', method='euler') second = br.NeuronGroup(no_neurons, eqs, threshold='v>' + str(threshold_val) + ' or v<-' + str(threshold_val) + '', reset='v = 0', method='euler') input_neuron.tau = [tau_val] * br.ms first.tau = [tau_val] * br.ms second.tau = [tau_val] * br.ms # Comment these two lines out to see what happens without Synapses # dirak delta function -> exponential decay #find out characteristics -> poisson both ways two dimensional random variable # -> two dimensional two one dimensional # analyuze what this is pass_con = br.Synapses(P, input_neuron, 'w : 1', on_pre='v_post += ' + str(spike_size) + '*sign((randn()+' + str(mu) + '))') S1 = br.Synapses(input_neuron, first, 'w : 1', on_pre='v_post += v_pre/abs(v_pre)*' + str(spike_size)) S2 = br.Synapses(first, second, 'w : 1', on_pre='v_post += v_pre/abs(v_pre)*' + str(spike_size)) #''' #v_post += (v/abs(v))*0.2 : 1 #v = 0 : 1 #''') pass_con.connect(j='i') S1.connect(j='i') S2.connect(j='i') #S.w = '0.3' in_mon = br.StateMonitor(pass_con, 'v', record=True) first_mon = br.StateMonitor(first, 'v', record=True) spikes_of_neuron = br.SpikeMonitor(first) second_mon = br.StateMonitor(second, 'v', record=True) br.run(run_time * br.ms) if graph: plt.clf() plt.subplot(3, 1, 1) plt.plot(in_mon.t / br.ms, in_mon.v[0], label='Input') #plt.xlabel('Time (ms)') plt.ylabel('Input Spike') plt.subplot(3, 1, 2) plt.plot(first_mon.t / br.ms, first_mon.v[0], label='1st Neuron') #plt.xlabel('Time (ms)') plt.ylabel('1st Neuron') plt.hlines(y=1, xmin=0, xmax=run_time, color='r', linestyles='dashed') plt.hlines(y=-1, xmin=0, xmax=run_time, color='r', linestyles='dashed') plt.subplot(3, 1, 3) plt.plot(second_mon.t / br.ms, second_mon.v[0], label='2st Neuron') plt.xlabel('Time (ms)') plt.ylabel('2nd Neuron') plt.hlines(y=1, xmin=0, xmax=run_time, color='r', linestyles='dashed') plt.hlines(y=-1, xmin=0, xmax=run_time, color='r', linestyles='dashed') plt.savefig('figures/double.png', bbox_inches='tight') pos_list = [] neg_list = [] for i in spikes_of_neuron.t: if first_mon.v[0, int(float(i) * 10000)] > 0.1: pos_list.append(i) else: neg_list.append(i) #print(pos_list) #print(neg_list) time_delta_pos = np.diff(np.append([0], list(pos_list))) time_delta_neg = np.diff(np.append([0], list(neg_list))) return [ np.average(time_delta_pos), np.std(time_delta_pos), np.average(time_delta_neg), np.std(time_delta_neg) ]
def simulate(to_file=True): common_params = { # Parameters common to all neurons. 'C': 100*b2.pF, 'tau_m': 10*b2.ms, 'EL': -60*b2.mV, 'DeltaT': 2*b2.mV, 'Vreset': -65, # *b2.mV 'VTmean': -50*b2.mV, 'VTsd': 2*b2.mV, 'delay': 0.*b2.ms, } common_params['gL'] = common_params['C'] / common_params['tau_m'] E_cell_params = dict( common_params, **{ 'Ncells': num_E_cells, 'IXmean': 30. * b2.pA, # 30 'IXsd': 20. * b2.pA }) I_cell_params = dict( common_params, **{ 'Ncells': num_I_cells, 'IXmean': 30. * b2.pA, 'IXsd': 80. * b2.pA, 'p_rate': 400.0 * b2.Hz }) param_I_syn = { "Erev_i": -80.0 * b2.mV, "Erev_x": 0.0 * b2.mV, "Erev_e": 0.0 * b2.mV, "Tau_i": 3.0 * b2.ms, "Tau_e": 4.0 * b2.ms, "Tau_x": 4.0 * b2.ms, "w_i": 1.5, # *b2.nsiemens, # Peak conductance "w_x": 1.1, # *b2.nsiemens, # (0.8 in paper) "w_e": 0.2, # *b2.nsiemens, "p_i": 0.05, "p_e": 0.05, } param_E_syn = { "Erev_i": -80.0 * b2.mV, "Erev_x": 0.0 * b2.mV, "Erev_e": 0.0 * b2.mV, "Tau_i": 3.5 * b2.ms, "Tau_e": 4.0 * b2.ms, "Tau_x": 4.0 * b2.ms, "w_i": 0.6 * b2.nsiemens, # *b2.nsiemens, # Peak conductance "w_x": 1.4 * b2.nsiemens, "w_e": 0.1 * b2.nsiemens, "p_i": 0.1, "p_e": 0.05, } if state == "gamma": print('Gamma oscillation state.') param_I_syn['w_x'] = 0.3 * b2.nS param_I_syn['w_e'] = 0.4 * b2.nS elif state == "beta": param_I_syn['w_x'] = 0.5 * b2.nS param_I_syn['Tau_x'] = 12. * b2.ms param_E_syn['w_x'] = 0.55 * b2.nS param_E_syn['Tau_x'] = 12. * b2.ms param_E_syn['w_e'] = 0.05 * b2.nS param_E_syn['Tau_e'] = 12. * b2.ms param_I_syn['w_e'] = 0.1 * b2.nS param_E_syn['w_i'] = 0.1 * b2.nS param_E_syn['Tau_i'] = 15. * b2.ms param_I_syn['w_i'] = 0.2 * b2.nS param_I_syn['Tau_i'] = 15. * b2.ms eqs = Equations(""" VT : volt IX : amp I_syn_e = g_syn_e * (Erev_e - vm): amp I_syn_i = g_syn_i * (Erev_i - vm): amp I_syn_x = g_syn_x * (Erev_x - vm): amp Im = IX + gL * (EL - vm) + gL * DeltaT * exp((vm - VT) / DeltaT) : amp ds_e/dt = -s_e / Tau_e : siemens dg_syn_e/dt = (s_e - g_syn_e) / Tau_e : siemens ds_i/dt = -s_i / Tau_i : siemens dg_syn_i/dt = (s_i - g_syn_i) / Tau_i : siemens ds_x/dt = -s_x / Tau_x : siemens dg_syn_x/dt = (s_x - g_syn_x) / Tau_x : siemens dvm/dt = (Im + I_syn_e + I_syn_i + I_syn_x) / C : volt """) I_cells = b2.NeuronGroup(I_cell_params['Ncells'], model=eqs, dt=dt0, method=integration_method, threshold="vm > 0.*mV", refractory="vm > 0.*mV", reset="vm={}*mV".format(common_params['Vreset']), namespace={ **common_params, **param_I_syn }) E_cells = b2.NeuronGroup(E_cell_params['Ncells'], model=eqs, dt=dt0, method=integration_method, threshold="vm > 0.*mV", refractory="vm > 0.*mV", reset="vm={}*mV".format(common_params['Vreset']), namespace={ **common_params, **param_E_syn }) # rates = '400.0*(1 + 0.35 * cos(2*pi*sin(2*pi*t/(100*ms)) + pi + 2*pi/N + (1.0*i/N)*2*pi))*Hz' Poisson_to_E = b2.PoissonGroup( E_cell_params['Ncells'], rates='400.0*(1+0.35*cos(2*pi*sin(2*pi*t/({:d}*ms))+pi+' '2*pi/{:d} + (1.0*i/{:d})*2*pi))*Hz'.format(sim_duration, E_cell_params['Ncells'], E_cell_params['Ncells'])) Poisson_to_I = b2.PoissonGroup(I_cell_params['Ncells'], rates=I_cell_params["p_rate"]) # --------------------------------------------------------------- cEE = b2.Synapses(E_cells, E_cells, dt=dt0, delay=common_params['delay'], on_pre='s_e+= {}*nS'.format(param_E_syn['w_e']), namespace={ **common_params, **param_E_syn }) cEE.connect(p="{:g}".format(param_E_syn["p_e"])) #, condition='i!=j' cII = b2.Synapses(I_cells, I_cells, dt=dt0, delay=common_params['delay'], method=integration_method, on_pre='s_i+= {}*nS'.format(param_I_syn['w_i']), namespace={ **common_params, **param_I_syn }) cII.connect(p="{:g}".format(param_I_syn["p_e"])) #, condition='i!=j' cIE = b2.Synapses(E_cells, I_cells, dt=dt0, method=integration_method, on_pre='s_e+={}*nsiemens'.format(param_I_syn["w_e"])) cIE.connect(p=param_I_syn["p_e"]) cEI = b2.Synapses(I_cells, E_cells, dt=dt0, delay=common_params['delay'], method=integration_method, on_pre='s_i+={}*nsiemens'.format(param_I_syn["w_i"])) cEI.connect(p=param_I_syn["p_i"]) cEX = b2.Synapses(Poisson_to_E, E_cells, dt=dt0, delay=common_params['delay'], method=integration_method, on_pre="s_x += {}*nS".format(param_E_syn["w_x"])) cEX.connect(j='i') cIX = b2.Synapses(Poisson_to_I, I_cells, dt=dt0, delay=common_params['delay'], method=integration_method, on_pre="s_x += {}*nS".format(param_I_syn["w_x"])) cIX.connect(j='i') # Initialise random parameters.---------------------------------- E_cells.VT = (randn(len(E_cells)) * common_params['VTsd'] + common_params['VTmean']) I_cells.VT = (randn(len(I_cells)) * common_params['VTsd'] + common_params['VTmean']) E_cells.IX = (randn(len(E_cells)) * E_cell_params['IXsd'] + E_cell_params['IXmean']) I_cells.IX = (randn(len(I_cells)) * I_cell_params['IXsd'] + I_cell_params['IXmean']) I_cells.vm = randn(len(I_cells)) * 10 * b2.mV - 60 * b2.mV E_cells.vm = randn(len(E_cells)) * 10 * b2.mV - 60 * b2.mV spike_mon_E = b2.SpikeMonitor(E_cells) spike_mon_I = b2.SpikeMonitor(I_cells) LFP_E = b2.PopulationRateMonitor(E_cells) LFP_I = b2.PopulationRateMonitor(I_cells) state_monitor_E = state_monitor_I = None if rocord_voltages: state_monitor_E = b2.StateMonitor(E_cells, "vm", record=True, dt=dt0) state_monitor_I = b2.StateMonitor(I_cells, "vm", record=True, dt=dt0) net = b2.Network(E_cells) net.add(I_cells) net.add(spike_mon_E) net.add(spike_mon_I) net.add(LFP_E) net.add(LFP_I) net.add(cEE) net.add(cII) net.add(cEI) net.add(cIE) net.add(cIX) net.add(cEX) if rocord_voltages: net.add(state_monitor_E) net.add(state_monitor_I) # ---------------------------------------------------------------- print('Simulation running...') start_time = time.time() b2.run(sim_duration * b2.ms) duration = time.time() - start_time print('Simulation time:', duration, 'seconds') # ---------------------------------------------------------------- if to_file: to_npz(spike_mon_E, LFP_E, "data/E") to_npz(spike_mon_I, LFP_I, "data/I")
def run_sim(r1, r2, ww, sim_time=250*ms, plot=False): ''' Creates the neural model and runs the simulation. Returns the number of spikes from the LNgen Neuron. Use plot=True to see the behavior of the local neurons as a function of time. ''' b2.start_scope() # Time Constants and reversal potentials have been hardcoded. ln_eqs = ''' dv/dt = ((-80 - v) + ge * (0 - v) + gi * (-80 - v))/(20*ms) : 1 dge/dt = -ge/(5*ms) : 1 dgi/dt = -gi/(10*ms) : 1 ''' LNa = b2.NeuronGroup(1, model=ln_eqs, threshold='v>=-50', reset='v=-60', method='rk4') LNa.v = -80 LNb = b2.NeuronGroup(1, model=ln_eqs, threshold='v>=-50', reset='v=-60', method='rk4') LNb.v = -80 LNgen = b2.NeuronGroup(1, model=ln_eqs, threshold='v>=-50', reset='v=-60', method='rk4') LNgen.v = -80 ORN1 = b2.PoissonGroup(100, r1*Hz) ORN2 = b2.PoissonGroup(100, r2*Hz) s1a = b2.Synapses(ORN1, LNa, 'w : 1 (constant)', on_pre=''' ge_post += w ''') s1a.connect() s1a.w = ww[0] s1a.delay=1*ms s1gen = b2.Synapses(ORN1, LNgen, 'w : 1 (constant)', on_pre=''' ge_post += w ''') s1gen.connect() s1gen.w = ww[1] s1gen.delay=1*ms s2b = b2.Synapses(ORN2, LNb, 'w : 1 (constant)', on_pre=''' ge_post += w ''') s2b.connect() s2b.w = ww[0] s2gen = b2.Synapses(ORN2, LNgen, 'w : 1 (constant)', on_pre=''' ge_post += w ''') s2gen.connect() s2gen.w = ww[1] s2gen.delay=1*ms s_ab = b2.Synapses(LNa, LNb, 'w : 1 (constant)', on_pre=''' gi_post += w ''', on_post=''' gi_pre -= w ''') s_ab.connect() s_ab.w = ww[2] s_a_gen = b2.Synapses(LNa, LNgen, ''' w3 : 1 (constant) w4 : 1 (constant) ''', on_pre=''' gi_post += w4 ''', on_post=''' gi_pre += w3 ''') s_a_gen.connect() s_a_gen.w3 = ww[3] s_a_gen.w4 = ww[4] s_a_gen.delay = '2*ms' s_b_gen = b2.Synapses(LNb, LNgen, ''' w3 : 1 (constant) w4 : 1 (constant) ''', on_pre=''' gi_post += w4 ''', on_post=''' gi_pre += w3 ''') s_b_gen.connect() s_b_gen.w3 = ww[3] s_b_gen.w4 = ww[4] s_a_gen.delay = '2*ms' SM = b2.SpikeMonitor(LNgen) if plot: Mgen = b2.StateMonitor(LNgen, 'v', record=0) Ma = b2.StateMonitor(LNa, 'v', record=0) Mb = b2.StateMonitor(LNb, 'v', record=0) b2.run(sim_time) if plot: plt.plot(Mgen.t/ms, Mgen[0].v, Mgen.t/ms, Ma[0].v, Mgen.t/ms, Mb[0].v) plt.legend(['LNgen', 'LNa', 'LNb']) return(len(SM.t))
def run_network(duration, beta=0.0, w_ee_init=0.1, rate_ext=5, N=5000, save_spikes=True, pre_sim=1, monitor_weights=True, eta=2., plastic=False, tau_p=0.3, kappa=5, tau_c=1, c=0.1, gamma=5.5, spike_rec_ival=20 * 60, output_dir=None, w_ei=1, dt_wmon=10): """ :param duration: length of simulation (in seconds) :param beta: strength of presynaptic inhibition :param w_ee_init: initial weights for E-E connections :param rate_ext: population rate of external Poisson input :param N: total number of neurons :param save_spikes: whether to save spike times (takes memory!) :param pre_sim: simulation length before starting plasticity (in seconds) :param monitor_weights: whether to track E-E weights :param eta: learning rate (scales plasticity time constant) :param plastic: whether E-E weights are plastic :param tau_p: timescale of presynaptic inhibition :param kappa: target rate :param tau_c: timescale of homeostatic control :param c: connection probability :param gamma: E/I balance factor for weights :param spike_rec_ival: interval between recording spikes :param output_dir: directory where to compile the code :param w_ei: scales strength of I->E connection :param dt_wmon: timestep of recording weights (in seconds) Returns spike monitor (Brian object), rate monitor (as numpy array) and weight monitor (as Brian object) """ # ----------------------------- # # Set up brian environment # # ----------------------------- # b2.start_scope() b2.set_device( 'cpp_standalone', build_on_run=False) # ensures code is run in c++ only (speed!) b2.prefs.codegen.cpp.headers += ['"run.h"' ] # This is necessary to use brian_end() b2.prefs.core.default_float_dtype = np.float32 # only used 32 bit floats (memory & speed) # ------------------------------- # # Default network parameters # # ------------------------------- # # paremeters for monitoring the rate dt_rate = 10 * ms # monitor rate every 100 ms tau_rate = 20 * ms # network size dependent parameters N_e = int(N * (4 / 5)) N_i = int(N * (1 / 5)) N_ext = 2 * int(N / 5) # neuron parameters taue = 10 * ms taui = 10 * ms taup = tau_p * 1000 * ms Vt = -50 * mV Vr = -70 * mV taum_e = 20 taum_i = 20 # synaptic weight parameters J = 0.5 # w_ie = we/np.sqrt(c*N_e)*J # w_ei = gamma*we/np.sqrt(c*N_i)*J # w_ii = gamma*we/np.sqrt(c*N_i)*J w_ie = J * mV w_ei = -w_ei * J * gamma * mV w_ii = -J * gamma * mV w_ext = 2 * mV w0 = w_ee_init * mV # initial weight for EE connections w_max = 5 * w0 # maximum weight # GABA spillover and presynaptic inhibition IE_ratefrac = taum_i / taum_e A_GABA = IE_ratefrac / ( c * N_i ) / taui * second # amount of GABA released for every inhibitory spike (indep. of timescale) p_init = np.clip(1 - beta * kappa, 0, 1) if plastic: w0 /= p_init etap = 1 if beta == 0: # disable changes in p if presynaptic inhibition inactive, beta = 0 means psi off etap = 0 # plasticity parameters tauplus = 16.8 * ms tauminus = 33.7 * ms tauslow = 114 * ms Aplus = 6.5 * 10**(-3) # amplitude of potentiation events eta_w = 0 * mV # plasticity is off initially w_min = 0 tau_c = tau_c * 1000 * ms kappa = kappa * Hz pref = Aplus * tauplus * tauslow / ( tauminus * kappa) # prefactor of adaptive depression amplitude term # ------------------------------- # # Model equations in Brian2 # # ------------------------------- # # dynamics for excitatory and inhibitory neurons eqs = ''' dv/dt = ((Vr-v) + g_e + g_i) /taum : volt (unless refractory) dg_e/dt = -g_e/taue : volt dg_i/dt = -g_i/taui : volt dGABA/dt = -GABA/taui: 1 dp/dt = (-p + clip(1-beta*GABA,0,1))*etap/taup : 1 taum : second dzplus/dt = -zplus /tauplus : 1 dzminus/dt = -zminus /tauminus : 1 dnu/dt = -nu/tau_c : Hz ''' neurons = b2.NeuronGroup(N, eqs, threshold='v>Vt', refractory=5 * ms, method='rk4', reset='''v=Vr zplus+=1 zminus+=1 nu+=1/tau_c''') exc_neurons = neurons[:N_e] inh_neurons = neurons[N_e:] # set initial value for single neurons neurons.v = 'Vr + rand() * (Vt - Vr)' neurons.g_e = 'rand()*w_ie' neurons.g_i = 'rand()*w_ii' exc_neurons.taum = taum_e * ms inh_neurons.taum = taum_i * ms neurons.p = p_init neurons.nu = kappa # set target rate # synapse models syn_ee = b2.Synapses( exc_neurons, exc_neurons, # E-E connections are plastic and subject to presynaptic inhibition '''w_ee : volt dzslow/dt = -zslow/tauslow : 1 (event-driven)''', on_pre='''g_e += p*w_ee w_ee -= eta_w*pref*(nu_post**2)*zminus_post w_ee = clip(w_ee,w_min,w_max)''', # depression on_post='''w_ee += eta_w*Aplus*zplus_pre*zslow w_ee = clip(w_ee,w_min,w_max) zslow += 1''', method='euler') # potentiation syn_ie = b2.Synapses(exc_neurons, inh_neurons, on_pre='g_e += w_ie') syn_ei = b2.Synapses(inh_neurons, exc_neurons, on_pre='''g_i += w_ei GABA += A_GABA''' ) # GABA spillover syn_ii = b2.Synapses(inh_neurons, inh_neurons, on_pre='g_i += w_ii') # connection lists for EE, EI, IE and II connections = {} pre_idx, post_idx = create_synapses(N_e, N_e, c, autapse=False) connections['ee'] = np.array([pre_idx, post_idx]) pre_idx, post_idx = create_synapses(N_e, N_i, c) connections['ie'] = np.array([pre_idx, post_idx]) pre_idx, post_idx = create_synapses(N_i, N_e, c) connections['ei'] = np.array([pre_idx, post_idx]) pre_idx, post_idx = create_synapses(N_i, N_i, c, autapse=False) connections['ii'] = np.array([pre_idx, post_idx]) # connect populations using the connection lists syn_ee.connect(i=connections['ee'][0], j=connections['ee'][1]) syn_ee.w_ee = w0 syn_ie.connect(i=connections['ie'][0], j=connections['ie'][1]) syn_ei.connect(i=connections['ei'][0], j=connections['ei'][1]) syn_ii.connect(i=connections['ii'][0], j=connections['ii'][1]) # external input neurons_ext = b2.PoissonGroup(N_ext, rate_ext * Hz) syn_ext = b2.Synapses(neurons_ext, neurons, on_pre='g_e += w_ext') pre_idx, post_idx = create_synapses(N_ext, N, c) syn_ext.connect(i=pre_idx, j=post_idx) # ---------------------------------------------- # # Code to allows interruptions of simulation # # ---------------------------------------------- # # - stops run if network activity is pathologically high # - implementation of stopping function needs to be in C++ @implementation(CPPStandaloneCodeObject, ''' double stop_if_too_high(double rate, double t, double add) { if ((rate > 190) && (t>add+0.5)) { brian_end(); // save all data to disk std::exit(0); } return 0.0; } ''') @implementation('numpy', discard_units=True) @check_units(rate=Hz, t=second, add=1, result=1) def stop_if_too_high(rate, t, add): if rate > 190 * Hz and t > (add + 0.5) * second: b2.stop() # Instantaneous rate is tracked by external population connected to first 1000 neurons instant_rate = b2.NeuronGroup(1, '''rate : Hz drate_mon/dt = -rate_mon/tau_rate : Hz''', threshold='True', reset='rate=0*Hz', method='exact') con = b2.Synapses(exc_neurons[:1000], instant_rate, on_pre='''rate += 1.0/N_incoming/dt rate_mon += 1.0/N_incoming/tau_rate''' ) con.connect() instant_rate.run_regularly('dummy = stop_if_too_high(rate, t, pre_sim)', when='after_synapses') # ------------------- # # Set up monitors # # ------------------- # rate_mon = b2.StateMonitor(instant_rate, 'rate_mon', dt=dt_rate, record=True) spike_mon = 0 # in case simulation is interrupted, spike_mon needs to exist if monitor_weights: wmon = b2.StateMonitor(syn_ee, 'w_ee', record=np.arange(500), dt=dt_wmon * 1000 * ms) # (monitor first 500 weights) else: wmon = 0 # ------------------- # # Start simulation # # ------------------- # # run for some time before plasticity is turned on b2.run(pre_sim * second) # switch plasticity on if plastic: eta_w = eta * mV # if spikes should be monitored - do that in the beginning and end of the simulation only (memory!) if save_spikes: spike_record_interval = np.minimum(spike_rec_ival, duration) b2.run((duration - spike_rec_ival) * second) spike_mon = b2.SpikeMonitor(exc_neurons[:1000]) b2.run(5 * second) spike_mon.active = False b2.run(spike_rec_ival * second) spike_mon.active = True b2.run(5 * second) else: spike_mon = 0 b2.run(duration * second) # this compiles the code and runs it b2.device.build(directory=output_dir, compile=True, run=True, debug=False, clean=True) # postprocessing of raw rate data to numpy array rate_e = np.vstack((np.array(rate_mon.t), np.array(rate_mon.rate_mon))).T rate_i = None # inh rate not monitored return spike_mon, rate_e, wmon
'v : 1 (shared)', threshold= '((v < ratenoised1*dt) and rand() < sqrt(c)) or rand() < ratenoised1*(1 - sqrt(c))*dt' ) noised1.run_regularly('v = rand()') ratenoised2 = noised2pars['rate'] * b2.Hz noised2 = b2.NeuronGroup( noised2pars['num'], 'v : 1 (shared)', threshold= '((v < ratenoised2*dt) and rand() < sqrt(c)) or rand() < ratenoised2*(1 - sqrt(c))*dt' ) noised2.run_regularly('v = rand()') noisestn = b2.PoissonGroup(noisestnpars['num'], rates=noisestnpars['rate'] * b2.Hz) noisegpti = b2.PoissonGroup(noisegptipars['num'], rates=noisegptipars['rate'] * b2.Hz) noisegpta = b2.PoissonGroup(noisegptapars['num'], rates=noisegptapars['rate'] * b2.Hz) noisegpi = b2.PoissonGroup(noisegpipars['num'], rates=noisegpipars['rate'] * b2.Hz) mulval = 0.1 * b2.nsiemens weightnoisefsn = noisefsnpars['weight'] * b2.nsiemens noisetofsn = b2.Synapses(noisefsn, FSN, delay=noisefsnpars['delay'] * b2.ms, model='''k : siemens''', on_pre='g_e += k')
def run_model( N=N, p=p, f=f, N_E=N_E, N_I=N_I, w_plus=w_plus, w_minus=w_minus, N_sub=N_sub, N_non=N_non, C_ext=C_ext, C_E=C_E, C_I=C_I, namespace=namespace, net=None, use_conductance=True, coherence=0.2, stim_on=100 * b2.ms, stim_off=900 * b2.ms, runtime=2 * b2.second, **namespace_kwargs # use for repeated simulations? ): if net is None: b2.start_scope() s_AMPA_initial_ext = namespace['rate_ext'] * C_ext * namespace[ 'tau_AMPA'] # update namespace with computed variables namespace['tau_m_E'] = namespace['C_m_E'] / namespace['g_m_E'] namespace['tau_m_I'] = namespace['C_m_I'] / namespace['g_m_I'] P_E = b2.NeuronGroup( N_E, eqs_conductance_E if use_conductance else eqs_current_E, threshold='v > V_thr', reset='v = V_reset', refractory='tau_rp_E', method='euler', name='P_E') P_E.v = namespace['V_L'] P_E.s_AMPA_ext = s_AMPA_initial_ext # estimated 4.8 P_I = b2.NeuronGroup( N_E, eqs_conductance_I if use_conductance else eqs_current_I, threshold='v > V_thr', reset='v = V_reset', refractory='tau_rp_I', method='euler', name='P_I') P_I.v = namespace['V_L'] P_I.s_AMPA_ext = s_AMPA_initial_ext C_E_E = b2.Synapses( P_E, P_E, model=eqs_glut, # equations for NMDA on_pre=eqs_pre_glut, on_post=eqs_post_glut, method='euler', name='C_E_E') C_E_E.connect('i != j') C_E_E.w[:] = 1.0 for pi in range(N_non, N_non + p * N_sub, N_sub): # internal other subpopulation to current nonselective # brian synapses are i->j C_E_E.w[C_E_E.indices[:, pi:pi + N_sub]] = w_minus # internal current subpopulation to current subpopulation C_E_E.w[C_E_E.indices[pi:pi + N_sub, pi:pi + N_sub]] = w_plus C_E_I = b2.Synapses(P_E, P_I, model=eqs_glut, on_pre=eqs_pre_glut, on_post=eqs_post_glut, method='euler', name='C_E_I') C_E_I.connect() C_E_I.w[:] = 1.0 C_I_I = b2.Synapses(P_I, P_I, on_pre=eqs_pre_gaba, method='euler', name='C_I_I') C_I_I.connect('i != j') C_I_E = b2.Synapses(P_I, P_E, on_pre=eqs_pre_gaba, method='euler', name='C_I_E') C_I_E.connect() C_P_E = b2.PoissonInput(P_E, target_var='s_AMPA_ext', N=C_ext, rate=namespace['rate_ext'], weight=1.) C_P_I = b2.PoissonInput(P_I, target_var='s_AMPA_ext', N=C_ext, rate=namespace['rate_ext'], weight=1.) # TODO: change the stimulus to match the task # C_selection = int(f * C_ext) # rate_selection = 25. * b2.Hz # if 'stimulus1' not in namespace: # stimtimestep = 25 * b2.ms # stimtime = 1 # stimuli1 = b2.TimedArray(np.r_[ # np.zeros(8), np.ones(stimtime), np.zeros(100)], # dt=stimtimestep # ) # namespace['stimuli1'] = stimuli1 # input1 = b2.PoissonInput( # P_E[N_non:N_non + N_sub], # target_var='s_AMPA_ext', # N=C_selection, # rate=rate_selection, # weight='stimuli1(t)' # ) N_input = C_ext increment1 = 0.05 * (1 + coherence) * namespace['rate_ext'] increment2 = 0.05 * (1 - coherence) * namespace['rate_ext'] sigma_rate = 0.05 * namespace['rate_ext'] input1 = b2.PoissonGroup(N_input, rates=0. * b2.Hz) input1_syn = b2.Synapses(input1, P_E[N_non:N_non + N_sub], model='', on_pre='s_AMPA_ext_post += 1') input1_syn.connect() input2 = b2.PoissonGroup(N_input, rates=0. * b2.Hz) input2_syn = b2.Synapses(input2, P_E[N_non + N_sub:N_non + 2 * N_sub], model='', on_pre='s_AMPA_ext_post += 1') input2_syn.connect() @b2.network_operation(dt=50 * b2.ms, when='start') def update_inputs(t): if t < stim_on or t >= stim_off: input1.rates = 0. * b2.Hz input2.rates = 0. * b2.Hz else: input1.rates = (np.random.randn() * sigma_rate + increment1) # input1.rates = increment1 input2.rates = (np.random.randn() * sigma_rate + increment2) # input2.rates = increment2 # ri1 = b2.PopulationRateMonitor(input1_syn, name='ri1') # ri2 = b2.PopulationRateMonitor(input2_syn, name='ri2') r0 = b2.PopulationRateMonitor(P_E[:N_non], name='r0') r1 = b2.PopulationRateMonitor(P_E[N_non:N_non + N_sub], name='r1') r2 = b2.PopulationRateMonitor(P_E[N_non + N_sub:N_non + 2 * N_sub], name='r2') rI = b2.PopulationRateMonitor(P_I, name='rI') net = b2.Network(b2.collect()) net.store('initialised') net.restore('initialised') net.run(duration=runtime, report='stdout', namespace=namespace) return net
#! /usr/bin/python3.7m import brian2 as b from numpy import save import matplotlib.pyplot as plt print("\nLibraries loaded.") b.start_scope() t_max = 100 * b.second f = 10 * b.Hz filename = "/home/ven0m/code/btp/simple-0/stimulus.npy" P = b.PoissonGroup(1, f) M = b.SpikeMonitor(P) def reporter(elapsed, complete, start, duration): print("\rSimulating... {}%".format(round(complete * 100, 2)), end='', flush=True) # run simulation print("Simulating... ", end='', flush=True) b.run(t_max, report=reporter, report_period=t_simul / 100) print("done") print("Saving to '{}'... ".format(filename), end='', flush=True) save(filename, [list(M.t), [0] * M.num_spikes]) print("done")