Mentions légales du service

Skip to content
Snippets Groups Projects
skl_fgraph.py 6.4 KiB
Newer Older
NADAL Morgane's avatar
NADAL Morgane committed
# Copyright CNRS/Inria/UNS
NADAL Morgane's avatar
NADAL Morgane committed
# Contributor(s): Eric Debreuve (since 2018), Morgane Nadal (2020)
NADAL Morgane's avatar
NADAL Morgane committed
#
# eric.debreuve@cnrs.fr
#
# This software is governed by the CeCILL  license under French law and
# abiding by the rules of distribution of free software.  You can  use,
# modify and/ or redistribute the software under the terms of the CeCILL
# license as circulated by CEA, CNRS and INRIA at the following URL
# "http://www.cecill.info".
#
# As a counterpart to the access to the source code and  rights to copy,
# modify and redistribute granted by the license, users are provided only
# with a limited warranty  and the software's author,  the holder of the
# economic rights,  and the successive licensors  have only  limited
# liability.
#
# In this respect, the user's attention is drawn to the risks associated
# with loading,  using,  modifying and/or developing or reproducing the
# software by the user in light of its specific status of free software,
# that may mean  that it is complicated to manipulate,  and  that  also
# therefore means  that it is reserved for developers  and  experienced
# professionals having in-depth computer knowledge. Users are therefore
# encouraged to load and test the software's suitability as regards their
# requirements in conditions enabling the security of their systems and/or
# data to be ensured and,  more generally, to use and operate it in the
# same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.

# skl_fgraph=Skeleton graph with computable features; Derived from base skeleton graph.

from sklgraph.skl_graph import skl_graph_t as skl_nfgraph_t  # nf=no feature
NADAL Morgane's avatar
NADAL Morgane committed

from typing import Callable, Iterable, List, Tuple  # , SupportsFloat

import numpy as np_


class skl_graph_t(skl_nfgraph_t):
    #
    @property
    def n_nodes(self) -> int:
        return self.number_of_nodes()

    @property
    def n_edges(self) -> int:
        return self.number_of_edges()

    @property
NADAL Morgane's avatar
NADAL Morgane committed
    def max_degree(self) -> int:
        return max(degree for node, degree in self.degree if "S" not in node)
    @property
    def std_degree(self) -> int:
        return np_.std(list(degree for node, degree in self.degree if "S" not in node and degree != 1))

NADAL Morgane's avatar
NADAL Morgane committed
    @property
    def max_degree_except_leaves_an_roots(self) -> int:
        try:
            return max(degree for node, degree in self.degree if "S" not in node and degree > 2)
        except:
            return 1
NADAL Morgane's avatar
NADAL Morgane committed

    @property
    def min_degree_except_leaves_and_roots(self) -> int:
        try:
            return min(degree for node, degree in self.degree if "S" not in node and degree > 2)
        except:
            return 1
NADAL Morgane's avatar
NADAL Morgane committed

    @property
    def mean_degree_except_leaves_and_roots(self) -> int:
        try:
            return np_.mean(list(degree for node, degree in self.degree if "S" not in node and degree > 2))
        except:
            return 1
NADAL Morgane's avatar
NADAL Morgane committed

    @property
    def median_degree_except_leaves_and_roots(self) -> int:
        try:
            return np_.median(list(degree for node, degree in self.degree if "S" not in node and degree > 2))
        except:
            return 1
    @property
    def std_degree_except_leaves_and_roots(self) -> int:
        try:
            return np_.std(list(degree for node, degree in self.degree if "S" not in node and degree > 2))
        except:
            return 0
NADAL Morgane's avatar
NADAL Morgane committed

    @property
    def edge_lengths(self) -> Tuple[float, ...]:
        #
        return tuple(
            edge.lengths.length for ___, ___, edge in self.edges.data("as_edge_t") if edge is not None
NADAL Morgane's avatar
NADAL Morgane committed
        )

    @property
    def length(self) -> float:
        #
        return sum(self.edge_lengths)

    @property
    def min_length(self) -> float:
        #
        return min(self.edge_lengths)

    @property
    def max_length(self) -> float:
        #
        return max(self.edge_lengths)

    @property
    def mean_length(self) -> float:
        #
        return np_.mean(self.edge_lengths)

    @property
    def median_length(self) -> float:
        #
        return np_.median(self.edge_lengths)

    @property
    def std_length(self) -> float:
        #
        return np_.std(self.edge_lengths)

NADAL Morgane's avatar
NADAL Morgane committed
    @property
    def edge_ww_lengths(self) -> Tuple[float, ...]:
        #
        return tuple(
            edge.lengths.ww_length for ___, ___, edge in self.edges.data("as_edge_t") if edge is not None
NADAL Morgane's avatar
NADAL Morgane committed
        )

    @property
    def ww_length(self) -> float:
        #
        return sum(self.edge_ww_lengths)

    def edge_reduced_widths(
NADAL Morgane's avatar
NADAL Morgane committed
            self, reduce_fct: Callable[[Iterable[float]], float] = np_.mean
NADAL Morgane's avatar
NADAL Morgane committed
    ) -> Tuple[float, ...]:
        #
        return tuple(
            reduce_fct(edge.widths) for ___, ___, edge in self.edges.data("as_edge_t") if edge is not None
NADAL Morgane's avatar
NADAL Morgane committed
        )

    def reduced_width(
NADAL Morgane's avatar
NADAL Morgane committed
            self, reduce_fct: Callable[[Iterable[float]], float] = np_.mean
NADAL Morgane's avatar
NADAL Morgane committed
    ) -> float:
        #
        all_widths = []
        for ___, ___, edge in self.edges.data("as_edge_t"):
            if edge is not None:
                all_widths.extend(edge.widths)
NADAL Morgane's avatar
NADAL Morgane committed

        return reduce_fct(all_widths)

    def heterogeneous_reduced_width(
NADAL Morgane's avatar
NADAL Morgane committed
            self,
            edge_reduce_fct: Callable[[Iterable[float]], float] = np_.mean,
            final_reduce_fct: Callable[[Iterable[float]], float] = np_.mean,
NADAL Morgane's avatar
NADAL Morgane committed
    ) -> float:
        #
        return final_reduce_fct(self.edge_reduced_widths(edge_reduce_fct))

    def primary_edge_lengths(self, soma) -> Tuple[float, ...]:
        #
        return tuple(edge.lengths.length for node1_id, node2_id, edge in self.edges.data("as_edge_t") if(edge is not None) and ((node1_id in soma.graph_roots.values()) or (node2_id in soma.graph_roots.values())))

    def secondary_edge_lengths(self, soma) -> Tuple[float, ...]:
        #
        return tuple(edge.lengths.length for node1_id, node2_id, edge in self.edges.data("as_edge_t") if (node1_id not in soma.graph_roots.values()) and (node2_id not in soma.graph_roots.values()))

    def highest_degree_w_nodes(self, soma) -> Tuple[int, List[str]]:
        #
        max_degree = 1
        at_nodes = None
        for node, degree in self.degree:
            if "S" not in node:
                if degree > 2:
                    if degree > max_degree:
                        max_degree = degree
                        at_nodes = [node]
                    elif degree == max_degree:
                        at_nodes.append(node)

        return max_degree, at_nodes