.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/EI_clustered_network/network.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_EI_clustered_network_network.py: PyNEST EI-clustered network: Network Class --------------------------------------------- .. only:: html ---- Run this example as a Jupyter notebook: .. card:: :width: 25% :margin: 2 :text-align: center :link: https://lab.ebrains.eu/hub/user-redirect/git-pull?repo=https%3A%2F%2Fgithub.com%2Fnest%2Fnest-simulator-examples&urlpath=lab%2Ftree%2Fnest-simulator-examples%2Fnotebooks%2Fnotebooks%2FEI_clustered_network%2Fnetwork.ipynb&branch=main :link-alt: JupyterHub service .. image:: https://nest-simulator.org/TryItOnEBRAINS.png .. grid:: 1 1 1 1 :padding: 0 0 2 0 .. grid-item:: :class: sd-text-muted :margin: 0 0 3 0 :padding: 0 0 3 0 :columns: 4 See :ref:`our guide ` for more information and troubleshooting. ---- ``ClusteredNetwork`` class with functions to build and simulate the EI-clustered network. .. GENERATED FROM PYTHON SOURCE LINES 28-825 .. code-block:: Python import pickle import helper import nest import numpy as np class ClusteredNetwork: """EI-clustered network objeect to build and simulate the network. Provides functions to create neuron populations, stimulation devices and recording devices for an EI-clustered network and setups the simulation in NEST (v3.x). Attributes ---------- _params: dict Dictionary with parameters used to construct network. _populations: list List of neuron population groups. _recording_devices: list List of recording devices. _currentsources: list List of current sources. _model_build_pipeline: list List of functions to build the network. """ def __init__(self, sim_dict, net_dict, stim_dict): """Initialize the ClusteredNetwork object. Parameters are given and explained in the files network_params.py, sim_params.py and stimulus_params.py. Parameters ---------- sim_dict: dict Dictionary with simulation parameters. net_dict: dict Dictionary with network parameters. stim_dict: dict Dictionary with stimulus parameters. """ # merge dictionaries of simulation, network and stimulus parameters self._params = {**sim_dict, **net_dict, **stim_dict} # list of neuron population groups [E_pops, I_pops] self._populations = [] self._recording_devices = [] self._currentsources = [] self._model_build_pipeline = [ self.setup_nest, self.create_populations, self.create_stimulation, self.create_recording_devices, self.connect, ] if self._params["clustering"] == "weight": jep = self._params["rep"] jip = 1.0 + (jep - 1) * self._params["rj"] self._params["jplus"] = np.array([[jep, jip], [jip, jip]]) elif self._params["clustering"] == "probabilities": pep = self._params["rep"] pip = 1.0 + (pep - 1) ** self._params["rj"] self._params["pplus"] = np.array([[pep, pip], [pip, pip]]) else: raise ValueError("Clustering type not recognized") def setup_nest(self): """Initializes the NEST kernel. Reset the NEST kernel and pass parameters to it. Updates randseed of parameters to the actual used one if none is supplied. """ nest.ResetKernel() nest.set_verbosity("M_WARNING") nest.local_num_threads = self._params.get("n_vp", 4) nest.resolution = self._params.get("dt") self._params["randseed"] = self._params.get("randseed") nest.rng_seed = self._params.get("randseed") def create_populations(self): """Create all neuron populations. n_clusters excitatory and inhibitory neuron populations with the parameters of the network are created. """ # make sure number of clusters and units are compatible if self._params["N_E"] % self._params["n_clusters"] != 0: raise ValueError("N_E must be a multiple of Q") if self._params["N_I"] % self._params["n_clusters"] != 0: raise ValueError("N_E must be a multiple of Q") if self._params["neuron_type"] != "iaf_psc_exp": raise ValueError("Model only implemented for iaf_psc_exp neuron model") if self._params["I_th_E"] is None: I_xE = self._params["I_xE"] # I_xE is the feed forward excitatory input in pA else: I_xE = self._params["I_th_E"] * helper.rheobase_current( self._params["tau_E"], self._params["E_L"], self._params["V_th_E"], self._params["C_m"] ) if self._params["I_th_I"] is None: I_xI = self._params["I_xI"] else: I_xI = self._params["I_th_I"] * helper.rheobase_current( self._params["tau_I"], self._params["E_L"], self._params["V_th_I"], self._params["C_m"] ) E_neuron_params = { "E_L": self._params["E_L"], "C_m": self._params["C_m"], "tau_m": self._params["tau_E"], "t_ref": self._params["t_ref"], "V_th": self._params["V_th_E"], "V_reset": self._params["V_r"], "I_e": I_xE if self._params["delta_I_xE"] == 0 else I_xE * nest.random.uniform(1 - self._params["delta_I_xE"] / 2, 1 + self._params["delta_I_xE"] / 2), "tau_syn_ex": self._params["tau_syn_ex"], "tau_syn_in": self._params["tau_syn_in"], "V_m": self._params["V_m"] if not self._params["V_m"] == "rand" else self._params["V_th_E"] - 20 * nest.random.lognormal(0, 1), } I_neuron_params = { "E_L": self._params["E_L"], "C_m": self._params["C_m"], "tau_m": self._params["tau_I"], "t_ref": self._params["t_ref"], "V_th": self._params["V_th_I"], "V_reset": self._params["V_r"], "I_e": I_xI if self._params["delta_I_xE"] == 0 else I_xI * nest.random.uniform(1 - self._params["delta_I_xE"] / 2, 1 + self._params["delta_I_xE"] / 2), "tau_syn_ex": self._params["tau_syn_ex"], "tau_syn_in": self._params["tau_syn_in"], "V_m": self._params["V_m"] if not self._params["V_m"] == "rand" else self._params["V_th_I"] - 20 * nest.random.lognormal(0, 1), } # iaf_psc_exp allows stochasticity, if not used - don't supply the parameters and use # iaf_psc_exp as deterministic model if (self._params.get("delta") is not None) and (self._params.get("rho") is not None): E_neuron_params["delta"] = self._params["delta"] I_neuron_params["delta"] = self._params["delta"] E_neuron_params["rho"] = self._params["rho"] I_neuron_params["rho"] = self._params["rho"] # create the neuron populations pop_size_E = self._params["N_E"] // self._params["n_clusters"] pop_size_I = self._params["N_I"] // self._params["n_clusters"] E_pops = [ nest.Create(self._params["neuron_type"], n=pop_size_E, params=E_neuron_params) for _ in range(self._params["n_clusters"]) ] I_pops = [ nest.Create(self._params["neuron_type"], n=pop_size_I, params=I_neuron_params) for _ in range(self._params["n_clusters"]) ] self._populations = [E_pops, I_pops] def connect(self): """Connect the excitatory and inhibitory populations with each other in the EI-clustered scheme Raises ------ ValueError If the clustering method is not recognized """ if "clustering" not in self._params or self._params["clustering"] == "weight": self.connect_weight() elif self._params["clustering"] == "probabilities": self.connect_probabilities() else: raise ValueError("Clustering method %s not implemented" % self._params["clustering"]) def connect_probabilities(self): """Connect the clusters with a probability EI-cluster scheme Connects the excitatory and inhibitory populations with each other in the EI-clustered scheme by increasing the probabilities of the connections within the clusters and decreasing the probabilities of the connections between the clusters. The weights are calculated so that the total input to a neuron is balanced. """ # self._populations[0] -> Excitatory population # self._populations[1] -> Inhibitory population N = self._params["N_E"] + self._params["N_I"] # total units # if js are not given compute them so that sqrt(K) spikes equal v_thr-E_L and rows are balanced # if any of the js is nan or not given if self._params.get("js") is None or np.isnan(self._params.get("js")).any(): js = helper.calculate_RBN_weights(self._params) js *= self._params["s"] if self._params["n_clusters"] > 1: pminus = (self._params["n_clusters"] - self._params["pplus"]) / float(self._params["n_clusters"] - 1) else: self._params["pplus"] = np.ones((2, 2)) pminus = np.ones((2, 2)) p_plus = self._params["pplus"] * self._params["baseline_conn_prob"] p_minus = pminus * self._params["baseline_conn_prob"] # Connection probabilities within clusters can exceed 1. In this case, we iteratively split # the connections in multiple synapse populations with probabilities < 1. iterations = np.ones((2, 2), dtype=int) # test if any of the probabilities is larger than 1 if np.any(p_plus > 1): print("The probability of some connections is larger than 1.") print("Pre-splitting the connections in multiple synapse populations:") printoptions = np.get_printoptions() np.set_printoptions(precision=2, floatmode="fixed") print("p_plus:\n", p_plus) print("p_minus:\n", p_minus) for i in range(2): for j in range(2): if p_plus[i, j] > 1: iterations[i, j] = int(np.ceil(p_plus[i, j])) p_plus[i, j] /= iterations[i, j] print("\nPost-splitting the connections in multiple synapse populations:") print("p_plus:\n", p_plus) print("Number of synapse populations:\n", iterations) np.set_printoptions(**printoptions) # define the synapses and connect the populations # Excitatory to excitatory neuron connections j_ee = js[0, 0] / np.sqrt(N) nest.CopyModel("static_synapse", "EE", {"weight": j_ee, "delay": self._params["delay"]}) if self._params["fixed_indegree"]: K_EE_plus = int(p_plus[0, 0] * self._params["N_E"] / self._params["n_clusters"]) print("K_EE+: ", K_EE_plus) K_EE_minus = int(p_minus[0, 0] * self._params["N_E"] / self._params["n_clusters"]) print("K_EE-: ", K_EE_minus) conn_params_EE_plus = { "rule": "fixed_indegree", "indegree": K_EE_plus, "allow_autapses": False, "allow_multapses": True, } conn_params_EE_minus = { "rule": "fixed_indegree", "indegree": K_EE_minus, "allow_autapses": False, "allow_multapses": True, } else: conn_params_EE_plus = { "rule": "pairwise_bernoulli", "p": p_plus[0, 0], "allow_autapses": False, "allow_multapses": True, } conn_params_EE_minus = { "rule": "pairwise_bernoulli", "p": p_minus[0, 0], "allow_autapses": False, "allow_multapses": True, } for i, pre in enumerate(self._populations[0]): for j, post in enumerate(self._populations[0]): if i == j: # same cluster for n in range(iterations[0, 0]): nest.Connect(pre, post, conn_params_EE_plus, "EE") else: nest.Connect(pre, post, conn_params_EE_minus, "EE") # Inhibitory to excitatory neuron connections j_ei = js[0, 1] / np.sqrt(N) nest.CopyModel("static_synapse", "EI", {"weight": j_ei, "delay": self._params["delay"]}) if self._params["fixed_indegree"]: K_EI_plus = int(p_plus[0, 1] * self._params["N_I"] / self._params["n_clusters"]) print("K_EI+: ", K_EI_plus) K_EI_minus = int(p_minus[0, 1] * self._params["N_I"] / self._params["n_clusters"]) print("K_EI-: ", K_EI_minus) conn_params_EI_plus = { "rule": "fixed_indegree", "indegree": K_EI_plus, "allow_autapses": False, "allow_multapses": True, } conn_params_EI_minus = { "rule": "fixed_indegree", "indegree": K_EI_minus, "allow_autapses": False, "allow_multapses": True, } else: conn_params_EI_plus = { "rule": "pairwise_bernoulli", "p": p_plus[0, 1], "allow_autapses": False, "allow_multapses": True, } conn_params_EI_minus = { "rule": "pairwise_bernoulli", "p": p_minus[0, 1], "allow_autapses": False, "allow_multapses": True, } for i, pre in enumerate(self._populations[1]): for j, post in enumerate(self._populations[0]): if i == j: # same cluster for n in range(iterations[0, 1]): nest.Connect(pre, post, conn_params_EI_plus, "EI") else: nest.Connect(pre, post, conn_params_EI_minus, "EI") # Excitatory to inhibitory neuron connections j_ie = js[1, 0] / np.sqrt(N) nest.CopyModel("static_synapse", "IE", {"weight": j_ie, "delay": self._params["delay"]}) if self._params["fixed_indegree"]: K_IE_plus = int(p_plus[1, 0] * self._params["N_E"] / self._params["n_clusters"]) print("K_IE+: ", K_IE_plus) K_IE_minus = int(p_minus[1, 0] * self._params["N_E"] / self._params["n_clusters"]) print("K_IE-: ", K_IE_minus) conn_params_IE_plus = { "rule": "fixed_indegree", "indegree": K_IE_plus, "allow_autapses": False, "allow_multapses": True, } conn_params_IE_minus = { "rule": "fixed_indegree", "indegree": K_IE_minus, "allow_autapses": False, "allow_multapses": True, } else: conn_params_IE_plus = { "rule": "pairwise_bernoulli", "p": p_plus[1, 0], "allow_autapses": False, "allow_multapses": True, } conn_params_IE_minus = { "rule": "pairwise_bernoulli", "p": p_minus[1, 0], "allow_autapses": False, "allow_multapses": True, } for i, pre in enumerate(self._populations[0]): for j, post in enumerate(self._populations[1]): if i == j: # same cluster for n in range(iterations[1, 0]): nest.Connect(pre, post, conn_params_IE_plus, "IE") else: nest.Connect(pre, post, conn_params_IE_minus, "IE") # Inhibitory to inhibitory neuron connections j_ii = js[1, 1] / np.sqrt(N) nest.CopyModel("static_synapse", "II", {"weight": j_ii, "delay": self._params["delay"]}) if self._params["fixed_indegree"]: K_II_plus = int(p_plus[1, 1] * self._params["N_I"] / self._params["n_clusters"]) print("K_II+: ", K_II_plus) K_II_minus = int(p_minus[1, 1] * self._params["N_I"] / self._params["n_clusters"]) print("K_II-: ", K_II_minus) conn_params_II_plus = { "rule": "fixed_indegree", "indegree": K_II_plus, "allow_autapses": False, "allow_multapses": True, } conn_params_II_minus = { "rule": "fixed_indegree", "indegree": K_II_minus, "allow_autapses": False, "allow_multapses": True, } else: conn_params_II_plus = { "rule": "pairwise_bernoulli", "p": p_plus[1, 1], "allow_autapses": False, "allow_multapses": True, } conn_params_II_minus = { "rule": "pairwise_bernoulli", "p": p_minus[1, 1], "allow_autapses": False, "allow_multapses": True, } for i, pre in enumerate(self._populations[1]): for j, post in enumerate(self._populations[1]): if i == j: # same cluster for n in range(iterations[1, 1]): nest.Connect(pre, post, conn_params_II_plus, "II") else: nest.Connect(pre, post, conn_params_II_minus, "II") def connect_weight(self): """Connect the clusters with a weight EI-cluster scheme Connects the excitatory and inhibitory populations with each other in the EI-clustered scheme by increasing the weights of the connections within the clusters and decreasing the weights of the connections between the clusters. The weights are calculated so that the total input to a neuron is balanced. """ # self._populations[0] -> Excitatory population # self._populations[1] -> Inhibitory population N = self._params["N_E"] + self._params["N_I"] # total units # if js are not given compute them so that sqrt(K) spikes equal v_thr-E_L and rows are balanced # if any of the js is nan or not given if self._params.get("js") is None or np.isnan(self._params.get("js")).any(): js = helper.calculate_RBN_weights(self._params) js *= self._params["s"] # jminus is calculated so that row sums remain constant if self._params["n_clusters"] > 1: jminus = (self._params["n_clusters"] - self._params["jplus"]) / float(self._params["n_clusters"] - 1) else: self._params["jplus"] = np.ones((2, 2)) jminus = np.ones((2, 2)) # define the synapses and connect the populations # Excitatory to excitatory neuron connections j_ee = js[0, 0] / np.sqrt(N) nest.CopyModel( "static_synapse", "EE_plus", { "weight": self._params["jplus"][0, 0] * j_ee, "delay": self._params["delay"], }, ) nest.CopyModel( "static_synapse", "EE_minus", {"weight": jminus[0, 0] * j_ee, "delay": self._params["delay"]}, ) if self._params["fixed_indegree"]: K_EE = int(self._params["baseline_conn_prob"][0, 0] * self._params["N_E"] / self._params["n_clusters"]) print("K_EE: ", K_EE) conn_params_EE = { "rule": "fixed_indegree", "indegree": K_EE, "allow_autapses": False, "allow_multapses": False, } else: conn_params_EE = { "rule": "pairwise_bernoulli", "p": self._params["baseline_conn_prob"][0, 0], "allow_autapses": False, "allow_multapses": False, } for i, pre in enumerate(self._populations[0]): for j, post in enumerate(self._populations[0]): if i == j: # same cluster nest.Connect(pre, post, conn_params_EE, "EE_plus") else: nest.Connect(pre, post, conn_params_EE, "EE_minus") # Inhibitory to excitatory neuron connections j_ei = js[0, 1] / np.sqrt(N) nest.CopyModel( "static_synapse", "EI_plus", { "weight": j_ei * self._params["jplus"][0, 1], "delay": self._params["delay"], }, ) nest.CopyModel( "static_synapse", "EI_minus", {"weight": j_ei * jminus[0, 1], "delay": self._params["delay"]}, ) if self._params["fixed_indegree"]: K_EI = int(self._params["baseline_conn_prob"][0, 1] * self._params["N_I"] / self._params["n_clusters"]) print("K_EI: ", K_EI) conn_params_EI = { "rule": "fixed_indegree", "indegree": K_EI, "allow_autapses": False, "allow_multapses": False, } else: conn_params_EI = { "rule": "pairwise_bernoulli", "p": self._params["baseline_conn_prob"][0, 1], "allow_autapses": False, "allow_multapses": False, } for i, pre in enumerate(self._populations[1]): for j, post in enumerate(self._populations[0]): if i == j: # same cluster nest.Connect(pre, post, conn_params_EI, "EI_plus") else: nest.Connect(pre, post, conn_params_EI, "EI_minus") # Excitatory to inhibitory neuron connections j_ie = js[1, 0] / np.sqrt(N) nest.CopyModel( "static_synapse", "IE_plus", { "weight": j_ie * self._params["jplus"][1, 0], "delay": self._params["delay"], }, ) nest.CopyModel( "static_synapse", "IE_minus", {"weight": j_ie * jminus[1, 0], "delay": self._params["delay"]}, ) if self._params["fixed_indegree"]: K_IE = int(self._params["baseline_conn_prob"][1, 0] * self._params["N_E"] / self._params["n_clusters"]) print("K_IE: ", K_IE) conn_params_IE = { "rule": "fixed_indegree", "indegree": K_IE, "allow_autapses": False, "allow_multapses": False, } else: conn_params_IE = { "rule": "pairwise_bernoulli", "p": self._params["baseline_conn_prob"][1, 0], "allow_autapses": False, "allow_multapses": False, } for i, pre in enumerate(self._populations[0]): for j, post in enumerate(self._populations[1]): if i == j: # same cluster nest.Connect(pre, post, conn_params_IE, "IE_plus") else: nest.Connect(pre, post, conn_params_IE, "IE_minus") # Inhibitory to inhibitory neuron connections j_ii = js[1, 1] / np.sqrt(N) nest.CopyModel( "static_synapse", "II_plus", { "weight": j_ii * self._params["jplus"][1, 1], "delay": self._params["delay"], }, ) nest.CopyModel( "static_synapse", "II_minus", {"weight": j_ii * jminus[1, 1], "delay": self._params["delay"]}, ) if self._params["fixed_indegree"]: K_II = int(self._params["baseline_conn_prob"][1, 1] * self._params["N_I"] / self._params["n_clusters"]) print("K_II: ", K_II) conn_params_II = { "rule": "fixed_indegree", "indegree": K_II, "allow_autapses": False, "allow_multapses": False, } else: conn_params_II = { "rule": "pairwise_bernoulli", "p": self._params["baseline_conn_prob"][1, 1], "allow_autapses": False, "allow_multapses": False, } for i, pre in enumerate(self._populations[1]): for j, post in enumerate(self._populations[1]): if i == j: # same cluster nest.Connect(pre, post, conn_params_II, "II_plus") else: nest.Connect(pre, post, conn_params_II, "II_minus") def create_stimulation(self): """Create a current source and connect it to clusters.""" if self._params["stim_clusters"] is not None: stim_amp = self._params["stim_amp"] # amplitude of the stimulation current in pA stim_starts = self._params["stim_starts"] # list of stimulation start times stim_ends = self._params["stim_ends"] # list of stimulation end times amplitude_values = [] amplitude_times = [] for start, end in zip(stim_starts, stim_ends): amplitude_times.append(start + self._params["warmup"]) amplitude_values.append(stim_amp) amplitude_times.append(end + self._params["warmup"]) amplitude_values.append(0.0) self._currentsources = [nest.Create("step_current_generator")] for stim_cluster in self._params["stim_clusters"]: nest.Connect(self._currentsources[0], self._populations[0][stim_cluster]) nest.SetStatus( self._currentsources[0], { "amplitude_times": amplitude_times, "amplitude_values": amplitude_values, }, ) def create_recording_devices(self): """Creates a spike recorder Create and connect a spike recorder to all neuron populations in self._populations. """ self._recording_devices = [nest.Create("spike_recorder")] self._recording_devices[0].record_to = "memory" all_units = self._populations[0][0] for E_pop in self._populations[0][1:]: all_units += E_pop for I_pop in self._populations[1]: all_units += I_pop nest.Connect(all_units, self._recording_devices[0], "all_to_all") # Spikerecorder def set_model_build_pipeline(self, pipeline): """Set _model_build_pipeline Parameters ---------- pipeline: list ordered list of functions executed to build the network model """ self._model_build_pipeline = pipeline def setup_network(self): """Setup network in NEST Initializes NEST and creates the network in NEST, ready to be simulated. Functions saved in _model_build_pipeline are executed. """ for func in self._model_build_pipeline: func() def simulate(self): """Simulates network for a period of warmup+simtime""" nest.Simulate(self._params["warmup"] + self._params["simtime"]) def get_recordings(self): """Extract spikes from Spikerecorder Extract spikes form the Spikerecorder connected to all populations created in create_populations. Cuts the warmup period away and sets time relative to end of warmup. Ids 1:N_E correspond to excitatory neurons, N_E+1:N_E+N_I correspond to inhibitory neurons. Returns ------- spiketimes: ndarray 2D array [2xN_Spikes] of spiketimes with spiketimes in row 0 and neuron IDs in row 1. """ events = nest.GetStatus(self._recording_devices[0], "events")[0] # convert them to the format accepted by spiketools spiketimes = np.append(events["times"][None, :], events["senders"][None, :], axis=0) spiketimes[1] -= 1 # remove the pre warmup spikes spiketimes = spiketimes[:, spiketimes[0] >= self._params["warmup"]] spiketimes[0] -= self._params["warmup"] return spiketimes def get_parameter(self): """Get all parameters used to create the network. Returns ------- dict Dictionary with all parameters of the network and the simulation. """ return self._params def create_and_simulate(self): """Create and simulate the EI-clustered network. Returns ------- spiketimes: ndarray 2D array [2xN_Spikes] of spiketimes with spiketimes in row 0 and neuron IDs in row 1. """ self.setup_network() self.simulate() return self.get_recordings() def get_firing_rates(self, spiketimes=None): """Calculates the average firing rates of all excitatory and inhibitory neurons. Calculates the firing rates of all excitatory neurons and the firing rates of all inhibitory neurons created by self.create_populations. If spiketimes are not supplied, they get extracted. Parameters ---------- spiketimes: ndarray 2D array [2xN_Spikes] of spiketimes with spiketimes in row 0 and neuron IDs in row 1. Returns ------- tuple[float, float] average firing rates of excitatory (0) and inhibitory (1) neurons (spikes/s) """ if spiketimes is None: spiketimes = self.get_recordings() e_count = spiketimes[:, spiketimes[1] < self._params["N_E"]].shape[1] i_count = spiketimes[:, spiketimes[1] >= self._params["N_E"]].shape[1] e_rate = e_count / float(self._params["N_E"]) / float(self._params["simtime"]) * 1000.0 i_rate = i_count / float(self._params["N_I"]) / float(self._params["simtime"]) * 1000.0 return e_rate, i_rate def set_I_x(self, I_XE, I_XI): """Set DC currents for excitatory and inhibitory neurons Adds DC currents for the excitatory and inhibitory neurons. The DC currents are added to the currents already present in the populations. Parameters ---------- I_XE: float extra DC current for excitatory neurons [pA] I_XI: float extra DC current for inhibitory neurons [pA] """ for E_pop in self._populations[0]: I_e_loc = E_pop.get("I_e") E_pop.set({"I_e": I_e_loc + I_XE}) for I_pop in self._populations[1]: I_e_loc = I_pop.get("I_e") I_pop.set({"I_e": I_e_loc + I_XI}) def get_simulation(self, PathSpikes=None): """Create network, simulate and return results Creates the EI-clustered network and simulates it with the parameters supplied in the object creation. Returns a dictionary with firing rates, timing information (dict) and parameters (dict). If PathSpikes is supplied the spikes get saved to a pickle file. Parameters ---------- PathSpikes: str (optional) Path of file for spiketimes, if None, no file is saved Returns ------- dict Dictionary with firing rates, spiketimes (ndarray) and parameters (dict) """ self.setup_network() self.simulate() spiketimes = self.get_recordings() e_rate, i_rate = self.get_firing_rates(spiketimes) if PathSpikes is not None: with open(PathSpikes, "wb") as outfile: pickle.dump(spiketimes, outfile) return { "e_rate": e_rate, "i_rate": i_rate, "_params": self.get_parameter(), "spiketimes": spiketimes, } .. _sphx_glr_download_auto_examples_EI_clustered_network_network.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: network.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: network.py ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_