def prepare(self): """ Prepare GeNN model. """ self.model = genn_model.GeNNModel( "float", "multi_area_model", code_gen_log_level=genn_wrapper.info, deviceSelectMethod=DeviceSelect_MANUAL, blockSizeSelectMethod=BlockSizeSelect_MANUAL, selectGPUByDeviceID=True, generateEmptyStatePushPull=False, generateExtraGlobalParamPull=False) self.model.dT = self.params['dt'] self.model._model.set_merge_postsynaptic_models(True) self.model.timing_enabled = self.params['timing_enabled'] self.model.default_var_location = genn_wrapper.VarLocation_DEVICE self.model.default_sparse_connectivity_location = genn_wrapper.VarLocation_DEVICE self.model._model.set_seed(self.params['master_seed']) quantile = 0.9999 normal_quantile_cdf = norm.ppf(quantile) # Calculate max delay for ex_delay_sd = self.network.params['delay_params'][ 'delay_e'] * self.network.params['delay_params']['delay_rel'] in_delay_sd = self.network.params['delay_params'][ 'delay_i'] * self.network.params['delay_params']['delay_rel'] max_ex_delay = self.network.params['delay_params']['delay_e'] + ( ex_delay_sd * normal_quantile_cdf) max_in_delay = self.network.params['delay_params']['delay_i'] + ( in_delay_sd * normal_quantile_cdf) self.max_inter_area_delay = max(max_ex_delay, max_in_delay) print("Max inter-area delay:%fms" % self.max_inter_area_delay) # If we should create cortico-cortico connections if not self.network.params['connection_params']['replace_cc']: self.max_intra_area_delay = 0 for target_area in self.areas_simulated: # Loop source area though complete list of areas for source_area in self.network.area_list: if target_area != source_area: # If source_area is part of the simulated network, # connect it to target_area if source_area in self.areas_simulated: v = self.network.params['delay_params'][ 'interarea_speed'] s = self.network.distances[target_area][ source_area] mean_delay = s / v delay_sd = mean_delay * self.network.params[ 'delay_params']['delay_rel'] self.max_intra_area_delay = max( self.max_intra_area_delay, mean_delay + (delay_sd * normal_quantile_cdf)) print("Max intra-area delay:%fms" % self.max_intra_area_delay)
# Set the initial values of variables of the weight update rule # Initialize weights uniformly between 0 and 1 stdp_var_init = { "g": genn_model.init_var("Uniform", { "min": 0.1, "max": 1.0 }), "label": 0.0, } # Initialize label to 0 # Define GeNN model model = genn_model.GeNNModel("float", "speech_recognition") # Add neuron populations num_inp_neurons = 200 num_output_neurons = 10 inp_layer = model.add_neuron_population("input_layer", num_inp_neurons, izk_neuron, izk_params, izk_var_init) neuron_layers = [inp_layer] for i in range(10): neuron_layers.append( model.add_neuron_population("output_neuron_" + str(i), 1, izk_neuron, izk_params, izk_var_init))
# ---------------------------------------------------------------------------- # Model description # ---------------------------------------------------------------------------- # If we should respect CUDA_VISIBLE_DEVICES, # use manual device ID-based device selection (note default is 0) kwargs = {} if args.cuda_visible_devices: kwargs["selectGPUByDeviceID"] = True kwargs["deviceSelectMethod"] = DeviceSelect_MANUAL # If we should use NCCL, turn on flag to generate NCCL reductions if args.use_nccl: kwargs["enableNCCLReductions"] = True model = genn_model.GeNNModel("float", "%s_tonic_classifier_%s" % (args.dataset, name_suffix), **kwargs) model.dT = args.dt model.timing_enabled = args.timing model.batch_size = batch_size model._model.set_seed(args.seed) # Add neuron populations input = model.add_neuron_population("Input", num_input_neurons, "SpikeSourceArray", {}, {"startSpike": None, "endSpike": None}) if args.num_recurrent_alif > 0: recurrent_alif = model.add_neuron_population("RecurrentALIF", args.num_recurrent_alif, eprop.recurrent_alif_model, recurrent_alif_params, recurrent_alif_vars) recurrent_alif.spike_recording_enabled = args.record if args.num_recurrent_lif > 0: recurrent_lif = model.add_neuron_population("RecurrentLIF", args.num_recurrent_lif, eprop.recurrent_lif_model, recurrent_lif_params, recurrent_lif_vars)
# ---------------------------------------------------------------------------- # Model description # ---------------------------------------------------------------------------- if args.backend == "CUDA": kwargs = { "selectGPUByDeviceID": True, "deviceSelectMethod": DeviceSelect_MANUAL } if args.cuda_visible_devices else {} elif args.backend == "SingleThreadedCPU": kwargs = {"userCxxFlagsGNU": "-march=native"} else: kwargs = {} model = genn_model.GeNNModel("float", "%s_tonic_classifier_evaluate_%s" % (args.dataset, name_suffix), backend=args.backend, **kwargs) model.dT = args.dt model.timing_enabled = args.timing model.batch_size = args.batch_size model._model.set_seed(args.seed) # Add neuron populations input = model.add_neuron_population("Input", num_input_neurons, "SpikeSourceArray", {}, { "startSpike": None, "endSpike": None }) if args.num_recurrent_alif > 0:
spike_counts = [len(n) for n in target_poisson_spikes] target_end_spike = np.cumsum(spike_counts) target_start_spike = np.empty_like(target_end_spike) target_start_spike[0] = 0 target_start_spike[1:] = target_end_spike[0:-1] target_spikeTimes = np.hstack(target_poisson_spikes).astype(float) # Set up startSpike and endSpike for custom SpikeSourceArray model ssa_input_init["startSpike"] = start_spike ssa_input_init["endSpike"] = end_spike ########### Build model ################ model = genn_model.GeNNModel("float", "spike_source_array", time_precision="double") model.dT = 1.0 * TIME_FACTOR inp = model.add_neuron_population("inp", 100, ssa_input_model, SSA_INPUT_PARAMS, ssa_input_init) inp.set_extra_global_param("spikeTimes", spikeTimes) output_init['startSpike'] = target_start_spike output_init['endSpike'] = target_end_spike out = model.add_neuron_population("out", 1, output_model, OUTPUT_PARAMS, output_init) out.set_extra_global_param("spikeTimes", target_spikeTimes) inp2out = model.add_synapse_population("inp2out", "DENSE_INDIVIDUALG", genn_wrapper.NO_DELAY, inp, out,
def build_model(name, params, reward_timesteps): model = genn_model.GeNNModel("float", name) model.dT = params["timestep_ms"] model._model.set_merge_postsynaptic_models(True) model._model.set_default_narrow_sparse_ind_enabled(True) if "seed" in params: model._model.set_seed(params["seed"]) model.timing_enabled = params["measure_timing"] # Excitatory model parameters exc_params = {"a": 0.02, "b": 0.2, "c": -65.0, "d": 8.0, "tauD": params["tau_d"], "dStrength": params["dopamine_strength"]} # Excitatory initial state exc_init = {"V": -65.0, "U": -13.0, "D": 0.0} # Inhibitory model parameters inh_params = {"a": 0.1, "b": 0.2, "c": -65.0, "d": 2.0} # Inhibitory initial state inh_init = {"V": -65.0, "U": -13.0} # Static inhibitory synapse initial state inh_syn_init = {"g": params["inh_weight"]} # STDP parameters stdp_params = {"tauPlus": 20.0, "tauMinus": 20.0, "tauC": 1000.0, "tauD": params["tau_d"], "aPlus": 0.1, "aMinus": 0.15, "wMin": 0.0, "wMax": params["max_exc_weight"]} # STDP initial state stdp_init = {"g": params["init_exc_weight"], "c": 0.0} # Fixed probability connector parameters fixed_prob_params = {"prob": params["probability_connection"]} # Create excitatory and inhibitory neuron populations e_pop = model.add_neuron_population("E", params["num_excitatory"], izhikevich_dopamine_model, exc_params, exc_init) i_pop = model.add_neuron_population("I", params["num_inhibitory"], "Izhikevich", inh_params, inh_init) # Turn on zero-copy for spikes if required if params["use_zero_copy"]: e_pop.pop.set_spike_location(genn_wrapper.VarLocation_HOST_DEVICE_ZERO_COPY) i_pop.pop.set_spike_location(genn_wrapper.VarLocation_HOST_DEVICE_ZERO_COPY) # Set dopamine timestep bitmask e_pop.set_extra_global_param("rewardTimesteps", reward_timesteps) # Enable spike recording e_pop.spike_recording_enabled = params["use_genn_recording"] i_pop.spike_recording_enabled = params["use_genn_recording"] # Add synapse population e_e_pop = model.add_synapse_population("EE", "SPARSE_INDIVIDUALG", genn_wrapper.NO_DELAY, "E", "E", izhikevich_stdp_model, stdp_params, stdp_init, {}, {}, "DeltaCurr", {}, {}, genn_model.init_connectivity("FixedProbability", fixed_prob_params)) e_i_pop = model.add_synapse_population("EI", "SPARSE_INDIVIDUALG", genn_wrapper.NO_DELAY, "E", "I", izhikevich_stdp_model, stdp_params, stdp_init, {}, {}, "DeltaCurr", {}, {}, genn_model.init_connectivity("FixedProbability", fixed_prob_params)) model.add_synapse_population("II", "SPARSE_GLOBALG", genn_wrapper.NO_DELAY, "I", "I", "StaticPulse", {}, inh_syn_init, {}, {}, "DeltaCurr", {}, {}, genn_model.init_connectivity("FixedProbability", fixed_prob_params)) model.add_synapse_population("IE", "SPARSE_GLOBALG", genn_wrapper.NO_DELAY, "I", "E", "StaticPulse", {}, inh_syn_init, {}, {}, "DeltaCurr", {}, {}, genn_model.init_connectivity("FixedProbability", fixed_prob_params)) # Return model and populations return model, e_pop, i_pop, e_e_pop, e_i_pop
# # TEST_LIF_PARAMS = {"C": 10.0, # "TauM": 10.0, # "Vrest": -60.0, # "Vreset": -60.0, # "Vthresh": -50.0, # "Ioffset": 0.0, # "TauRefrac": 5.0} """ We're ready to build our model! We define three populations: input, hidden, and output. We make feedforward connections from input to hidden and from hidden to output. We also make feedback connections from output to hidden. """ model = genn_model.GeNNModel(precision="float", model_name=model_name, time_precision="double") model.dT = 1.0 * TIME_FACTOR inp = model.add_neuron_population("inp", N_INPUT, ssa_input_model, SSA_INPUT_PARAMS, ssa_input_init) inp.set_extra_global_param("spikeTimes", spikeTimes) hid = model.add_neuron_population("hid", N_HIDDEN, hidden_model, HIDDEN_PARAMS, hidden_init) out = model.add_neuron_population("out", N_OUTPUT, output_model_classification, OUTPUT_PARAMS, output_init_classification) inp2hid = model.add_synapse_population("inp2hid", "DENSE_INDIVIDUALG", genn_wrapper.NO_DELAY, inp, hid,
""", pre_spike_code=""" scalar dt = $(t) - $(sT_pre); $(preTrace) = ($(preTrace) * exp(-dt / $(tauPlus))) + 1.0; """, post_spike_code=""" scalar dt = $(t) - $(sT_post); $(postTrace) = ($(postTrace) * exp(-dt / $(tauMinus))) + 1.0; """, is_pre_spike_time_required=True, is_post_spike_time_required=True) # ---------------------------------------------------------------------------- # Network creation # ---------------------------------------------------------------------------- model = genn_model.GeNNModel("float", "hpc_benchmark") model.dT = DT_MS model._model.set_merge_postsynaptic_models(True) model._model.set_default_narrow_sparse_ind_enabled(True) model.timing_enabled = MEASURE_TIMING model.default_var_location = genn_wrapper.VarLocation_DEVICE model.default_sparse_connectivity_location = genn_wrapper.VarLocation_DEVICE # LIF neuron model parameters and initial state lif_params = { "C": C_M_PF / 1000.0, "TauM": TAU_M, "Vrest": 0.0, "Vreset": 0.0, "Vthresh": V_THRESH, "Ioffset": 0.0,
# Calculate spike times pre_phase = [ START_TIME + d + 1.0 if d > 0 else START_TIME + 1.0 for d in DELTA_T ] post_phase = [START_TIME if d > 0 else START_TIME - d for d in DELTA_T] pre_stim_spike_times = np.concatenate([ p + np.arange(0, TIME_BETWEEN_PAIRS * NUM_SPIKES, TIME_BETWEEN_PAIRS) for p in pre_phase ]) post_stim_spike_times = np.concatenate([ p + np.arange(0, TIME_BETWEEN_PAIRS * NUM_SPIKES, TIME_BETWEEN_PAIRS) for p in post_phase ]) # Create model using single-precion and 1ms timesteps model = genn_model.GeNNModel("float", "stdp_curve_pygenn") model.dT = 1.0 # Add a neuron population and two spike sources to provide pre and postsynaptic stimuli neuron_pop = model.add_neuron_population("Pop", NUM_NEURONS, "LIF", lif_params, lif_init) pre_stim_pop = model.add_neuron_population("PreStim", NUM_NEURONS, "SpikeSourceArray", {}, stim_init) post_stim_pop = model.add_neuron_population("PostStim", NUM_NEURONS, "SpikeSourceArray", {}, stim_init) # Set spike source spike times pre_stim_pop.set_extra_global_param("spikeTimes", pre_stim_spike_times) post_stim_pop.set_extra_global_param("spikeTimes", post_stim_spike_times) # Add STDP connection between presynaptic spike source and neurons
import numpy as np import matplotlib.pyplot as plt from pygenn import genn_wrapper, genn_model model = genn_model.GeNNModel("float", "tutorial2_pygenn") model.dT = 1.0 izk_params = {"a": 0.02, "b": 0.2, "c": -65.0, "d": 8.0} izk_init = {"V": -65.0, "U": genn_model.init_var("Uniform", {"min": 0.0, "max": 20.0})} stim_params = {"amp": 4.0} exc_syn_init = {"g": 0.05} inh_syn_init = {"g": -0.25} fixed_prob = {"prob": 0.1} exc = model.add_neuron_population("Exc", 8000, "Izhikevich", izk_params, izk_init) inh = model.add_neuron_population("Inh", 2000, "Izhikevich", izk_params, izk_init) model.add_current_source("ExcStim", "DC", "Exc", stim_params, {}) model.add_current_source("InhStim", "DC", "Inh", stim_params, {}) model.add_synapse_population("Exc_Exc", "SPARSE_GLOBALG", genn_wrapper.NO_DELAY, exc, exc, "StaticPulse", {}, exc_syn_init, {}, {}, "DeltaCurr", {}, {}, genn_model.init_connectivity("FixedProbabilityNoAutapse", fixed_prob)) model.add_synapse_population("Exc_Inh", "SPARSE_GLOBALG", genn_wrapper.NO_DELAY,
stdp_init = { "g": genn_model.init_var("Uniform", { "min": 0.0, "max": g_max }), "eta": eta } stdp_params = {"tauMinus": 20.0, "gMax": g_max, "Xtar": x_tar, "mu": mu} stdp_pre_init = {"Xpre": 0.0} # ******************************************************************************** # Model Instances # ******************************************************************************** model = genn_model.GeNNModel("float", "mnist") # Neuron populations poisson_pop = model.add_neuron_population("poisson_pop", n_input, poisson_model, {}, { 'rate': 100.0, 'timeStepToSpike': 0.0 }) lif_e_pop = model.add_neuron_population("lif_e_pop", n_e, lif_e_model, lif_e_params, lif_e_init) lif_i_pop = model.add_neuron_population("lif_i_pop", n_i, lif_i_model, lif_i_params, lif_i_init) syn_pe_pop = model.add_synapse_population("syn_pe_pop", "DENSE_INDIVIDUALG",
hidden_output_weight_dist_params = {"mean": 0.0, "sd": W0 / np.sqrt(float(NUM_HIDDEN)), "min": W_MIN, "max": W_MAX} hidden_output_init_vars = {"w": genn_model.init_var("NormalClipped", hidden_output_weight_dist_params), "e": 0.0, "lambda": 0.0, "m": 0.0} # ---------------------------------------------------------------------------- # Custom update initialisation # ---------------------------------------------------------------------------- r_max_prop_params = {"updateTime": UPDATE_TIME_MS, "tauRMS": TAU_RMS_MS, "epsilon": EPSILON, "wMin": W_MIN, "wMax": W_MAX} # ---------------------------------------------------------------------------- # Model description # ---------------------------------------------------------------------------- model = genn_model.GeNNModel("float", "superspike_demo", generateLineInfo=True) model.dT = TIMESTEP_MS model.timing_enabled = TIMING # Add neuron populations input = model.add_neuron_population("Input", NUM_INPUT, "SpikeSourceArray", {}, input_init_vars) hidden = model.add_neuron_population("Hidden", NUM_HIDDEN, hidden_neuron_model, hidden_params, hidden_init_vars) output = model.add_neuron_population("Output", NUM_OUTPUT, output_neuron_model, output_params, output_init_vars) input.set_extra_global_param("spikeTimes", input_spikes) output.set_extra_global_param("spikeTimes", target_spikes["time"]) # Turn on recording
poisson_spikes = [] dt = 1.0 rate = 10.0 isi = 1000.0 / (rate * dt) for p in range(100): time = 0.0 neuron_spikes = [] while True: time += expon.rvs(1) * isi if time >= 500.0: break else: neuron_spikes.append(time) poisson_spikes.append(neuron_spikes) model = genn_model.GeNNModel("float", "ssa") model.dT = dt # Count spikes each neuron should emit spike_counts = [len(n) for n in poisson_spikes] # Get start and end indices of each spike sources section end_spike = np.cumsum(spike_counts) start_spike = np.empty_like(end_spike) start_spike[0] = 0 start_spike[1:] = end_spike[0:-1] # Build model model = genn_model.GeNNModel("float", "spike_source_array") model.dT = dt
threshold_condition_code= "$(startSpike) != $(endSpike) && $(t)>= $(spikeTimes)[$(startSpike)]", extra_global_params=[("spikeTimes", "scalar*")], is_auto_refractory_required=False) SSA_INPUT_PARAMS = {"t_rise": 5, "t_decay": 10} ssa_input_init = { "startSpike": start_spike, "endSpike": end_spike, "z": 0.0, "z_tilda": 0.0 } model = genn_model.GeNNModel(precision="float", model_name=model_name_build, time_precision="double") model.dT = 1.0 * TIME_FACTOR inp = model.add_neuron_population("inp", N_INPUT, ssa_input_model, SSA_INPUT_PARAMS, ssa_input_init) inp.set_extra_global_param("spikeTimes", spikeTimes) hid = model.add_neuron_population("hid", N_HIDDEN, hidden_model, HIDDEN_PARAMS, hidden_init) output_init['startSpike'] = target_start_spike output_init['endSpike'] = target_end_spike out = model.add_neuron_population("out", N_OUTPUT, output_model, OUTPUT_PARAMS, output_init) out.set_extra_global_param("spikeTimes", target_spikeTimes)
# test_start_spike[1:] = test_end_spike[0:-1] # # test_spikeTimes = np.hstack(test_poisson_spikes).astype(float) # Set up startSpike and endSpike for custom SpikeSourceArray model ssa_input_init["startSpike"] = start_spike ssa_input_init["endSpike"] = end_spike """ We're ready to build our model! We define three populations: input, hidden, and output. We make feedforward connections from input to hidden and from hidden to output. We also make feedback connections from output to hidden. """ model = genn_model.GeNNModel(precision="float", model_name="xor", time_precision="double") model.dT = 1.0 * TIME_FACTOR inp = model.add_neuron_population("inp", N_INPUT, ssa_input_model, SSA_INPUT_PARAMS, ssa_input_init) inp.set_extra_global_param("spikeTimes", spikeTimes) hid = model.add_neuron_population("hid", N_HIDDEN, hidden_model, HIDDEN_PARAMS, hidden_init) out = model.add_neuron_population("out", N_OUTPUT, output_model_classification, OUTPUT_PARAMS, output_init_classification) inp2hid = model.add_synapse_population("inp2hid", "DENSE_INDIVIDUALG", genn_wrapper.NO_DELAY, inp, hid, superspike_model, SUPERSPIKE_PARAMS, superspike_init, {}, {}, "ExpCurr", {"tau": 5.0}, {})
post_spike_code=""" const scalar dt = $(t) - $(sT_post); $(postTrace) = $(postTrace) * exp(-dt / $(tauMinus)) + 1.0; """, is_pre_spike_time_required=True, is_post_spike_time_required=True) DT = 1.0 NUM_EX_SYNAPSES = 1000 G_MAX = 0.01 DURATION_MS = 300000.0 A_PLUS = 0.01 A_MINUS = 1.05 * A_PLUS model = genn_model.GeNNModel("float", "song") model.dT = DT lif_params = { "C": 0.17, "TauM": 10.0, "Vrest": -74.0, "Vreset": -60.0, "Vthresh": -54.0, "Ioffset": 0.0, "TauRefrac": 1.0 } lif_init = {"V": -60.0, "RefracTime": 0.0} poisson_params = {"rate": 15.0}
mean_input_current += ( get_mean_weight(src_layer, src_pop, layer, pop) * get_full_num_inputs(src_layer, src_pop, layer, pop) * MEAN_FIRING_RATES[src_layer][src_pop]) # Add mean external input current mean_input_current += EXTERNAL_W * NUM_EXTERNAL_INPUTS[layer][ pop] * BACKGROUND_RATE assert mean_input_current >= 0.0 return mean_input_current # ---------------------------------------------------------------------------- # Network creation # ---------------------------------------------------------------------------- model = genn_model.GeNNModel("float", "potjans_microcircuit") model.dT = DT_MS model._model.set_merge_postsynaptic_models(True) model._model.set_default_narrow_sparse_ind_enabled(True) model.timing_enabled = MEASURE_TIMING model.default_var_location = genn_wrapper.VarLocation_DEVICE model.default_sparse_connectivity_location = genn_wrapper.VarLocation_DEVICE lif_init = { "V": genn_model.init_var("Normal", { "mean": -58.0, "sd": 5.0 }), "RefracTime": 0.0 } poisson_init = {"current": 0.0}
def convert(self, tf_model, scaled_tf_weights=None): supported_layers = (tf.keras.layers.Dense, tf.keras.layers.Flatten, tf.keras.layers.Conv2D, tf.keras.layers.AveragePooling2D, tf.keras.layers.Dropout) # Check model compatibility if not isinstance(tf_model, tf.keras.models.Sequential): raise NotImplementedError( 'Implementation for type {} models not found'.format( type(tf_model))) for layer in tf_model.layers[:-1]: if not isinstance(layer, supported_layers): raise NotImplementedError( '{} layers are not supported'.format(layer)) elif isinstance(layer, tf.keras.layers.Dense): if layer.activation != tf.keras.activations.relu: print(layer.activation) raise NotImplementedError( 'Only ReLU activation function is supported') if layer.use_bias == True: raise NotImplementedError( 'TensorFlow model should be trained without bias tensors' ) # create custom classes if_model = genn_model.create_custom_neuron_class( "if_model", param_names=["Vres", "Vthr", "Cm"], var_name_types=[("Vmem", "scalar"), ("SpikeNumber", "unsigned int")], sim_code=""" $(Vmem) += $(Isyn)*(DT / $(Cm)); """, reset_code=""" $(Vmem) = $(Vres); $(SpikeNumber) += 1; """, threshold_condition_code="$(Vmem) >= $(Vthr)") cs_model = genn_model.create_custom_current_source_class( "cs_model", var_name_types=[("magnitude", "scalar")], injection_code=""" $(injectCurrent, $(magnitude)); """) # Params and init dense_if_params = { "Vres": self.Vres, "Vthr": self.Vthr, "Cm": self.dCm } sparse_if_params = { "Vres": self.Vres, "Vthr": self.Vthr, "Cm": self.sCm } if_init = { "Vmem": genn_model.init_var("Uniform", { "min": self.Vres, "max": self.Vthr }), "SpikeNumber": 0 } cs_init = {"magnitude": 10.0} # Fetch augmented weight matrices gw_inds, gw_vals, n_units = self.create_weight_matrices( tf_model, scaled_tf_weights) # Define model and populations self.g_model = genn_model.GeNNModel("float", "g_model") self.neuron_pops = [] self.syn_pops = [] for i, (inds, vals, n) in enumerate(zip(gw_inds, gw_vals, n_units), start=1): if i == 1: # Presynaptic neuron self.neuron_pops.append( self.g_model.add_neuron_population("if" + str(i - 1), n_units[i - 1], if_model, sparse_if_params, if_init)) if inds is None: # Postsynaptic neuron self.neuron_pops.append( self.g_model.add_neuron_population("if" + str(i), n_units[i], if_model, dense_if_params, if_init)) # Synapse self.syn_pops.append( self.g_model.add_synapse_population( "syn" + str(i - 1) + str(i), "DENSE_INDIVIDUALG", genn_wrapper.NO_DELAY, self.neuron_pops[-2], self.neuron_pops[-1], "StaticPulse", {}, {'g': vals}, {}, {}, "DeltaCurr", {}, {})) else: self.neuron_pops.append( self.g_model.add_neuron_population("if" + str(i), n_units[i], if_model, sparse_if_params, if_init)) self.syn_pops.append( self.g_model.add_synapse_population( "syn" + str(i - 1) + str(i), "SPARSE_INDIVIDUALG", genn_wrapper.NO_DELAY, self.neuron_pops[-2], self.neuron_pops[-1], "StaticPulse", {}, {'g': vals}, {}, {}, "DeltaCurr", {}, {})) self.syn_pops[-1].set_sparse_connections(inds[0], inds[1]) self.current_source = self.g_model.add_current_source( "cs", cs_model, "if0", {}, cs_init) self.g_model.dT = self.timestep self.g_model.build() self.g_model.load() return self.g_model, self.neuron_pops, self.current_source