Esempio n. 1
0
def _compute_connections(num_source,
                         num_target,
                         density,
                         edges,
                         avg_deg,
                         directed,
                         reciprocity=-1):
    assert not np.allclose((density, edges, avg_deg), -1.), "At leat one " +\
        "of the following entries must be specified: 'density', 'edges', " +\
        "'avg_deg'."
    pre_recip_edges = 0
    if avg_deg > 0:
        pre_recip_edges = int(avg_deg * num_source)
    elif edges > 0:
        pre_recip_edges = int(edges)
    else:
        pre_recip_edges = int(density * num_source * num_target)
    dens = pre_recip_edges / float(num_source * num_target)
    edges = pre_recip_edges
    if edges:
        if not directed:
            pre_recip_edges = edges = int(edges / 2)
        elif reciprocity > max(0, (2. - 1. / dens)):
            frac_recip = ((reciprocity - 1. + np.sqrt(1. + dens *
                                                      (reciprocity - 2.))) /
                          (2. - reciprocity))
            if frac_recip < 1.:
                pre_recip_edges = int(edges / (1 + frac_recip))
            else:
                raise InvalidArgument(
                    "Such reciprocity cannot be obtained, request ignored.")
        elif reciprocity > 0.:
            raise InvalidArgument(
                "Reciprocity cannot be lower than 2-1/density.")
    return edges, pre_recip_edges
Esempio n. 2
0
def _check_num_edges(source_ids, target_ids, num_edges, directed, multigraph):
    num_source, num_target = len(source_ids), len(target_ids)
    has_only_one_population = (False if num_source != num_target else
                               not np.all(source_ids - target_ids))
    if not has_only_one_population and not multigraph:
        b_d = (num_edges > num_source * num_target)
        b_nd = (num_edges > int(0.5 * num_source * num_target))
        if (not directed and b_nd) or (directed and b_d):
            raise InvalidArgument("Required number of edges is too high")
    elif has_only_one_population and not multigraph:
        b_d = (num_edges > num_source * (num_target - 1))
        b_nd = (num_edges > int((0.5 * num_source - 1) * num_target))
        if (not directed and b_nd) or (directed and b_d):
            raise InvalidArgument("Required number of edges is too high")
    return has_only_one_population
Esempio n. 3
0
def assortativity(graph, deg_type="in"):
    '''
    Assortativity of the graph.

    Parameters
    ----------
    graph : :class:`~nngt.Graph` or subclass
        Network to analyze.
    deg_type : string, optional (default: 'in')
        Type of degree to take into account (among 'in', 'out' or 'total').

    Returns
    -------
    a float quantifying the graph assortativity.
    '''
    if nngt._config["backend"] == "igraph":
        deg_list = graph.get_degrees(deg_type=deg_type)
        return graph.assortativity(deg_list, directed=graph.is_directed())
        #~ return graph.assortativity(deg_type, directed=graph.is_directed())
    elif nngt._config["backend"] == "graph-tool":
        return nngt.analyze_graph["assortativity"](graph, deg_type)[0]
    else:
        if deg_type == 'total':
            raise InvalidArgument("Cannot use total degree assortativity with "
                                  "`networkx`.")
        return nngt.analyze_graph["assortativity"](graph,
                                                   x=deg_type,
                                                   y=deg_type)
Esempio n. 4
0
def _value_psp(weight, neuron_model, di_param, timestep, simtime):
    nest.ResetKernel()
    nest.SetKernelStatus({"resolution": timestep})
    # create neuron and recorder
    neuron = nest.Create(neuron_model, params=di_param)
    V_rest = nest.GetStatus(neuron)[0]["E_L"]
    nest.SetStatus(neuron, {"V_m": V_rest})
    vm = nest.Create("voltmeter", params={"interval": timestep})
    nest.Connect(vm, neuron)
    # send the initial spike
    sg = nest.Create("spike_generator",
                     params={
                         'spike_times': [timestep],
                         'spike_weights': weight
                     })
    nest.Connect(sg, neuron)
    nest.Simulate(simtime)
    # get the max and its time
    dvm = nest.GetStatus(vm)[0]
    da_voltage = dvm["events"]["V_m"]
    idx = np.argmax(da_voltage)
    if idx == len(da_voltage - 1):
        raise InvalidArgument("simtime too short: PSP maximum is out of range")
    else:
        val = da_voltage[idx] - V_rest
        return val
