Exemplo n.º 1
0
 def _get_property(self, prop, selection):
     if prop == Edge.SOURCE_NODE_ID:
         result = utils.ensure_ids(self._population.source_nodes(selection))
     elif prop == Edge.TARGET_NODE_ID:
         result = utils.ensure_ids(self._population.target_nodes(selection))
     elif prop in self._attribute_names:
         result = self._population.get_attribute(prop, selection)
     elif prop in self._dynamics_params_names:
         result = self._population.get_dynamics_attribute(
             prop.split(DYNAMICS_PREFIX)[1], selection)
     else:
         raise BluepySnapError(f"No such property: {prop}")
     return result
Exemplo n.º 2
0
    def get(self, group=None, t_start=None, t_stop=None):
        """Fetch data from the report.

        Args:
            group (None/int/list/np.array/dict): Get frames filtered by group. See NodePopulation.
            t_start (float): Include only frames occurring at or after this time.
            t_stop (float): Include only frames occurring at or before this time.

        Returns:
            pandas.DataFrame: frame as columns indexed by timestamps.
        """
        ids = self._resolve(group).tolist()
        try:
            view = self._frame_population.get(node_ids=ids,
                                              tstart=t_start,
                                              tstop=t_stop)
        except SonataError as e:
            raise BluepySnapError(e) from e

        if len(view.ids) == 0:
            return pd.DataFrame()

        # cell ids and section ids in the columns are enforced to be int64
        # to avoid issues with numpy automatic conversions and to ensure that
        # the results are the same regardless of the libsonata version [NSETM-1766]
        res = pd.DataFrame(
            data=view.data,
            columns=pd.MultiIndex.from_arrays(ensure_ids(view.ids).T),
            index=view.times,
        ).sort_index(axis=1)

        # rename from multi index to index cannot be achieved easily through df.rename
        res.columns = self._wrap_columns(res.columns)
        return res
Exemplo n.º 3
0
    def node_ids(self):
        """Returns the node ids present in the report.

        Returns:
            np.Array: Numpy array containing the node_ids included in the report
        """
        return np.sort(ensure_ids(self._frame_population.get_node_ids()))
Exemplo n.º 4
0
    def pathway_edges(self, source=None, target=None, properties=None):
        """Get edges corresponding to ``source`` -> ``target`` connections.

        Args:
            source (CircuitNodeIds/int/sequence/str/mapping/None): source node group
            target (CircuitNodeIds/int/sequence/str/mapping/None): target node group
            properties: None / edge property name / list of edge property names

        Returns:
            List of edge IDs, if ``properties`` is None;
            Pandas Series indexed by edge IDs if ``properties`` is string;
            Pandas DataFrame indexed by edge IDs if ``properties`` is list.
        """
        if source is None and target is None:
            raise BluepySnapError(
                "Either `source` or `target` should be specified")

        source_node_ids = self._resolve_node_ids(self.source, source)
        target_edge_ids = self._resolve_node_ids(self.target, target)

        if source_node_ids is None:
            selection = self._population.afferent_edges(target_edge_ids)
        elif target_edge_ids is None:
            selection = self._population.efferent_edges(source_node_ids)
        else:
            selection = self._population.connecting_edges(
                source_node_ids, target_edge_ids)

        if properties:
            return self._get(selection, properties)
        return utils.ensure_ids(selection.flatten())
Exemplo n.º 5
0
    def _get(self, selection, properties=None):
        """Get an array of edge IDs or DataFrame with edge properties."""
        edge_ids = utils.ensure_ids(selection.flatten())
        if properties is None:
            Deprecate.warn(
                "Returning ids with get/properties is deprecated and will be removed in 1.0.0. "
                "Please use EdgePopulation.ids instead.")
            return edge_ids

        if utils.is_iterable(properties):
            if len(edge_ids) == 0:
                result = pd.DataFrame(columns=properties)
            else:
                result = pd.DataFrame(index=edge_ids)
                for p in properties:
                    result[p] = self._get_property(p, selection)
        else:
            if len(edge_ids) == 0:
                result = pd.Series(name=properties, dtype=np.float64)
            else:
                result = pd.Series(self._get_property(properties, selection),
                                   index=edge_ids,
                                   name=properties)

        return result
