コード例 #1
0
ファイル: graph_interface.py プロジェクト: tfardet/NNGT
    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)
コード例 #2
0
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])
コード例 #3
0
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