Esempio n. 5
0
    def set_param(self, param, group=None):
        '''
        Set the groups' parameters.

        Parameters
        ----------
        param : dict
            Dictionary containing the model type as key ("neuron" or "synapse")
            and the model parameter as value (e.g. {"neuron": {"C_m": 125.}}).
        group : list of strings, optional (default: None)
            List of strings containing the names of the groups which models
            should be updated.

        .. warning::
            No check is performed on the validity of the parameters, which
            means that errors will only be detected when building the graph in
            NEST.
        '''
        if group is None:
            group = self.keys()
        try:
            for key, val in param.items():
                for name in group:
                    if key == "neuron":
                        self[name].neuron_param = val
                    elif key == "synapse":
                        self[name].syn_param = val
                    else:
                        raise ValueError(
                            "Model type {} is not valid; choose among 'neuron'"
                            " or 'synapse'.".format(key))
        except:
            raise InvalidArgument(
                "Invalid param dict or group; see docstring.")
Esempio n. 6
0
def _get_psp_list(bins, neuron_model, di_param, timestep, simtime):
    '''
    Return the list of effective weights from a list of NEST connection
    weights.
    '''
    nest.ResetKernel()
    nest.SetKernelStatus({"resolution": timestep})
    # create neuron and recorder
    neuron = nest.Create(neuron_model, params=di_param)
    vm = nest.Create("voltmeter", params={"interval": timestep})
    nest.Connect(vm, neuron)
    # send the spikes
    times = [timestep + n * simtime for n in range(len(bins))]
    sg = nest.Create("spike_generator",
                     params={
                         'spike_times': times,
                         'spike_weights': bins
                     })
    nest.Connect(sg, neuron)
    nest.Simulate((len(bins) + 1) * simtime)
    # get the max and its time
    dvm = nest.GetStatus(vm)[0]
    da_voltage = dvm["events"]["V_m"]
    da_times = dvm["events"]["times"]
    da_max_psp = da_voltage[argrelmax(da_voltage)]
    da_min_psp = da_voltage[argrelmin(da_voltage)]
    da_max_psp -= da_min_psp
    if len(bins) != len(da_max_psp):
        raise InvalidArgument("simtime too short: all PSP maxima are not in "
                              "range.")
    else:
        return da_max_psp
Esempio n. 7
0
    def __setitem__(self, name, value):
        g = self.parent()._graph

        if name in self:
            size = g.num_edges()

            if size:
                dtype = super(_GtEProperty, self).__getitem__(name)

                # check for list value for one edge
                if dtype == "object" and size == 1 and isinstance(value, list):
                    value = [value]

                if len(value) == size:
                    if dtype == "string":
                        g.edge_properties[name].set_2d_array(
                            np.asarray(value, object))
                    else:
                        g.edge_properties[name].a = np.asarray(value, dtype)
                else:
                    raise ValueError("A list or a np.array with one entry per "
                                     "edge in the graph is required")
        else:
            raise InvalidArgument("Attribute does not exist yet, use "
                                  "set_attribute to create it.")

        self._num_values_set[name] = len(value)