Exemplo n.º 6
0
    def from_dict(cls, ids_dictionary):
        """Create a set of ids using a dictionary as input.

        Args:
            ids_dictionary (dict): a dictionary with the population as keys and node IDs as
                values.

        Notes:
            with the support of python 2 we cannot guaranty the ordering so we force the sorting
            of ids.

        Returns:
            CircuitIds: a set of global node IDs created via the provided dictionary.

        Examples:
            >>> CircuitIds.from_dict({"pop1": [0,2,4], "pop2": [1,2,5]})
        """
        populations = np.empty((0, ), dtype=str)
        population_ids = np.empty((0, ), dtype=utils.IDS_DTYPE)
        for population, ids in ids_dictionary.items():
            ids = utils.ensure_ids(ids)
            population_ids = np.append(population_ids, ids)
            populations = np.append(populations,
                                    np.full(ids.shape, fill_value=population))
        index = pd.MultiIndex.from_arrays([populations, population_ids])
        return cls(index, sort_index=True)
Exemplo n.º 7
0
    def ids(self,
            group=None,
            limit=None,
            sample=None,
            raise_missing_property=True):
        """Edge IDs corresponding to edges ``edge_ids``.

        Args:
            group (None/int/CircuitEdgeId/CircuitEdgeIds/sequence): Which IDs will be
                returned depends on the type of the ``group`` argument:
                - ``None``: return all IDs.
                - ``int``, ``CircuitEdgeId``: return a single edge ID.
                - ``CircuitEdgeIds`` return IDs of edges the edge population in an array.
                - ``sequence``: return IDs of edges in an array.

            sample (int): If specified, randomly choose ``sample`` number of
                IDs from the match result. If the size of the sample is greater than
                the size of the EdgePopulation then all ids are taken and shuffled.

            limit (int): If specified, return the first ``limit`` number of
                IDs from the match result. If limit is greater than the size of the population
                all node IDs are returned.

            raise_missing_property (bool): if True, raises if a property is not listed in this
                population. Otherwise the ids are just not selected if a property is missing.

        Returns:
            numpy.array: A numpy array of IDs.
        """
        if group is None:
            result = self._population.select_all().flatten()
        elif isinstance(group, CircuitEdgeIds):
            result = group.filter_population(self.name).get_ids()
        elif isinstance(group, np.ndarray):
            result = group
        elif isinstance(group, Mapping):
            result = self._edge_ids_by_filter(
                queries=group, raise_missing_prop=raise_missing_property)
        else:
            result = utils.ensure_list(group)
            # test if first value is a CircuitEdgeId if yes then all values must be CircuitEdgeId
            if isinstance(first(result, None), CircuitEdgeId):
                try:
                    result = [
                        cid.id for cid in result if cid.population == self.name
                    ]
                except AttributeError as e:
                    raise BluepySnapError(
                        "All values from a list must be of type int or CircuitEdgeId."
                    ) from e
        if sample is not None:
            if len(result) > 0:
                result = np.random.choice(result,
                                          min(sample, len(result)),
                                          replace=False)
        if limit is not None:
            result = result[:limit]
        return utils.ensure_ids(result)
