def _attr_new_edges(self, edge_list, attributes=None): ''' Generate attributes for newly created edges. ''' num_edges = len(edge_list) if num_edges: attributes = {} if attributes is None else attributes specials = ("weight", "delay", 'distance') for k in attributes.keys(): if k not in self.edge_attributes and k in specials: self._eattr.new_attribute(name=k, value_type="double") # take care of classic attributes bio_weights = False bio_delays = False # distance must come first if self.is_spatial() or "distance" in attributes: prop = attributes.get("distance", None) values = _get_edge_attr(self, edge_list, 'distance', prop, last_edges=True) self._eattr.set_attribute("distance", values, edges=edge_list, last_edges=True) # first check for potential syn_spec if Network if self.is_network(): for syn_param in self.population.syn_spec.values(): bio_weights += ("weight" in syn_param) bio_delays += ("delay" in syn_param) # then weights if bio_weights: syn_spec = self.population.syn_spec mat = csr_matrix((np.repeat(1., num_edges), (edge_list[:, 0], edge_list[:, 1])), (self.population.size, self.population.size)) for name1, g1 in self.population.items(): for name2, g2 in self.population.items(): src_slice = slice(g1.ids[0], g1.ids[-1] + 1) tgt_slice = slice(g2.ids[0], g2.ids[-1] + 1) e12 = mat[src_slice, tgt_slice].nonzero() syn_prop = _get_syn_param(name1, g1, name2, g2, syn_spec, "weight") syn_prop = 1. if syn_prop is None else syn_prop if isinstance(syn_prop, dict): # through set_weights for dict distrib = syn_prop["distribution"] del syn_prop["distribution"] self.set_weights(elist=e12, distribution=distrib, parameters=syn_prop) elif nonstring_container(syn_prop): # otherwise direct attribute set self.set_edge_attribute("weight", values=syn_prop, value_type="double", edges=edge_list) else: self.set_edge_attribute("weight", val=syn_prop, value_type="double", edges=edge_list) elif self.is_weighted() or "weight" in attributes: values = _get_edge_attr(self, edge_list, 'weight', attributes.get("weight", None), last_edges=True) self._eattr.set_attribute("weight", values, edges=edge_list, last_edges=True) # then delay if self.is_network() or "delay" in self.edge_attributes: prop = attributes.get("delay", None) values = _get_edge_attr(self, edge_list, 'delay', prop, last_edges=True) self._eattr.set_attribute("delay", values, edges=edge_list, last_edges=True) for k in attributes.keys(): if k not in specials: if k in self.edge_attributes: values = _get_edge_attr(self, edge_list, k, attributes[k], last_edges=True) self._eattr.set_attribute(k, values, edges=edge_list, last_edges=True) else: raise RuntimeError("Unknown attribute: '" + k + "'.") # take care of potential new attributes if "names" in attributes: num_attr = len(attributes["names"]) for i in range(num_attr): v = attributes["values"][i] if not nonstring_container(v): v = np.repeat(v, self.edge_nb()) self._eattr.new_attribute(attributes["names"][i], attributes["types"][i], values=v)
def make_nest_network(network, send_only=None, use_weights=True): ''' Create a new network which will be filled with neurons and connector objects to reproduce the topology from the initial network. .. versionchanged:: 0.8 Added `send_only` parameter. Parameters ---------- network: :class:`nngt.Network` or :class:`nngt.SpatialNetwork` the network we want to reproduce in NEST. send_only : int, str, or list of str, optional (default: None) Restrict the nodes that are created in NEST to either inhibitory or excitatory neurons `send_only` :math:`\in \{ 1, -1\}` to a group or a list of groups. use_weights : bool, optional (default: True) Whether to use the network weights or default ones (value: 10.). Returns ------- gids : tuple (nodes in NEST) GIDs of the neurons in the network. ''' gids = [] pop = network.population send = list(network.population.keys()) if send_only in (-1, 1): send = [g for g in send if pop[g].neuron_type == send_only] elif isinstance(send_only, str): send = [pop[send_only]] elif nonstring_container(send_only): send = [g for g in send_only] # link NEST Gids to nngt.Network ids as neurons are created num_neurons = network.node_nb() ia_nngt_ids = np.full(num_neurons, -1, dtype=int) ia_nest_gids = np.full(num_neurons, -1, dtype=int) ia_nngt_nest = np.full(num_neurons, -1, dtype=int) current_size = 0 for name in send: group = pop[name] group_size = len(group.ids) if group_size: ia_nngt_ids[current_size:current_size + group_size] = group.ids # clean up neuron_param dict defaults = nest.GetDefaults(group.neuron_model) n_param = { key: val for key, val in group.neuron_param.items() if key in defaults and key != "model" } # create neurons gids_tmp = nest.Create(group.neuron_model, group_size, n_param) idx_nest = ia_nngt_ids[np.arange(current_size, current_size + group_size)] ia_nest_gids[current_size:current_size + group_size] = gids_tmp ia_nngt_nest[idx_nest] = gids_tmp current_size += group_size gids.extend(gids_tmp) # conversions ids/gids network.nest_gid = ia_nngt_nest network._id_from_nest_gid = { gid: idx for (idx, gid) in zip(ia_nngt_ids, ia_nest_gids) } # get all properties as scipy.sparse.csr matrices csr_weights = network.adjacency_matrix(types=False, weights=True) csr_delays = network.adjacency_matrix(types=False, weights=DELAY) cspec = 'one_to_one' for src_name in send: src_group = pop[src_name] syn_sign = src_group.neuron_type # local connectivity matrix and offset to correct neuron id local_csr = csr_weights[src_group.ids, :] min_sidx = np.min(src_group.ids) if len(src_group.ids) > 0 and pop.syn_spec is not None: # check whether custom synapses should be used for tgt_name in send: tgt_group = pop[tgt_name] # get list of targets for each src_ids = local_csr[:, tgt_group.ids].nonzero()[0] src_ids += min_sidx min_tidx = np.min(tgt_group.ids) tgt_ids = local_csr[:, tgt_group.ids].nonzero()[1] tgt_ids += min_tidx if len(tgt_ids) and len(src_ids): # get the synaptic parameters syn_spec = _get_syn_param(src_name, src_group, tgt_name, tgt_group, pop.syn_spec) # using A1 to get data from matrix if use_weights: syn_spec[WEIGHT] = syn_sign *\ csr_weights[src_ids, tgt_ids].A1 else: syn_spec[WEIGHT] = np.repeat(syn_sign, len(tgt_ids)) syn_spec[DELAY] = csr_delays[src_ids, tgt_ids].A1 # check backend with_mpi = nngt.get_config("mpi") if nngt.get_config("backend") == "nngt" and with_mpi: comm = nngt.get_config("mpi_comm") for i in range(comm.Get_size()): sources = comm.bcast(network.nest_gid[src_ids], i) targets = comm.bcast(network.nest_gid[tgt_ids], i) sspec = comm.bcast(syn_spec, i) nest.Connect(sources, targets, syn_spec=sspec, conn_spec=cspec) comm.Barrier() else: nest.Connect(network.nest_gid[src_ids], network.nest_gid[tgt_ids], syn_spec=syn_spec, conn_spec=cspec) elif len(src_group.ids) > 0: # get NEST gids of sources and targets for each edge src_ids = network.nest_gid[local_csr.nonzero()[0] + min_sidx] tgt_ids = network.nest_gid[local_csr.nonzero()[1]] # prepare weights syn_spec = { WEIGHT: np.repeat(syn_sign, len(src_ids)).astype(float) } if use_weights: syn_spec[WEIGHT] *= csr_weights[src_group.ids, :].data syn_spec[DELAY] = csr_delays[src_group.ids, :].data nest.Connect(src_ids, tgt_ids, syn_spec=syn_spec, conn_spec=cspec) return tuple(ia_nest_gids[:current_size])
def make_nest_network(network, send_only=None, weights=True): ''' Create a new network which will be filled with neurons and connector objects to reproduce the topology from the initial network. .. versionchanged:: 0.8 Added `send_only` parameter. Parameters ---------- network: :class:`nngt.Network` or :class:`nngt.SpatialNetwork` the network we want to reproduce in NEST. send_only : int, str, or list of str, optional (default: None) Restrict the nodes that are created in NEST to either inhibitory or excitatory neurons `send_only` :math:`\in \{ 1, -1\}` to a group or a list of groups. weights : bool or str, optional (default: binary edges) Whether edge weights should be considered; if ``None`` or ``False`` then use binary edges; if ``True``, uses the 'weight' edge attribute, otherwise uses any valid edge attribute required. Returns ------- gids : tuple or NodeCollection (nodes in NEST) GIDs of the neurons in the NEST network. ''' gids = _get_nest_gids([]) pop = network.population send = list(network.population.keys()) if send_only in (-1, 1): send = [g for g in send if pop[g].neuron_type == send_only] elif isinstance(send_only, str): send = [pop[send_only]] elif nonstring_container(send_only): send = [g for g in send_only] send = [g for g in send if pop[g].ids] # link NEST Gids to nngt.Network ids as neurons are created num_neurons = network.node_nb() ia_nngt_ids = np.full(num_neurons, -1, dtype=int) ia_nest_gids = np.full(num_neurons, -1, dtype=int) ia_nngt_nest = np.full(num_neurons, -1, dtype=int) current_size = 0 for name in send: group = pop[name] group_size = len(group.ids) if group_size: ia_nngt_ids[current_size:current_size + group_size] = group.ids # clean up neuron_param dict, separate scalar and non-scalar defaults = nest.GetDefaults(group.neuron_model) scalar_param = {} ns_param = {} for key, val in group.neuron_param.items(): if key in defaults and key != "model": if nonstring_container(val) and len(val) == group_size: ns_param[key] = val else: scalar_param[key] = val # create neurons: gids_tmp = nest.Create(group.neuron_model, group_size, scalar_param, _warn=False) # set non-scalar properties for k, v in ns_param.items(): nest.SetStatus(gids_tmp, k, v, _warn=False) # create ids idx_nest = ia_nngt_ids[ np.arange(current_size, current_size + group_size)] ia_nest_gids[current_size:current_size + group_size] = gids_tmp ia_nngt_nest[idx_nest] = gids_tmp current_size += group_size gids += gids_tmp # conversions ids/gids network.nest_gids = ia_nngt_nest network._id_from_nest_gid = { gid: idx for (idx, gid) in zip(ia_nngt_ids, ia_nest_gids) } # get all properties as scipy.sparse.csr matrices csr_weights = network.adjacency_matrix(types=False, weights=weights) csr_delays = network.adjacency_matrix(types=False, weights=DELAY) cspec = 'one_to_one' num_conn = 0 for src_name in send: src_group = pop[src_name] syn_sign = src_group.neuron_type # local connectivity matrix and offset to correct neuron id arr_idx = np.sort(src_group.ids).astype(int) local_csr = csr_weights[arr_idx, :] assert local_csr.shape[1] == network.node_nb() if len(src_group.ids) > 0 and pop.syn_spec is not None: # check whether custom synapses should be used local_tgt_names = [name for name in send if pop[name].ids] for tgt_name in send: tgt_group = pop[tgt_name] # get list of targets for each arr_tgt_idx = np.sort(tgt_group.ids).astype(int) # get non-wero entries (global NNGT ids) keep = local_csr[:, arr_tgt_idx].nonzero() local_tgt_ids = arr_tgt_idx[keep[1]] local_src_ids = arr_idx[keep[0]] if len(local_tgt_ids) and len(local_src_ids): # get the synaptic parameters syn_spec = _get_syn_param( src_name, src_group, tgt_name, tgt_group, pop.syn_spec) # check whether sign must be given or not local_sign = syn_sign if "receptor_type" in syn_spec: if "cond" in tgt_group.neuron_model: # do not specify the sign for conductance-based # multisynapse model local_sign = 1 # using A1 to get data from matrix if weights: syn_spec[WEIGHT] = local_sign *\ csr_weights[local_src_ids, local_tgt_ids].A1 else: syn_spec[WEIGHT] = np.repeat(local_sign, len(tgt_ids)) syn_spec[DELAY] = \ csr_delays[local_src_ids, local_tgt_ids].A1 num_conn += len(local_src_ids) # check backend with_mpi = nngt.get_config("mpi") if nngt.get_config("backend") == "nngt" and with_mpi: comm = nngt.get_config("mpi_comm") for i in range(comm.Get_size()): sources = \ comm.bcast(network.nest_gids[local_src_ids], i) targets = \ comm.bcast(network.nest_gids[local_tgt_ids], i) sspec = comm.bcast(syn_spec, i) nest.Connect(sources, targets, syn_spec=sspec, conn_spec=cspec, _warn=False) comm.Barrier() else: nest.Connect( network.nest_gids[local_src_ids], network.nest_gids[local_tgt_ids], syn_spec=syn_spec, conn_spec=cspec, _warn=False) elif len(src_group.ids) > 0: # get NEST gids of sources and targets for each edge src_ids = network.nest_gids[local_csr.nonzero()[0] + min_sidx] tgt_ids = network.nest_gids[local_csr.nonzero()[1]] # prepare weights syn_spec = { WEIGHT: np.repeat(syn_sign, len(src_ids)).astype(float) } if weights not in {None, False}: syn_spec[WEIGHT] *= csr_weights[src_group.ids, :].data syn_spec[DELAY] = csr_delays[src_group.ids, :].data nest.Connect(src_ids, tgt_ids, syn_spec=syn_spec, conn_spec=cspec, _warn=False) # tell the populaton that the network it describes was sent to NEST network.population._sent_to_nest() return gids