Esempio n. 8
0
def _newman_watts(source_ids, target_ids, coord_nb=-1, proba_shortcut=-1,
                  directed=True, multigraph=False, **kwargs):
    '''
    Returns a numpy array of dimension (num_edges,2) that describes the edge 
    list of a Newmaan-Watts graph.
    '''
    node_ids = np.array(source_ids, dtype=int)
    target_ids = np.array(target_ids, dtype=int)
    nodes = len(node_ids)
    circular_edges = nodes*coord_nb
    num_edges = int(circular_edges*(1+proba_shortcut))
    num_edges, circular_edges = (num_edges, circular_edges if directed
                             else (int(num_edges/2), int(circular_edges/2)))
    
    b_one_pop = _check_num_edges(
        source_ids, target_ids, num_edges, directed, multigraph)
    if not b_one_pop:
        raise InvalidArgument("This graph model can only be used if source "
                              "and target populations are the same.")
    # generate the initial circular graph
    ia_edges = np.zeros((num_edges,2),dtype=int)
    ia_edges[:circular_edges,:] = _circular_graph(node_ids, coord_nb)
    # add the random connections
    num_test, num_ecurrent = 0, circular_edges
    edges_hash = {}
    while num_ecurrent != num_edges and num_test < MAXTESTS:
        ia_sources = node_ids[randint(0, nodes, num_edges-num_ecurrent)]
        ia_targets = node_ids[randint(0, nodes, num_edges-num_ecurrent)]
        ia_edges_tmp = np.array([ia_sources,ia_targets]).T
        ia_edges, num_ecurrent = _filter(ia_edges, ia_edges_tmp, num_ecurrent,
                                         edges_hash, b_one_pop, multigraph)
        num_test += 1
    ia_edges = _no_self_loops(ia_edges)
    return ia_edges
Esempio n. 9
0
 def __getitem__(self, name):
     edges = None
     if isinstance(name, slice):
         edges = self.parent().edges_array[name]
     elif nonstring_container(name):
         if nonstring_container(name[0]):
             edges = name
         else:
             if len(name) != 2:
                 raise InvalidArgument(
                     "key for edge attribute must be one of the following: "
                     "slice, list of edges, edges or attribute name.")
             return self.parent()[name[0]][name[1]]
     if isinstance(name, str):
         dtype = _np_dtype(super(_NxEProperty, self).__getitem__(name))
         eprop = np.empty(self.parent().edge_nb(), dtype=dtype)
         g = self.parent()
         for d, eid in zip(g.edges(data=name), g.edges(data="eid")):
             eprop[eid[2]] = d[2]
         return eprop
     else:
         eprop = {k: [] for k in self.keys()}
         for edge in edges:
             data = self.parent().get_edge_data(edge[0], edge[1])
             for k, v in data.items():
                 if k != "eid":
                     eprop[k].append(v)
         for k, v in eprop.items():
             dtype = _np_dtype(super(_NxEProperty, self).__getitem__(k))
             eprop = {k: np.array(v, dtype)}
         return eprop
Esempio n. 10
0
def set_step_currents(gids, times, currents):
    '''
    Set step-current excitations

    Parameters
    ----------
    gids : tuple
        NEST gids of the target neurons.
    times : list or :class:`numpy.ndarray`
        List of the times where the current will change (by default the current
        generator is initiated at I=0. for t=0.)
    currents : list or :class:`numpy.ndarray`
        List of the new current value after the associated time value in
        `times`.

    Returns
    -------
    noise : tuple
        The NEST gid of the noise_generator.
    '''
    if len(times) != len(currents):
        raise InvalidArgument('Length of `times` and `currents` must be the '
                              'same')

    params = {"amplitude_times": times, "amplitude_values": currents}

    scg = nest.Create("step_current_generator", params=params, _warn=False)

    gids = _get_nest_gids(gids)

    nest.Connect(scg, gids, _warn=False)

    return scg
Esempio n. 11
0
def _monitor(gids, nest_recorder, params):
    new_record = []
    recorders = []
    for i, rec in enumerate(nest_recorder):
        # multi/volt/conductancemeter
        if "meter" in rec:
            device = None
            di_spec = {"rule": "all_to_all"}
            if not params[i].get("to_accumulator", True):
                device = nest.Create(rec, len(gids))
                di_spec["rule"] = "one_to_one"
            else:
                device = nest.Create(rec)
            recorders.append(device)
            device_params = nest.GetDefaults(rec)
            device_params.update(params[i])
            new_record.append(device_params["record_from"])
            nest.SetStatus(device, params[i])
            nest.Connect(device, gids, conn_spec=di_spec)
        # event detectors
        elif "detector" in rec:
            device = nest.Create(rec)
            recorders.append(device)
            new_record.append("spikes")
            nest.SetStatus(device, params[i])
            nest.Connect(gids, device)
        else:
            raise InvalidArgument('Invalid recorder item in `nest_recorder`: '
                                  '{} is unknown.'.format(nest_recorder))
    return tuple(recorders), new_record