Exemplo n.º 8
0
    def _get_ids_from_pop(self,
                          fun_to_apply,
                          returned_ids_cls,
                          sample=None,
                          limit=None):
        """Get CircuitIds of class 'returned_ids_cls' for all populations using 'fun_to_apply'.

        Args:
            fun_to_apply (function): A function that returns the list of IDs for each population
                and the population containing these IDs.
            returned_ids_cls (CircuitNodeIds/CircuitEdgeIds): the class for the CircuitIds.
            sample (int): If specified, randomly choose ``sample`` number of
                IDs from the match result. If the size of the sample is greater than
                the size of all the NetworkObjectPopulation then all ids are taken and shuffled.
            limit (int): If specified, return the first ``limit`` number of
                IDs from the match result. If limit is greater than the size of all the population
                then all IDs are returned.

        Returns:
            CircuitNodeIds/CircuitEdgeIds: containing the IDs and the populations.
        """
        str_type = "<U{}".format(max(
            len(pop) for pop in self.population_names))
        ids = []
        populations = []
        for pop in self.values():
            pop_ids, name_ids = fun_to_apply(pop)
            pops = np.full_like(pop_ids, fill_value=name_ids, dtype=str_type)
            ids.append(pop_ids)
            populations.append(pops)
        ids = utils.ensure_ids(np.concatenate(ids))
        populations = np.concatenate(populations).astype(str_type)
        res = returned_ids_cls.from_arrays(populations, ids)
        if sample:
            res.sample(sample, inplace=True)
        if limit:
            res.limit(limit, inplace=True)
        return res
Exemplo n.º 9
0
    def efferent_nodes(self, source, unique=True):
        """Get efferent node IDs for given source ``node_id``.

        Notes:
            Efferent nodes are nodes receiving an incoming edge from one of the ``source`` node.

        Args:
            source (CircuitNodeIds/int/sequence/str/mapping/None): the source you want to resolve
                and use as source nodes.
            unique (bool): If ``True``, return only unique afferent node IDs.

        Returns:
            numpy.ndarray: Efferent node IDs for all the sources.
        """
        if source is not None:
            selection = self._population.efferent_edges(
                self._resolve_node_ids(self.source, source))
        else:
            selection = self._population.select_all()
        result = self._population.target_nodes(selection)
        if unique:
            result = np.unique(result)
        return utils.ensure_ids(result)
Exemplo n.º 10
0
    def afferent_nodes(self, target, unique=True):
        """Get afferent node IDs for given target ``node_id``.

        Notes:
            Afferent nodes are nodes projecting an outgoing edge to one of the ``target`` node.

        Args:
            target (CircuitNodeIds/int/sequence/str/mapping/None): the target you want to resolve
            and use as target nodes.
            unique (bool): If ``True``, return only unique afferent node IDs.

        Returns:
            numpy.ndarray: Afferent node IDs for all the targets.
        """
        if target is not None:
            selection = self._population.afferent_edges(
                self._resolve_node_ids(self.target, target))
        else:
            selection = self._population.select_all()
        result = self._population.source_nodes(selection)
        if unique:
            result = np.unique(result)
        return utils.ensure_ids(result)
Exemplo n.º 11
0
    def from_arrays(cls, populations, population_ids, sort_index=True):
        """Create a set of ids using two arrays population(s) and id(s).

        Args:
            populations (list/numpy.array): a sequence of populations. If the population is a
                string then all the ids will be connected to this population.
            population_ids (list/numpy.array): a sequence of node IDs or a single node ID.
            sort_index (bool): will sort the index if set to True. Otherwise the ordering from the
                user inputs is kept. Sorting the index can result in better performances.

        Returns:
            CircuitIds: a set of global node IDs created via the populations and the node IDs
                provided.
        """
        populations = np.asarray(populations)
        population_ids = utils.ensure_ids(population_ids)

        if len(populations) != len(population_ids):
            raise BluepySnapError(
                "populations and population_ids must have the same size. "
                f"{len(populations)} != {len(population_ids)}")

        index = pd.MultiIndex.from_arrays([populations, population_ids])
        return cls(index, sort_index=sort_index)
Exemplo n.º 12
0
def test_ensure_ids():
    res = test_module.ensure_ids(np.array([1, 2, 3], dtype=np.uint64))
    npt.assert_equal(res, np.array([1, 2, 3], dtype=test_module.IDS_DTYPE))
    npt.assert_equal(res.dtype, test_module.IDS_DTYPE)