Esempio n. 12
0
def dist_rule(rule, scale, pos_src, pos_targets, dist=None):
    '''
    DR test from one source to several targets

    Parameters
    ----------
    rule : str
        Either 'exp', 'gaussian', or 'lin'.
    scale : float
        Characteristic scale.
    pos_src : array of shape (2, N)
        Positions of the sources.
    pos_targets : array of shape (2, N)
        Positions of the targets.
    dist : list, optional (default: None)
        List that will be filled with the distances of the edges.

    Returns
    -------
    Array of size N giving the probability of the edges according to the rule.
    '''
    vect = pos_targets - pos_src
    origin = np.array([(0., 0.)])
    # todo correct this
    dist_tmp = np.squeeze(cdist(vect.T, origin), axis=1)
    if dist is not None:
        dist.extend(dist_tmp)
    if rule == 'exp':
        return np.exp(np.divide(dist_tmp, -scale))
    elif rule == 'gaussian':
        return np.exp(-0.5 * np.square(np.divide(dist_tmp, scale)))
    elif rule == 'lin':
        return np.divide(scale - dist_tmp, scale).clip(min=0.)
    else:
        raise InvalidArgument('Unknown rule "' + rule + '".')
Esempio n. 13
0
def lin_correlated_distrib(graph,
                           elist=None,
                           correl_attribute="betweenness",
                           noise_scale=None,
                           lower=None,
                           upper=None,
                           slope=None,
                           offset=0.,
                           last_edges=False,
                           **kwargs):
    if slope is not None and (lower, upper) != (None, None):
        raise InvalidArgument('`slope` and `lower`/`upper` parameters are not '
                              'compatible, please choose one or the other.')
    elif (lower is not None or upper is not None) and None in (lower, upper):
        raise InvalidArgument('Both `lower` and `upper` should be set if one '
                              'of the two is used.')
    ecount = _compute_num_prop(elist, graph)
    noise = (1. if noise_scale is None else np.abs(
        np.random.normal(1, noise_scale, ecount)))
    data = None
    if correl_attribute == "betweenness":
        data = graph.get_betweenness(kwargs["btype"], kwargs["use_weights"])
    elif correl_attribute == "distance":
        assert 'distance' in graph.edges_attributes, \
            'Graph has no "distance" edge attribute.'
        if 'distance' not in kwargs:
            if last_edges:
                slc = slice(-len(elist), None)
                data = graph.get_edge_attributes(slc, 'distance')
            else:
                data = graph.get_edge_attributes(elist, 'distance')
        else:
            data = kwargs['distance']
    else:
        raise NotImplementedError()
    if noise_scale is not None:
        data *= noise
    if len(data):
        if slope is None:
            dmax = np.max(data)
            dmin = np.min(data)
            return lower + (upper - lower) * (data - dmin) / (dmax -
                                                              dmin) + offset
        else:
            return slope * data + offset
    return np.array([])
Esempio n. 14
0
    def __setitem__(self, name, value):
        if name in self:
            if len(value) == size:
                self.parent()().vs[name] = value
            else:
                raise ValueError("A list or a np.array with one entry per \
node in the graph is required")
        else:
            raise InvalidArgument("Attribute does not exist yet, use \
set_attribute to create it.")
Esempio n. 15
0
    def _init_spatial_properties(self, shape, positions=None, **kwargs):
        '''
        Create the positions of the neurons from the graph `shape` attribute
        and computes the connections distances.
        '''
        positions = None if positions is None else np.asarray(positions)

        self.new_edge_attribute('distance', 'double')

        if positions is not None and len(positions) != self.node_nb():
            raise InvalidArgument("Wrong number of neurons in `positions`.")

        if shape is not None:
            shape.set_parent(self)
            self._shape = shape
        else:
            if positions is None or not np.any(positions):
                if 'height' in kwargs and 'width' in kwargs:
                    self._shape = nngt.geometry.Shape.rectangle(
                        kwargs['height'], kwargs['width'], parent=self)
                elif 'radius' in kwargs:
                    self._shape = nngt.geometry.Shape.disk(kwargs['radius'],
                                                           parent=self)
                elif 'radii' in kwargs:
                    self._shape = nngt.geometry.Shape.ellipse(kwargs['radii'],
                                                              parent=self)
                elif 'polygon' in kwargs:
                    self._shape = nngt.geometry.Shape.from_polygon(
                        kwargs['polygon'],
                        min_x=kwargs.get('min_x', -5000.),
                        max_x=kwargs.get('max_x', 5000.),
                        unit=kwargs.get('unit', 'um'),
                        parent=self)
                else:
                    raise RuntimeError('SpatialGraph needs a `shape` or '
                                       'keywords arguments to build one, or '
                                       'at least `positions` so it can create '
                                       'a square containing them')
            else:
                minx, maxx = np.min(positions[:, 0]), np.max(positions[:, 0])
                miny, maxy = np.min(positions[:, 1]), np.max(positions[:, 1])

                height, width = 1.01 * (maxy - miny), 1.01 * (maxx - minx)

                centroid = (0.5 * (maxx + minx), 0.5 * (maxy + miny))

                self._shape = nngt.geometry.Shape.rectangle(height,
                                                            width,
                                                            centroid=centroid,
                                                            parent=self)

        b_rnd_pos = True if not self.node_nb() or positions is None else False
        self._pos = self._shape.seed_neurons() if b_rnd_pos else positions

        Connections.distances(self)
Esempio n. 16
0
    def set_model(self, model, group=None):
        '''
        Set the groups' models.

        Parameters
        ----------
        model : dict
            Dictionary containing the model type as key ("neuron" or "synapse")
            and the model name as value (e.g. {"neuron": "iaf_neuron"}).
        group : list of strings, optional (default: None)
            List of strings containing the names of the groups which models
            should be updated.

        Note
        ----
        By default, synapses are registered as "static_synapse"s in NEST;
        because of this, only the ``neuron_model`` attribute is checked by
        the ``has_models`` function: it will answer ``True`` if all groups
        have a 'non-None' ``neuron_model`` attribute.

        Warning
        -------
        No check is performed on the validity of the models, which means
        that errors will only be detected when building the graph in NEST.
        '''
        if self._to_nest:
            raise RuntimeError("Models cannot be changed after the network "
                               "has been sent to NEST!")
        if group is None:
            group = self.keys()
        try:
            for key, val in model.items():
                for name in group:
                    if key == "neuron":
                        self[name].neuron_model = val
                    elif key == "synapse":
                        self[name].syn_model = val
                    else:
                        raise ValueError(
                            "Model type {} is not valid; choose among 'neuron'"
                            " or 'synapse'.".format(key))
        except:
            if model is not None:
                raise InvalidArgument(
                    "Invalid model dict or group; see docstring.")

        b_has_models = True

        if model is None:
            b_has_models = False

        for group in self.values():
            b_has_models *= group.has_model

        self._has_models = b_has_models