Exemplo n.º 13
0
    def ids(self,
            group=None,
            limit=None,
            sample=None,
            raise_missing_property=True):
        """Node IDs corresponding to node ``group``.

        Args:
            group (int/CircuitNodeId/CircuitNodeIds/sequence/str/mapping/None): Which IDs will be
                returned depends on the type of the ``group`` argument:

                - ``int``, ``CircuitNodeId``: return a single node ID if it belongs to the circuit.
                - ``CircuitNodeIds`` return IDs of nodes from the node population in an array.
                - ``sequence``: return IDs of nodes in an array.
                - ``str``: return IDs of nodes in a node set.
                - ``mapping``: return IDs of nodes matching a properties filter.
                - ``None``: return all node IDs.

                If ``group`` is a ``sequence``, the order of results is preserved.
                Otherwise the result is sorted and contains no duplicates.

            sample (int): If specified, randomly choose ``sample`` number of
                IDs from the match result. If the size of the sample is greater than
                the size of the NodePopulation then all ids are taken and shuffled.

            limit (int): If specified, return the first ``limit`` number of
                IDs from the match result. If limit is greater than the size of the population
                all node IDs are returned.

            raise_missing_property (bool): if True, raises if a property is not listed in this
                population. Otherwise the ids are just not selected if a property is missing.

        Returns:
            numpy.array: A numpy array of IDs.

        Examples:
            The available group parameter values:

            >>> nodes.ids(group=None)  #  returns all IDs
            >>> nodes.ids(group={})  #  returns all IDs
            >>> nodes.ids(group=1)  #  returns the single ID if present in population
            >>> #  returns the single ID if present in population and the circuit id population
            >>> #  corresponds to nodes.name
            >>> nodes.ids(group=CircuitNodeId('pop', 1))
            >>> nodes.ids(group=[1,2,3])  # returns list of IDs if all present in population
            >>> #  returns list of IDs if all present in population
            >>> nodes.ids(group=CircuitNodeIds.from_dict({"pop": [0, 1,2]}))
            >>> nodes.ids(group="node_set_name")  # returns list of IDs matching node set
            >>> nodes.ids(group={ Node.LAYER: 2})  # returns list of IDs matching layer==2
            >>> nodes.ids(group={ Node.LAYER: [2, 3]})  # returns list of IDs with layer in [2,3]
            >>> nodes.ids(group={ Node.X: (0, 1)})  # returns list of IDs with 0 < x < 1
            >>> # returns list of IDs matching one of the queries inside the 'or' list
            >>> nodes.ids(group={'$or': [{ Node.LAYER: [2, 3]},
            >>>                          { Node.X: (0, 1), Node.MTYPE: 'L1_SLAC' }]})
            >>> # returns list of IDs matching all the queries inside the 'and' list
            >>> nodes.ids(group={'$and': [{ Node.LAYER: [2, 3]},
            >>>                           { Node.X: (0, 1), Node.MTYPE: 'L1_SLAC' }]})
        """
        # pylint: disable=too-many-branches
        preserve_order = False
        if isinstance(group, str):
            group = self._get_node_set(group)
        elif isinstance(group, CircuitNodeIds):
            group = group.filter_population(self.name).get_ids()

        if group is None:
            result = self._data.index.values
        elif isinstance(group, Mapping):
            result = self._node_ids_by_filter(
                queries=group, raise_missing_prop=raise_missing_property)
        elif isinstance(group, np.ndarray):
            result = group
            self._check_ids(result)
            preserve_order = True
        else:
            result = utils.ensure_list(group)
            # test if first value is a CircuitNodeId all values are all CircuitNodeId
            if isinstance(first(result, None), CircuitNodeId):
                try:
                    result = [
                        cid.id for cid in result if cid.population == self.name
                    ]
                except AttributeError:
                    raise BluepySnapError(
                        "All values from a list must be of type int or "
                        "CircuitNodeId.")
            self._check_ids(result)
            preserve_order = isinstance(group, Sequence)

        if sample is not None:
            if len(result) > 0:
                result = np.random.choice(result,
                                          min(sample, len(result)),
                                          replace=False)
            preserve_order = False
        if limit is not None:
            result = result[:limit]

        result = utils.ensure_ids(result)
        if preserve_order:
            return result
        else:
            return np.unique(result)