Esempio n. 17
0
    def __setitem__(self, name, value):
        if name in self:
            size = self.parent().num_edges()
            if len(value) == size:
                self.parent().edge_properties[name].a = np.array(value)
            else:
                raise ValueError("A list or a np.array with one entry per \
edge in the graph is required")
        else:
            raise InvalidArgument("Attribute does not exist yet, use \
set_attribute to create it.")
Esempio n. 18
0
    def weights(graph=None, elist=None, wlist=None, distribution="constant",
                parameters={}, noise_scale=None):
        '''
        Compute the weights of the graph's edges.
        @todo: take elist into account

        Parameters
        ----------
        graph : class:`~nngt.Graph` or subclass
            Graph the nodes belong to.
        elist : class:`numpy.array`, optional (default: None)
            List of the edges (for user defined weights).
        wlist : class:`numpy.array`, optional (default: None)
            List of the weights (for user defined weights).
        distribution : class:`string`, optional (default: "constant")
            Type of distribution (choose among "constant", "uniform",
            "lognormal", "gaussian", "user_def", "lin_corr", "log_corr").
        parameters : class:`dict`, optional (default: {})
            Dictionary containing the distribution parameters.
        noise_scale : class:`int`, optional (default: None)
            Scale of the multiplicative Gaussian noise that should be applied
            on the weights.

        Returns
        -------
        new_weights : class:`scipy.sparse.lil_matrix`
            A sparse matrix containing *ONLY* the newly-computed weights.
        '''
        parameters["btype"] = parameters.get("btype", "edge")
        parameters["use_weights"] = parameters.get("use_weights", False)
        #~ elist = np.array(elist) if elist is not None else elist
        elist = None
        if wlist is not None:
            assert isinstance(wlist, np.ndarray), "numpy.ndarray required in "\
                                                  "Connections.weights"
            num_edges = graph.edge_nb() if elist is None else elist.shape[0]
            if len(wlist) != num_edges:
                raise InvalidArgument(
                    '''`wlist` must have one entry per edge. For graph {},
there are {} edges while {} values where provided'''.format(
                    graph.name, num_edges, len(wlist)))
        else:
            wlist = _eprop_distribution(graph, distribution, elist=elist,
                                        **parameters)
        # add to the graph container
        bwlist = (np.max(wlist) - wlist if np.any(wlist)
                  else np.repeat(0, len(wlist)))
        if graph is not None:
            graph.set_edge_attribute(
                WEIGHT, value_type="double", values=wlist, edges=elist)
            graph.set_edge_attribute(
                BWEIGHT, value_type="double", values=bwlist, edges=elist)
        return wlist
Esempio n. 19
0
 def __setitem__(self, name, value):
     if name in self:
         size = self.parent().edge_nb()
         if len(value) == size:
             self.prop[name] = list(value)
         else:
             raise ValueError("A list or a np.array with one entry per "
                              "edge in the graph is required")
     else:
         raise InvalidArgument("Attribute does not exist yet, use "
                               "set_attribute to create it.")
     self._num_values_set[name] = len(value)
Esempio n. 20
0
 def __setitem__(self, name, value):
     size = self.parent().number_of_nodes()
     if name in self:
         if len(value) == size:
             for i in range(size):
                 self.parent().node[i][name] = value[i]
         else:
             raise ValueError("A list or a np.array with one entry per "
                              "node in the graph is required")
     else:
         raise InvalidArgument("Attribute does not exist yet, use "
                               "set_attribute to create it.")
Esempio n. 21
0
 def __setitem__(self, name, value):
     if name in self:
         size = self.parent().number_of_edges()
         if len(value) == size:
             for e in self.parent().edges(data="eid"):
                 self.parent().edges[e[0], e[1]][name] = value[e[2]]
         else:
             raise ValueError("A list or a np.array with one entry per "
                              "edge in the graph is required")
     else:
         raise InvalidArgument("Attribute does not exist yet, use "
                               "set_attribute to create it.")
Esempio n. 22
0
    def delays(graph=None,
               dlist=None,
               elist=None,
               distribution="constant",
               parameters=None,
               noise_scale=None):
        '''
        Compute the delays of the neuronal connections.

        Parameters
        ----------
        graph : class:`~nngt.Graph` or subclass
            Graph the nodes belong to.
        dlist : class:`numpy.array`, optional (default: None)
            List of user-defined delays).
        elist : class:`numpy.array`, optional (default: None)
            List of the edges which value should be updated.
        distribution : class:`string`, optional (default: "constant")
            Type of distribution (choose among "constant", "uniform",
            "lognormal", "gaussian", "user_def", "lin_corr", "log_corr").
        parameters : class:`dict`, optional (default: {})
            Dictionary containing the distribution parameters.
        noise_scale : class:`int`, optional (default: None)
            Scale of the multiplicative Gaussian noise that should be applied
            on the weights.

        Returns
        -------
        new_delays : class:`scipy.sparse.lil_matrix`
            A sparse matrix containing *ONLY* the newly-computed weights.
        '''
        elist = np.array(elist) if elist is not None else elist
        if dlist is not None:
            assert isinstance(dlist, np.ndarray), "numpy.ndarray required in "\
                                                  "Connections.delays"
            num_edges = graph.edge_nb() if elist is None else elist.shape[0]
            if len(dlist) != num_edges:
                raise InvalidArgument("`dlist` must have one entry per edge.")
        else:
            parameters["btype"] = parameters.get("btype", "edge")
            parameters["use_weights"] = parameters.get("use_weights", False)
            dlist = _eprop_distribution(graph,
                                        distribution,
                                        elist=elist,
                                        **parameters)
        # add to the graph container
        if graph is not None:
            graph.set_edge_attribute(DELAY,
                                     value_type="double",
                                     values=dlist,
                                     edges=elist)
        return dlist
Esempio n. 23
0
def _get_attribute(network, attribute, nodes=None, data=None):
    if attribute.lower() == "b2":
        if data is None:
            from nngt.simulation import get_b2
            return get_b2(network, nodes=nodes)
        else:
            if nodes is None:
                raise InvalidArgument(
                    "`nodes` entry is required when using `data`.")
            return _b2_from_data(nodes, data)
    elif attribute == "betweenness":
        betw = network.get_betweenness("node")
        if nodes is not None:
            return betw[nodes]
        return betw
    elif attribute == "closeness":
        return closeness(network, nodes=nodes)
    elif attribute == "clustering":
        return local_clustering(network, nodes=nodes)
    elif "degree" in attribute.lower():
        dtype = attribute[:attribute.index("-")]
        return network.get_degrees(dtype, node_list=nodes)
    if attribute == "firing_rate":
        if data is None:
            from nngt.simulation import get_firing_rate
            return get_firing_rate(network, nodes=nodes)
        else:
            if nodes is None:
                raise InvalidArgument(
                    "`nodes` entry is required when using `data`.")
            return _fr_from_data(nodes, data)
    elif attribute == "subgraph_centrality":
        sc = subgraph_centrality(network)
        if nodes is not None:
            return sc[nodes]
        return sc
    else:
        raise RuntimeError(
            "Attribute '{}' is not available.".format(attribute))
Esempio n. 24
0
    def __setitem__(self, name, value):
        g = self.parent()._graph

        if name in self:
            size = g.ecount()
            if len(value) == size:
                g.es[name] = value
            else:
                raise ValueError("A list or a np.array with one entry per "
                                 "edge in the graph is required")
        else:
            raise InvalidArgument("Attribute does not exist yet, use "
                                  "set_attribute to create it.")
Esempio n. 25
0
 def new_edge(self, source, target, attributes=None):
     '''
     Adding a connection to the graph, with optional properties.
     
     Parameters
     ----------
     source : :class:`int/node`
         Source node.
     target : :class:`int/node`
         Target node.
     attributes : :class:`dict`, optional (default: ``{}``)
         Dictionary containing optional edge properties. If the graph is
         weighted, defaults to ``{"weight": 1.}``, the unit weight for the
         connection (synaptic strength in NEST).
         
     Returns
     -------
     The new connection.
     '''
     if attributes is None:
         attributes = {}
     connection = super(_GtGraph, self).add_edge(source,
                                                 target,
                                                 add_missing=True)
     _set_edge_attr(self, [(source, target)], attributes)
     for key, val in attributes:
         if key in self.edge_properties:
             self.edge_properties[key][connection] = val[0]
         else:
             raise InvalidArgument("Unknown edge property `" + key + "'.")
     if not self._directed:
         c2 = super(_GtGraph, self).add_edge(target, source)
         for key, val in attributes:
             if key in self.edge_properties:
                 self.edge_properties[key][c2] = val[0]
             else:
                 raise InvalidArgument("Unknown edge property `" + key +
                                       "'.")
     return connection
Esempio n. 26
0
    def new_node_attribute(self, name, value_type, values=None, val=None):
        num_nodes = self.vcount()
        if values is None:
            if val is not None:
                values = np.repeat(val, num_nodes)
            else:
                if vector in value_type:
                    values = [[] for _ in range(num_nodes)]
                else:
                    values = np.repeat(self.di_value[value_type], num_nodes)
        elif len(values) != num_nodes:
            raise InvalidArgument("'values' list must contain one element per \
node in the graph.")
        self.vs[name] = values
Esempio n. 27
0
    def new_edge_attribute(self, name, value_type, values=None, val=None):
        num_edges = self.edge_nb()
        if values is None:
            if val is not None:
                values = np.repeat(val, num_edges)
            else:
                if "vec" in value_type:
                    values = [[] for _ in range(num_edges)]
                else:
                    values = np.repeat(self.di_value[value_type], num_edges)
        elif len(values) != num_edges:
            raise InvalidArgument("'values' list must contain one element per \
edge in the graph.")
        for e, val in zip(self.edges(), values):
            self.edge[e[0]][e[1]][name] = val
Esempio n. 28
0
    def new_edge(self, source, target, attributes=None, ignore=False):
        '''
        Adding a connection to the graph, with optional properties.
        
        Parameters
        ----------
        source : :class:`int/node`
            Source node.
        target : :class:`int/node`
            Target node.
        attributes : :class:`dict`, optional (default: ``{}``)
            Dictionary containing optional edge properties. If the graph is
            weighted, defaults to ``{"weight": 1.}``, the unit weight for the
            connection (synaptic strength in NEST).
        ignore : bool, optional (default: False)
            If set to True, ignore attempts to add an existing edge, otherwise
            raises an error.

        Returns
        -------
        The new connection.
        '''
        #check attributes
        if attributes is None:
            attributes = {}
        # check that the edge does not already exist
        edge = (source, target)
        if edge not in self._edges:
            edge_id                = len(self._edges)
            self._edges[edge]      = edge_id
            self._out_deg[source] += 1
            self._in_deg[target]  += 1
            # attributes
            self.attr_new_edges([(source, target)], attributes=attributes)
            # update matrix
            w = _get_edge_attr(self, [edge], "weight", last_edges=True)
            self._adj_mat[source, target] = w
            if not self._directed:
                e_recip                = (target, source)
                self._edges[e_recip]   = edge_id + 1
                self._out_deg[target] += 1
                self._in_deg[source]  += 1
                _set_edge_attr(self, [e_recip], attributes)
                self._adj_mat[source, target] = w
        else:
            if not ignore:
                raise InvalidArgument("Trying to add existing edge.")
        return edge
Esempio n. 29
0
    def __setitem__(self, name, value):
        dtype = super(_GtNProperty, self).__getitem__(name)

        g = self.parent()._graph

        if name in self:
            size = g.num_vertices()
            if len(value) == size:
                if dtype == "string":
                    g.vertex_properties[name].set_2d_array(np.asarray(value))
                else:
                    g.vertex_properties[name].a = np.asarray(value)
            else:
                raise ValueError("A list or a np.array with one entry per "
                                 "node in the graph is required")
        else:
            raise InvalidArgument("Attribute does not exist yet, use "
                                  "set_attribute to create it.")
Esempio n. 30
0
 def new_edge(self, source, target, attributes=None, ignore=False):
     '''
     Adding a connection to the graph, with optional properties.
     
     Parameters
     ----------
     source : :class:`int/node`
         Source node.
     target : :class:`int/node`
         Target node.
     attributes : :class:`dict`, optional (default: ``{}``)
         Dictionary containing optional edge properties. If the graph is
         weighted, defaults to ``{"weight": 1.}``, the unit weight for the
         connection (synaptic strength in NEST).
     ignore : bool, optional (default: False)
         If set to True, ignore attempts to add an existing edge, otherwise
         raises an error.
         
     Returns
     -------
     The new connection.
     '''
     if self.has_edge(source, target):
         if not ignore:
             raise InvalidArgument("Trying to add existing edge.")
     else:
         for attr in attributes:
             if "_corr" in attr:
                 raise NotImplementedError("Correlated attributes are not "
                                           "available with networkx.")
         if self._weighted and "weight" not in attributes:
             attributes["weight"] = 1.
         self.add_edge(source, target)
         self[source][target]["eid"] = self.number_of_edges()
         # call parent function to set the attributes
         self.attr_new_edges([(source, target)], attributes=attributes)
         if not self._directed:
             self.add_edge(target,source)
             self[source][target]["eid"] = self.number_of_edges()
             for key, val in attributes.items():
                 self[target][source][key] = val
             self.attr_new_edges([(target, source)], attributes=attributes)
     return (source, target)