From 85d96807b894fc83da82442b8ba6dfc9159ea4ee Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Wed, 11 Aug 2021 16:13:57 +0200 Subject: [PATCH 01/16] documentation updated in algorithms.centralities.py --- pathpy/algorithms/centralities.py | 60 ++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/pathpy/algorithms/centralities.py b/pathpy/algorithms/centralities.py index 2498b22..b7fed5b 100644 --- a/pathpy/algorithms/centralities.py +++ b/pathpy/algorithms/centralities.py @@ -77,7 +77,20 @@ def betweenness_centrality(self, normalized: bool = False) -> Dict: @betweenness_centrality.register(PathCollection) def _bw_paths(self: PathCollection, normalized: bool = False) -> Dict: - """Betweenness Centrality for Paths.""" + """Betweenness Centrality for Paths. + + Parameters + ---------- + paths : PathCollection + + The :py:class:`PathCollection` object that contains a collection of edges. + + normalized : bool + + If True the resulting centralities will be normalized such that the + minimum centrality is zero and the maximum centrality is one. + + """ # TODO: Move sp calculation to shortest_paths # from pathpy.statistics.subpaths import SubPathCollection @@ -129,7 +142,20 @@ def _bw_paths(self: PathCollection, normalized: bool = False) -> Dict: @betweenness_centrality.register(BaseNetwork) def _bw_network(self: Network, normalized: bool = False) -> Dict: - """Betweenness Centrality for Networks.""" + """Betweenness Centrality for Networks. + + Parameters + ---------- + network : Network + + The :py:class:`Network` object that contains the network. + + normalized : bool + + If True the resulting centralities will be normalized such that the + minimum centrality is zero and the maximum centrality is one. + + """ all_paths = shortest_paths.all_shortest_paths( self, weight=False, return_distance_matrix=False) @@ -158,7 +184,20 @@ def _bw_network(self: Network, normalized: bool = False) -> Dict: @betweenness_centrality.register(ABCHigherOrderNetwork) def _bw_hon(self: HigherOrderNetwork, normalized: bool = False) -> Dict: - """Betweenness Centrality for Networks.""" + """Betweenness Centrality for Higher Order Networks. + + Parameters + ---------- + network : HigherOrderNetwork + + The :py:class:`HigherOrderNetwork` object that contains a Higher Order Network (HON). + + normalized : bool + + If True the resulting centralities will be normalized such that the + minimum centrality is zero and the maximum centrality is one. + + """ from pathpy.core.edge import Edge from pathpy.core.path import Path @@ -335,7 +374,20 @@ def _cl_network(network: BaseNetwork, normalized: bool = False, disconnected=Fal @closeness_centrality.register(PathCollection) def _cl_paths(paths: PathCollection, normalized: bool = False, disconnected=False, weight: Optional[str]=None, count: bool=False) -> Dict: - """Betweenness Centrality for Paths.""" + """Betweenness Centrality for Paths. + + Parameters + ---------- + paths : PathCollection + + The :py:class:`PathCollection` object that contains a collection of edges + + normalized : bool + + If True the resulting centralities will be normalized such that the + minimum centrality is zero and the maximum centrality is one. + + """ if disconnected and normalized: raise ParameterError('No meaningful definition for normalized closeness centrality in disconnected networks') From 36650e6e5930cea5b56aeccf56b173ce45c307cf Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Wed, 11 Aug 2021 16:23:53 +0200 Subject: [PATCH 02/16] documentation updated in algorithms.components.py --- pathpy/algorithms/components.py | 34 +++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/pathpy/algorithms/components.py b/pathpy/algorithms/components.py index 38dc121..17a4eb2 100644 --- a/pathpy/algorithms/components.py +++ b/pathpy/algorithms/components.py @@ -26,14 +26,13 @@ def find_connected_components(network: Network) -> Dict: Parameters ---------- + network : Network - network: Network + The :py:class:`Network` object that contains the network - Network instance Returns ------- - dict dictionary mapping node uids to components (represented as integer IDs) @@ -96,6 +95,13 @@ def tarjan(v: str): def mean_component_size(network: Network) -> float: """Returns the mean connected component size of the network. + + Parameters + ---------- + network : Network + + The :py:class:`Network` object that contains the network + """ components = find_connected_components(network) component_sizes = [len(nodes) for comp, nodes in components.items()] @@ -104,6 +110,13 @@ def mean_component_size(network: Network) -> float: def largest_connected_component(network: Network) -> Network: """Returns the largest connected component of the network. + + Parameters + ---------- + network : Network + + The :py:class:`Network` object that contains the network + """ LOG.debug('Computing connected components') @@ -128,12 +141,25 @@ def largest_connected_component(network: Network) -> Network: @property def is_connected(network: Network) -> bool: """Returns whether the network is (strongly) connected + Parameters + ---------- + network : Network + + The :py:class:`Network` object that contains the network + """ return largest_component_size(network) == network.number_of_nodes() def largest_component_size(network: Network) -> int: - """Largest component size of the network.""" + """Largest component size of the network. + Parameters + ---------- + network : Network + + The :py:class:`Network` object that contains the network + + """ LOG.debug('Computing connected components') components = find_connected_components(network) if len(components): From c61de2e4b84f4b959c3f94b5b5e1901817233f26 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Wed, 11 Aug 2021 16:46:11 +0200 Subject: [PATCH 03/16] documentation for algorithms.evaluation.py updated --- pathpy/algorithms/evaluation.py | 37 ++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/pathpy/algorithms/evaluation.py b/pathpy/algorithms/evaluation.py index c0b64be..fc2f310 100644 --- a/pathpy/algorithms/evaluation.py +++ b/pathpy/algorithms/evaluation.py @@ -109,7 +109,31 @@ def train_test_split(network: Network, test_size: Optional[float]=0.25, train_si @train_test_split.register(TemporalNetwork) def _(network: TemporalNetwork, test_size: Optional[float]=0.25, train_size: Optional[float]=None, split: Optional[str]='interactions') -> tuple(TemporalNetwork, TemporalNetwork): """ - Performs a random split of a temporal network into a training and test network. The split can be performed along nodes, interactions, or time + Performs a split of a temporal network into a training and test network. The split can be performed along interactions or time. + + Parameters + ---------- + + network: TemporalNetwork + + The temporal network for which the train/test split shall be performed. + + test_size: Optional[float] = 0.25 + + Fraction of the network to include in the test network + + train_size: Optional[float] = None + + Fraction of the network to include in the training network + + split: Optional['str'] = 'interactions' + + Specifies how the train/test split shall be performed. Based on the provided test size, for the parameter 'interactions' subset of edges is selected, while for 'time' a subset of the network time is selected. + + Returns + ------- + + Tuple (n1, n2) where n1 is the training network and n2 is the test network """ test_network = TemporalNetwork(directed=network.directed, multiedges=network.multiedges, uid=network.uid+'_test') train_network = TemporalNetwork(directed=network.directed, multiedges=network.multiedges, uid=network.uid+'_train') @@ -160,6 +184,17 @@ def shuffle_temporal_network(net: TemporalNetwork): """ Randomly reassigns timestamps (start, end, duration) of edges in a temporal network. This is useful to generate a random baseline for temporal patterns in temporal networks. + + Parameters + ---------- + net: TemporalNetwork + + The temporal network for which the shuffle shall be performed. + + Returns + ------- + + Shuffled version of the provided temporal network """ timestamps = [] edges = [] From d6d0da8efb251f9454b97974e09a034cb52ddaab Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Wed, 11 Aug 2021 17:49:35 +0200 Subject: [PATCH 04/16] documentation of components.py updated --- pathpy/generators/random_graphs.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pathpy/generators/random_graphs.py b/pathpy/generators/random_graphs.py index 3228ad5..43437df 100644 --- a/pathpy/generators/random_graphs.py +++ b/pathpy/generators/random_graphs.py @@ -533,6 +533,16 @@ def Molloy_Reed(degrees: Union[np.array, Dict[int, float]], multiedge: bool = Fa def Molloy_Reed_randomize(network: Network) -> Optional[Network]: """Generates a random realization of a given network based on the observed degree sequence. + + Parameters + ---------- + network : Network + + The :py:class:`Network` object that contains the network + + Returns + ------- + Molley-Reed graph """ # degrees are listed in order of node indices degrees = network.degree_sequence() From 1ec759c24cad522d5ce69e64626df6bdbb5f4257 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Thu, 12 Aug 2021 12:05:21 +0200 Subject: [PATCH 05/16] documentation updated in sortest_paths.py --- pathpy/algorithms/shortest_paths.py | 33 ++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/pathpy/algorithms/shortest_paths.py b/pathpy/algorithms/shortest_paths.py index 8936c69..6436795 100644 --- a/pathpy/algorithms/shortest_paths.py +++ b/pathpy/algorithms/shortest_paths.py @@ -195,6 +195,21 @@ def single_source_shortest_paths(network: Network, ) -> Union[dict, np.array]: """Calculates all shortest paths from a single given source node using a custom implementation of Dijkstra's algorithm based on a priority queue. + + Parameters + ---------- + + network : Network + + The :py:class:`Network` object that contains the network + + source : str + + The uid of the source node + + weight : Union[bool, str, None] = None + + Weight of the network edges, if weighted """ Q: dict = dict() dist = dict() @@ -255,7 +270,23 @@ def shortest_path_tree(network: Network, source: str, weight: Union[bool, str, None] = None ) -> Network: """Computes a shortest path tree rooted at the node with the - given source uid.""" + given source uid. + + Parameters + ---------- + + network : Network + + The :py:class:`Network` object that contains the network + + source : str + + The uid of the root node + + weight : Union[bool, str, None] = None + + Weight of the network edges, if weighted + """ n_tree = net.Network(directed=True) From d66e6025b40b202d20bfb4a335902089e4c82ef9 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Thu, 12 Aug 2021 12:38:16 +0200 Subject: [PATCH 06/16] updated documentation temporal.py --- pathpy/core/temporal.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pathpy/core/temporal.py b/pathpy/core/temporal.py index 499b1d9..0ca2254 100644 --- a/pathpy/core/temporal.py +++ b/pathpy/core/temporal.py @@ -21,7 +21,22 @@ class TemporalPathPyObject(PathPyObject): - """Base class for a temporal object.""" + """Base class for a temporal object. + + A temporal network consists of nodes which links are only active at certain points in time. + + Parameters + ---------- + + uid : Optional[str] = None + + The uid of the parent class. + + kwargs : Any + + Keyword Arguments to create new temporal network events. They are stored with theire beginning + and ending point. + """ def __init__(self, uid: Optional[str] = None, **kwargs: Any) -> None: """Initialize the temporal object.""" From 43b118a2b51b74f89aeecebfa8046a7ce2d53ab5 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Thu, 12 Aug 2021 13:35:28 +0200 Subject: [PATCH 07/16] updated documentation csv.py --- pathpy/io/csv.py | 96 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/pathpy/io/csv.py b/pathpy/io/csv.py index 60c7eb6..924df16 100644 --- a/pathpy/io/csv.py +++ b/pathpy/io/csv.py @@ -35,7 +35,27 @@ def read_dataframe(filename: Optional[str] = None, sep: str = ',', header: bool = True, names: Optional[list] = None) -> pd.DataFrame: - """Read csv database as a pandas data frame.""" + """Read csv database as a pandas data frame. + + Parameters + ---------- + filename : Optional[str] = None + + Path to the .csv file + + sep : str = `` , `` + + Character seperating the data + + header : bool = ``True`` + + Use the file header + + names : Optional[list] = ``None`` + + List of column names to use + + """ if header: frame = pd.read_csv(filename, sep=sep) @@ -54,7 +74,42 @@ def read_network(filename: Optional[str] = None, header: bool = True, names: Optional[list] = None, **kwargs: Any) -> Network: - """Reads a network from a csvfile.""" + """Reads a network from a csvfile. + + Parameters + ---------- + filename : Optional[str] = None + + Path to the .csv file + + loops : bool = ``True`` + + Does the network have loops + + directed : bool = ``True`` + + Is the network directed + + multiedges : bool = ``False`` + + Does the network have multiedges + + sep : str = `` , `` + + Character seperating the data + + header : bool = ``True`` + + Use the file header + + names : Optional[list] = ``None`` + + List of column names to use + + **kwargs : Any + + Arbitrary keyword arguments that will be set as network-level attributes + """ # pylint: disable=too-many-arguments frame = read_dataframe(filename=filename, sep=sep, @@ -74,7 +129,42 @@ def read_temporal_network(filename: Optional[str] = None, header: bool = True, names: Optional[list] = None, **kwargs: Any) -> TemporalNetwork: - """Read temporal network from a csv database.""" + """Read temporal network from a csv database. + + Parameters + ---------- + filename : Optional[str] = None + + Path to the .csv file + + loops : bool = ``True`` + + Does the network have loops + + directed : bool = ``True`` + + Is the network directed + + multiedges : bool = ``False`` + + Does the network have multiedges + + sep : str = `` , `` + + Character seperating the data + + header : bool = ``True`` + + Use the file header + + names : Optional[list] = ``None`` + + List of column names to use + + **kwargs : Any + + Arbitrary keyword arguments that will be set as network-level attributes + """ # pylint: disable=too-many-arguments frame = read_dataframe(filename=filename, sep=sep, From 918f227720034a096f26e6cfee313a5a37c0e0d4 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Thu, 12 Aug 2021 15:00:52 +0200 Subject: [PATCH 08/16] update documentation sql.py --- pathpy/io/sql.py | 112 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 11 deletions(-) diff --git a/pathpy/io/sql.py b/pathpy/io/sql.py index 3842cf2..9538576 100644 --- a/pathpy/io/sql.py +++ b/pathpy/io/sql.py @@ -37,7 +37,30 @@ def read_dataframe(db_file: Optional[str] = None, uri: Optional[bool] = False, sql: Optional[str] = None, table: Optional[str] = None) -> pd.DataFrame: - """Read sql database as a pandas data frame.""" + """Read sql database as a pandas data frame. The Database can exists locally or be read from an online ressource. + + Parameters + ---------- + db_file : Optional[str] = ``None`` + + The path to the databse file + + con : Optional[sqlite3.Connection] = ``None`` + + The SQLite3 connection in which the network will be stored + + uri : Optional[bool] = ``False`` + + Uniform Resource Identifier for the databse + + sql : Optional[str] = ``None`` + + Executable SQL query specify the datas + + table : Optional[str] = ``None`` + + Database table to read the data from + """ LOG.debug('Load sql file as pandas data frame.') @@ -111,7 +134,43 @@ def read_network(db_file: Optional[str] = None, table: Optional[str] = None, uri: Optional[bool] = False, **kwargs: Any) -> Network: - """Read network from a sqlite database.""" + """Read network from a sqlite database. + + Parameters + ---------- + db_file : Optional[str] = ``None`` + + The path to the databse file + + loops : bool = ``True`` + + Does the network have loops + + directed : bool = ``True`` + + Is the network directed + + multiedges : bool = ``True`` + + Does the network have multiedges + + con : Optional[sqlite3.Connection] = ``None`` + + The SQLite3 connection in which the network will be stored + + uri : Optional[bool] = ``False`` + + Uniform Resource Identifier for the databse + + sql : Optional[str] = ``None`` + + Executable SQL query specify the datas + + table : Optional[str] = ``None`` + + Database table to read the data from + + """ # pylint: disable=too-many-arguments frame = read_dataframe(db_file=db_file, con=con, sql=sql, table=table, uri=uri) @@ -152,23 +211,22 @@ def write_dataframe(frame: pd.DataFrame, Parameters ---------- + frame : pd.DataFrame + + Source pandas Data Frame to write into SQL - network: Network + table: str - The network to store in the sqlite database + Name of the table in the database in which the network will be stored. - filename: str + filename: Optional[str] = ``None`` The name of the SQLite database in which the network will be stored - con: sqlite3.Connection + con : Optional[sqlite3.Connection] = ``None`` The SQLite3 connection in which the network will be stored - table: str - - Name of the table in the database in which the network will be stored. - **pdargs: Keyword args that will be passed to pandas.DataFrame.to_sql. @@ -202,7 +260,39 @@ def write(network: Union[Network, TemporalNetwork], include_edge_uid: bool = False, export_indices: bool = False, **pdargs: Any) -> None: - """Stores all edges including edge attributes in a sql file.""" + """Stores all edges including edge attributes in a sql file. It stores regular as well as temporal networks. + + Parameters + ---------- + + network: Union[Network, TemporalNetwork] + + The network to store in the sqlite database + + table: str + + Name of the table in the database in which the network will be stored. + + filename: str + + The name of the SQLite database in which the network will be stored + + con: sqlite3.Connection + + The SQLite3 connection in which the network will be stored + + include_edge_ui : bool = ``False`` + + Whether or not to include a column that stores the uids of the edge objects + + export_indices : bool = ``False`` + + Whether or not to use node indices rather than node uids. This is useful to import network data in tools that only support integer node identifiers. + + **pdargs: + + Keyword args that will be passed to pandas.DataFrame.to_sql. + """ frame = to_dataframe(network=network, include_edge_uid=include_edge_uid, export_indices=export_indices) From f27db96d4b47722cec0b7c6281f08fdb4c5d2078 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Thu, 12 Aug 2021 15:04:30 +0200 Subject: [PATCH 09/16] begin of temporal_network documentation --- pathpy/models/temporal_network.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pathpy/models/temporal_network.py b/pathpy/models/temporal_network.py index 8330b89..145afce 100644 --- a/pathpy/models/temporal_network.py +++ b/pathpy/models/temporal_network.py @@ -227,7 +227,15 @@ def _remove(self, obj) -> None: class TemporalNetwork(BaseTemporalNetwork, Network): - """Base class for a temporal networks.""" + """Base class for a temporal networks. + + Parameters + ---------- + uid : Optional[str] = ``None`` + directed : bool = ``True`` + multiedges : bool = ``False`` + **kwargs : Any + """ def __init__(self, uid: Optional[str] = None, directed: bool = True, multiedges: bool = False, **kwargs: Any) -> None: From 282e4204b9bfb17c148da9ac1195d1edd1c00271 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Thu, 19 Aug 2021 19:57:42 +0200 Subject: [PATCH 10/16] temporal.py and temporal network updated --- pathpy/core/temporal.py | 7 +++++-- pathpy/models/temporal_network.py | 23 ++++++++++++++++++++++- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/pathpy/core/temporal.py b/pathpy/core/temporal.py index 0ca2254..0d7f7a0 100644 --- a/pathpy/core/temporal.py +++ b/pathpy/core/temporal.py @@ -23,14 +23,17 @@ class TemporalPathPyObject(PathPyObject): """Base class for a temporal object. - A temporal network consists of nodes which links are only active at certain points in time. + A temporal network consists of nodes which links are only active or + change theire values at certain points in time. Parameters ---------- uid : Optional[str] = None - The uid of the parent class. + The parameter ``uid`` is the unique identifier for the path object. This + option can later be used for multi-layer networks. Currently the ``uid`` + of the network is not in use. kwargs : Any diff --git a/pathpy/models/temporal_network.py b/pathpy/models/temporal_network.py index 145afce..68e2660 100644 --- a/pathpy/models/temporal_network.py +++ b/pathpy/models/temporal_network.py @@ -227,14 +227,35 @@ def _remove(self, obj) -> None: class TemporalNetwork(BaseTemporalNetwork, Network): - """Base class for a temporal networks. + """Base class for a temporal networks. In a temporal Network, properties of nodes, edges or paths + can change over time. Parameters ---------- uid : Optional[str] = ``None`` + + The parameter ``uid`` is the unique identifier for the network. This + option can late be used for multi-layer networks. Currently the ``uid`` + of the network is not in use. + directed : bool = ``True`` + + Specifies if a network contains directed edges and paths, i.e u->v->w + or undirected edges and paths i.d. u-v-w. If ``True`` the all + subsequent objects are directed, i.e. quantities can only transmited + from the source node ``v`` to the traget node ``w``. If ``False`` the + al subsequent obects are undirected, i.e. quantities can be transmited + in both directions. Per default networks in ``pathpy`` are directed. + multiedges : bool = ``False`` + + Specifies if a network contians multiple edges, i.e. two or more edges that have + the same head and tail vertices. + **kwargs : Any + + Keyword arguments to store network attributes. Attributes are added to + the network as ``key=value`` pairs. """ def __init__(self, uid: Optional[str] = None, directed: bool = True, From f1d08930902b47bb33179268c357f1613afc4c07 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Thu, 19 Aug 2021 20:12:44 +0200 Subject: [PATCH 11/16] temporal_network updated --- pathpy/models/temporal_network.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/pathpy/models/temporal_network.py b/pathpy/models/temporal_network.py index 68e2660..1a357dd 100644 --- a/pathpy/models/temporal_network.py +++ b/pathpy/models/temporal_network.py @@ -50,7 +50,11 @@ def __init__(self, *node: Union[str, PathPyObject], TemporalPathPyObject.__init__(self, uid=self.uid, **kwargs) def summary(self) -> str: - """Object summary. """ + """Returns a summary of the temporal node. + + The summary containes the observation periode of the node, i.e. + the observation start and the observation end time. + """ summary = [ 'Observation periode:\t{} - {}'.format(self.start, self.end) ] @@ -73,7 +77,11 @@ def __init__(self, v: Union[str, PathPyObject], TemporalPathPyObject.__init__(self, uid=uid, **kwargs) def summary(self) -> str: - """Object summary. """ + """Object summary. + + The summary containes the observation periode of the edge, i.e. + the observation start and the observation end time. + """ summary = [ 'Observation period:\t{} - {}'.format(self.start, self.end) ] @@ -186,17 +194,17 @@ def _(self, key: Union[int, float, slice]) -> Any: @property def start(self): - """start of the object""" + """Returns the start of the edge object""" return self._events.begin() @property def end(self): - """end of the object""" + """Returns the end of the edge object""" return self._events.end() @property def events(self): - """Temporal events""" + """Returns all temporal events of the edge object""" return self._events @singledispatchmethod From e863806c99385c5d0ba78fe19bb573badf98b686 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Fri, 20 Aug 2021 12:20:48 +0200 Subject: [PATCH 12/16] community_detection.py update --- pathpy/algorithms/community_detection.py | 25 +++++++++++++++++++++++- pathpy/algorithms/evaluation.py | 2 +- pathpy/core/temporal.py | 2 +- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/pathpy/algorithms/community_detection.py b/pathpy/algorithms/community_detection.py index 467131b..3fc26f7 100644 --- a/pathpy/algorithms/community_detection.py +++ b/pathpy/algorithms/community_detection.py @@ -38,7 +38,30 @@ def _Q_merge(network: Network, A, D, n: int, m: int, C: Dict, merge: Set = set() def modularity_maximisation(network: Network, iterations: int = 1000) -> Tuple[Dict, float]: - """Modularity maximisation.""" + """Performs modularity maximisation in the given Network to detect + communities. + + Parameters + ---------- + + network: Network + + Object of the py:Network class. + + iterations: int = 1000 + + Number of iterations for the detection algorithm. + + Returns + ------- + + Tuple[Dict, float] + + The Dict containes tuples of node identifiers and + their corresponding communities. + The second value of the tuple returns the modularity of the network. + + """ A = network.adjacency_matrix(weighted=False) D = network.degrees() diff --git a/pathpy/algorithms/evaluation.py b/pathpy/algorithms/evaluation.py index fc2f310..731051b 100644 --- a/pathpy/algorithms/evaluation.py +++ b/pathpy/algorithms/evaluation.py @@ -189,7 +189,7 @@ def shuffle_temporal_network(net: TemporalNetwork): ---------- net: TemporalNetwork - The temporal network for which the shuffle shall be performed. + The temporal network for which the shuffle is to be performed. Returns ------- diff --git a/pathpy/core/temporal.py b/pathpy/core/temporal.py index 0d7f7a0..3b15c60 100644 --- a/pathpy/core/temporal.py +++ b/pathpy/core/temporal.py @@ -24,7 +24,7 @@ class TemporalPathPyObject(PathPyObject): """Base class for a temporal object. A temporal network consists of nodes which links are only active or - change theire values at certain points in time. + change their values at certain points in time. Parameters ---------- From 5058065113ef0985795a0d23cd300839a70eac14 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Fri, 20 Aug 2021 14:08:59 +0200 Subject: [PATCH 13/16] path_extraction, temporal.py, temporal_network.py doc updated --- pathpy/algorithms/path_extraction.py | 24 ++++++++++++++++++++++++ pathpy/core/temporal.py | 4 +--- pathpy/models/temporal_network.py | 6 +++--- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/pathpy/algorithms/path_extraction.py b/pathpy/algorithms/path_extraction.py index dfcb23c..4259160 100644 --- a/pathpy/algorithms/path_extraction.py +++ b/pathpy/algorithms/path_extraction.py @@ -312,6 +312,30 @@ def generate_causal_tree(dag, root, node_map) -> Tuple(ABCDirectedAcyclicGraph, causal tree capture that - starting from the root node at step 0 - there is a causal path to node v at distance d from the root. Note that the same node can be represented by multiple nodes in the causal tree (at different distances d). + + Parameters + ---------- + dag : Any + + directed acyclic graph + + root : Any + + Root node of the causal tree + + node_map : Any + + Mapped nodes for the tree + + Returns + ------- + Tuple(ABCDirectedAcyclicGraph, defaultdict) + + A Tuple of the new causal tree as Directed Acyclic Graph + and a Dictionary with tuples of all the nodes' unique identifiers + and their distance to the root node. Using the uids of the nodes + ensures that the same physical nodes can occur at different + distances from the root """ from pathpy.models.directed_acyclic_graph import DirectedAcyclicGraph causal_tree = DirectedAcyclicGraph() diff --git a/pathpy/core/temporal.py b/pathpy/core/temporal.py index 3b15c60..c3603dc 100644 --- a/pathpy/core/temporal.py +++ b/pathpy/core/temporal.py @@ -31,9 +31,7 @@ class TemporalPathPyObject(PathPyObject): uid : Optional[str] = None - The parameter ``uid`` is the unique identifier for the path object. This - option can later be used for multi-layer networks. Currently the ``uid`` - of the network is not in use. + The parameter ``uid`` is the unique identifier for the path object. T kwargs : Any diff --git a/pathpy/models/temporal_network.py b/pathpy/models/temporal_network.py index 1a357dd..7fce473 100644 --- a/pathpy/models/temporal_network.py +++ b/pathpy/models/temporal_network.py @@ -120,17 +120,17 @@ def _(self, key: Union[int, float, slice]) -> Any: @property def start(self): - """start of the object""" + """Returns the start of the node collections' events""" return self._events.begin() @property def end(self): - """end of the object""" + """Returns the end of the node collections' events""" return self._events.end() @property def events(self): - """Temporal events""" + """Returns an interval tree of the node collections' temporal events""" return self._events @singledispatchmethod From a06dce54c6d7548b329ae4ef85bb0a27f8a01ff2 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Fri, 20 Aug 2021 17:35:43 +0200 Subject: [PATCH 14/16] Coherent class description in documentation --- doc/tutorial/centralities.ipynb | 563 +++++++---------------- pathpy/algorithms/community_detection.py | 2 +- pathpy/algorithms/evaluation.py | 4 +- pathpy/algorithms/shortest_paths.py | 8 +- pathpy/algorithms/trees.py | 22 +- pathpy/io/csv.py | 59 ++- 6 files changed, 245 insertions(+), 413 deletions(-) diff --git a/doc/tutorial/centralities.ipynb b/doc/tutorial/centralities.ipynb index 9c2d969..ac9aa19 100644 --- a/doc/tutorial/centralities.ipynb +++ b/doc/tutorial/centralities.ipynb @@ -2,7 +2,6 @@ "cells": [ { "cell_type": "markdown", - "metadata": {}, "source": [ "# Calculating node centralities\n", "\n", @@ -10,11 +9,16 @@ "[Download notebook](https://github.com/pathpy/pathpy/raw/master/doc/tutorial/centralities.ipynb)\n", "\n", "In the following we implement degree- and path-based centrality measures and apply them to identify important nodes in empirical networks." - ] + ], + "metadata": {} }, { "cell_type": "code", "execution_count": null, + "source": [ + "pip install git+git://github.com/pathpy/pathpy.git" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:05.807157Z", @@ -22,15 +26,18 @@ "iopub.status.idle": "2021-05-21T08:57:15.235168Z", "shell.execute_reply": "2021-05-21T08:57:15.235781Z" } - }, - "outputs": [], - "source": [ - "pip install git+git://github.com/pathpy/pathpy.git" - ] + } }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, + "source": [ + "from collections import defaultdict, Counter\n", + "\n", + "import pathpy as pp\n", + "import numpy as np" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:15.241285Z", @@ -38,52 +45,18 @@ "iopub.status.idle": "2021-05-21T08:57:16.045140Z", "shell.execute_reply": "2021-05-21T08:57:16.045516Z" } - }, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": "", - "text/html": "\n \n " - }, - "metadata": {} - } - ], - "source": [ - "from collections import defaultdict, Counter\n", - "\n", - "import pathpy as pp\n", - "import numpy as np" - ] + } }, { "cell_type": "markdown", - "metadata": {}, "source": [ "We will test our implementation in an undirected and a directed example network." - ] + ], + "metadata": {} }, { "cell_type": "code", - "execution_count": 2, - "metadata": { - "execution": { - "iopub.execute_input": "2021-05-21T08:57:16.050824Z", - "iopub.status.busy": "2021-05-21T08:57:16.050360Z", - "iopub.status.idle": "2021-05-21T08:57:16.056826Z", - "shell.execute_reply": "2021-05-21T08:57:16.057195Z" - } - }, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": "", - "text/html": "\n
\n
\n\n" - }, - "metadata": {} - } - ], + "execution_count": null, "source": [ "n_undirected = pp.Network(directed=False)\n", "n_undirected.add_edge('a', 'b')\n", @@ -96,29 +69,20 @@ "n_undirected.add_edge('d', 'f')\n", "n_undirected.add_edge('b', 'd')\n", "n_undirected.plot()" - ] - }, - { - "cell_type": "code", - "execution_count": 3, + ], + "outputs": [], "metadata": { "execution": { - "iopub.execute_input": "2021-05-21T08:57:16.063394Z", - "iopub.status.busy": "2021-05-21T08:57:16.062932Z", - "iopub.status.idle": "2021-05-21T08:57:16.067423Z", - "shell.execute_reply": "2021-05-21T08:57:16.067016Z" - } - }, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": "", - "text/html": "\n
\n
\n\n" - }, - "metadata": {} + "iopub.execute_input": "2021-05-21T08:57:16.050824Z", + "iopub.status.busy": "2021-05-21T08:57:16.050360Z", + "iopub.status.idle": "2021-05-21T08:57:16.056826Z", + "shell.execute_reply": "2021-05-21T08:57:16.057195Z" } - ], + } + }, + { + "cell_type": "code", + "execution_count": null, "source": [ "n_directed = pp.Network(directed=True)\n", "n_directed.add_edge('a', 'b')\n", @@ -131,20 +95,33 @@ "n_directed.add_edge('d', 'f')\n", "n_directed.add_edge('b', 'd')\n", "n_directed.plot()" - ] + ], + "outputs": [], + "metadata": { + "execution": { + "iopub.execute_input": "2021-05-21T08:57:16.063394Z", + "iopub.status.busy": "2021-05-21T08:57:16.062932Z", + "iopub.status.idle": "2021-05-21T08:57:16.067423Z", + "shell.execute_reply": "2021-05-21T08:57:16.067016Z" + } + } }, { "cell_type": "markdown", - "metadata": {}, "source": [ "## Degree Centrality\n", "\n", "A simple, local notion of node importance in networks can be defined based on the degrees of nodes. In `pathpy` we can compute the (in- or out-)degrees of nodes as follows:" - ] + ], + "metadata": {} }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, + "source": [ + "n_undirected.degrees()" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.071088Z", @@ -152,26 +129,15 @@ "iopub.status.idle": "2021-05-21T08:57:16.074330Z", "shell.execute_reply": "2021-05-21T08:57:16.073654Z" } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "{'a': 2, 'b': 3, 'c': 2, 'd': 4, 'e': 2, 'f': 3, 'g': 2}" - ] - }, - "metadata": {}, - "execution_count": 4 - } - ], - "source": [ - "n_undirected.degrees()" - ] + } }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, + "source": [ + "n_directed.indegrees()" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.080201Z", @@ -179,26 +145,15 @@ "iopub.status.idle": "2021-05-21T08:57:16.082069Z", "shell.execute_reply": "2021-05-21T08:57:16.082689Z" } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "{'a': 1, 'b': 1, 'c': 1, 'd': 2, 'e': 1, 'f': 2, 'g': 1}" - ] - }, - "metadata": {}, - "execution_count": 5 - } - ], - "source": [ - "n_directed.indegrees()" - ] + } }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, + "source": [ + "n_directed.outdegrees()" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.087948Z", @@ -206,33 +161,22 @@ "iopub.status.idle": "2021-05-21T08:57:16.090618Z", "shell.execute_reply": "2021-05-21T08:57:16.090067Z" } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "{'a': 1, 'b': 2, 'c': 1, 'd': 2, 'e': 1, 'f': 1, 'g': 1}" - ] - }, - "metadata": {}, - "execution_count": 6 - } - ], - "source": [ - "n_directed.outdegrees()" - ] + } }, { "cell_type": "markdown", - "metadata": {}, "source": [ "In order to provide a unified API to all centrality measures, `pathpy` additionally includes a `degree_centrality` function in the module `pp.algorithms.centralities`. Using the `mode` parameter, we can switch between degre, in-, or out-degree." - ] + ], + "metadata": {} }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, + "source": [ + "pp.algorithms.centralities.degree_centrality(n_undirected)" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.094198Z", @@ -240,26 +184,15 @@ "iopub.status.idle": "2021-05-21T08:57:16.097035Z", "shell.execute_reply": "2021-05-21T08:57:16.096626Z" } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "{'a': 2, 'b': 3, 'c': 2, 'd': 4, 'e': 2, 'f': 3, 'g': 2}" - ] - }, - "metadata": {}, - "execution_count": 7 - } - ], - "source": [ - "pp.algorithms.centralities.degree_centrality(n_undirected)" - ] + } }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, + "source": [ + "pp.algorithms.centralities.degree_centrality(n_directed, mode='indegree')" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.102237Z", @@ -267,26 +200,15 @@ "iopub.status.idle": "2021-05-21T08:57:16.104847Z", "shell.execute_reply": "2021-05-21T08:57:16.105208Z" } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "{'a': 1, 'b': 1, 'c': 1, 'd': 2, 'e': 1, 'f': 2, 'g': 1}" - ] - }, - "metadata": {}, - "execution_count": 8 - } - ], - "source": [ - "pp.algorithms.centralities.degree_centrality(n_directed, mode='indegree')" - ] + } }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, + "source": [ + "pp.algorithms.centralities.degree_centrality(n_directed, mode='outdegree')" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.110721Z", @@ -294,33 +216,25 @@ "iopub.status.idle": "2021-05-21T08:57:16.113957Z", "shell.execute_reply": "2021-05-21T08:57:16.113541Z" } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "{'a': 1, 'b': 2, 'c': 1, 'd': 2, 'e': 1, 'f': 1, 'g': 1}" - ] - }, - "metadata": {}, - "execution_count": 9 - } - ], - "source": [ - "pp.algorithms.centralities.degree_centrality(n_directed, mode='outdegree')" - ] + } }, { "cell_type": "markdown", - "metadata": {}, "source": [ "A common task in network analysis is the ranking of nodes by centrality. Since dictionaries in `python` are not ordered, this requires a different data structure. To simplify this frequent task, `pathpy` comes with a `rank_centralities` function that takes an unordered dictionary with centrality values as parameter, and returns a list of tuples with node uids and centrality values that are arranged in descending order:" - ] + ], + "metadata": {} }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, + "source": [ + "ranking = pp.algorithms.centralities.rank_centralities(pp.algorithms.centralities.degree_centrality(n_undirected))\n", + "print(ranking)\n", + "\n", + "print('The most important node is', ranking[0][0])" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.119027Z", @@ -328,35 +242,24 @@ "iopub.status.idle": "2021-05-21T08:57:16.121694Z", "shell.execute_reply": "2021-05-21T08:57:16.122299Z" } - }, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "[('d', 4), ('f', 3), ('b', 3), ('g', 2), ('e', 2), ('c', 2), ('a', 2)]\nThe most important node is d\n" - ] - } - ], - "source": [ - "ranking = pp.algorithms.centralities.rank_centralities(pp.algorithms.centralities.degree_centrality(n_undirected))\n", - "print(ranking)\n", - "\n", - "print('The most important node is', ranking[0][0])" - ] + } }, { "cell_type": "markdown", - "metadata": {}, "source": [ "## Centrality measures in `pathpy`\n", "\n", "To obtain a centrality measure that actually considers the topology of links (and not only the number of links incident to nodes) we can use the `centralities` module in `pathpy.algorithms`. " - ] + ], + "metadata": {} }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, + "source": [ + "pp.algorithms.centralities.closeness_centrality(n_undirected)" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.136270Z", @@ -364,33 +267,15 @@ "iopub.status.idle": "2021-05-21T08:57:16.138974Z", "shell.execute_reply": "2021-05-21T08:57:16.138263Z" } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "defaultdict(float,\n", - " {'a': 0.07692307692307693,\n", - " 'b': 0.1111111111111111,\n", - " 'c': 0.07692307692307693,\n", - " 'd': 0.125,\n", - " 'e': 0.08333333333333333,\n", - " 'f': 0.09090909090909091,\n", - " 'g': 0.08333333333333333})" - ] - }, - "metadata": {}, - "execution_count": 11 - } - ], - "source": [ - "pp.algorithms.centralities.closeness_centrality(n_undirected)" - ] + } }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, + "source": [ + "pp.algorithms.centralities.closeness_centrality(n_undirected, normalized=True)" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.146837Z", @@ -398,40 +283,22 @@ "iopub.status.idle": "2021-05-21T08:57:16.148704Z", "shell.execute_reply": "2021-05-21T08:57:16.149325Z" } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "defaultdict(float,\n", - " {'a': 0.46153846153846156,\n", - " 'b': 0.6666666666666666,\n", - " 'c': 0.46153846153846156,\n", - " 'd': 0.75,\n", - " 'e': 0.5,\n", - " 'f': 0.5454545454545454,\n", - " 'g': 0.5})" - ] - }, - "metadata": {}, - "execution_count": 12 - } - ], - "source": [ - "pp.algorithms.centralities.closeness_centrality(n_undirected, normalized=True)" - ] + } }, { "cell_type": "markdown", - "metadata": {}, "source": [ "Alternatively, the same methods are also available as members of the Network class, which allows us to directly calculate them on an instance:" - ] + ], + "metadata": {} }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, + "source": [ + "pp.algorithms.centralities.rank_centralities(n_undirected.betweenness_centrality())" + ], + "outputs": [], "metadata": { "execution": { "iopub.execute_input": "2021-05-21T08:57:16.156375Z", @@ -439,59 +306,27 @@ "iopub.status.idle": "2021-05-21T08:57:16.159166Z", "shell.execute_reply": "2021-05-21T08:57:16.158467Z" } - }, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "[('d', 19.0),\n", - " ('b', 16.0),\n", - " ('f', 1.0),\n", - " ('a', 0.0),\n", - " ('e', 0.0),\n", - " ('c', 0.0),\n", - " ('g', 0.0)]" - ] - }, - "metadata": {}, - "execution_count": 13 - } - ], - "source": [ - "pp.algorithms.centralities.rank_centralities(n_undirected.betweenness_centrality())" - ] + } }, { "cell_type": "markdown", - "metadata": {}, "source": [ "# todo\n", "\n", "datenbank highschoolabklären und visualiesirung hinzufügen" - ] + ], + "metadata": {} }, { "cell_type": "markdown", - "metadata": {}, "source": [ "# Path Centralities" - ] + ], + "metadata": {} }, { "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "output_type": "display_data", - "data": { - "text/plain": "", - "text/html": "\n
\n
\n\n" - }, - "metadata": {} - } - ], + "execution_count": null, "source": [ "n = pp.Network(directed=True)\n", "n.add_edge('a', 'x')\n", @@ -499,175 +334,88 @@ "n.add_edge('x', 'c')\n", "n.add_edge('x', 'd')\n", "n.plot()" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "output_type": "stream", - "name": "stdout", - "text": [ - "PathPyCounter({'0x250e243a278': 2, '0x250e243a358': 2})\n" - ] - } - ], + "execution_count": null, "source": [ "pc = pp.PathCollection()\n", "pc.add(n.nodes['a'], n.nodes['x'], n.nodes['c'], count=2)\n", "pc.add(n.nodes['b'], n.nodes['x'], n.nodes['d'], count=2)\n", "print(pc.counter)" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "array([[ 0., 1., inf, 2., 2.],\n", - " [inf, 0., inf, 1., 1.],\n", - " [inf, 1., 0., 2., 2.],\n", - " [inf, inf, inf, 0., inf],\n", - " [inf, inf, inf, inf, 0.]])" - ] - }, - "metadata": {}, - "execution_count": 16 - } - ], + "execution_count": null, "source": [ "pp.algorithms.shortest_paths.distance_matrix(n)" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "defaultdict(float, {'a': 2.0, 'x': 2.0, 'b': 2.0, 'c': 0.0, 'd': 0.0})" - ] - }, - "metadata": {}, - "execution_count": 17 - } - ], + "execution_count": null, "source": [ "pp.algorithms.closeness_centrality(n, disconnected=True)" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "defaultdict(float, {'x': 4.0, 'c': 0.0, 'b': 0.0, 'd': 0.0, 'a': 0.0})" - ] - }, - "metadata": {}, - "execution_count": 18 - } - ], + "execution_count": null, "source": [ "pp.algorithms.centralities.betweenness_centrality(n)" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "defaultdict(.()>,\n", - " {'a': defaultdict(...()>,\n", - " {'a': 0, 'c': 2}),\n", - " 'x': defaultdict(...()>,\n", - " {'x': 0}),\n", - " 'c': defaultdict(...()>,\n", - " {'c': 0}),\n", - " 'b': defaultdict(...()>,\n", - " {'b': 0, 'd': 2}),\n", - " 'd': defaultdict(...()>,\n", - " {'d': 0})})" - ] - }, - "metadata": {}, - "execution_count": 19 - } - ], + "execution_count": null, "source": [ "pp.algorithms.shortest_paths.distance_matrix(pc)" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "defaultdict(.()>,\n", - " {'a': 0.5, 'x': 0.0, 'c': 0.0, 'b': 0.5, 'd': 0.0})" - ] - }, - "metadata": {}, - "execution_count": 20 - } - ], + "execution_count": null, "source": [ "pp.algorithms.centralities.closeness_centrality(pc, disconnected=True)" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "output_type": "execute_result", - "data": { - "text/plain": [ - "defaultdict(float, {'x': 2.0, 'a': 0.0, 'c': 0.0, 'b': 0.0, 'd': 0.0})" - ] - }, - "metadata": {}, - "execution_count": 21 - } - ], + "execution_count": null, "source": [ "pp.algorithms.centralities.betweenness_centrality(pc)" - ] + ], + "outputs": [], + "metadata": {} }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "source": [], "outputs": [], - "source": [] + "metadata": {} } ], "metadata": { "kernelspec": { - "name": "python37364bitbaseconda0af53cac2fb5450b99ec78a7efde583f", - "display_name": "Python 3.7.3 64-bit ('base': conda)" + "name": "python3", + "display_name": "Python 3.9.6 64-bit ('pathp': venv)" }, "language_info": { "codemirror_mode": { @@ -679,12 +427,15 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.9.6" }, "metadata": { "interpreter": { "hash": "82db51cffef479cc4d0f53089378e5a2925f9e7adca31d741132ceba61ecca6f" } + }, + "interpreter": { + "hash": "cbc06d602e623f3da56a6fd8482a438fdef2ce96413bf7bd183f2e65bbc2f388" } }, "nbformat": 4, diff --git a/pathpy/algorithms/community_detection.py b/pathpy/algorithms/community_detection.py index 3fc26f7..1863659 100644 --- a/pathpy/algorithms/community_detection.py +++ b/pathpy/algorithms/community_detection.py @@ -46,7 +46,7 @@ def modularity_maximisation(network: Network, network: Network - Object of the py:Network class. + :py:class:`Network` object that contains the network. iterations: int = 1000 diff --git a/pathpy/algorithms/evaluation.py b/pathpy/algorithms/evaluation.py index 731051b..05f30b9 100644 --- a/pathpy/algorithms/evaluation.py +++ b/pathpy/algorithms/evaluation.py @@ -116,7 +116,7 @@ def _(network: TemporalNetwork, test_size: Optional[float]=0.25, train_size: Opt network: TemporalNetwork - The temporal network for which the train/test split shall be performed. + The :py:class:`TemporalNetwork` object that contains the network for which the train/test split is performed. test_size: Optional[float] = 0.25 @@ -189,7 +189,7 @@ def shuffle_temporal_network(net: TemporalNetwork): ---------- net: TemporalNetwork - The temporal network for which the shuffle is to be performed. + The :py:class:`TemporalNetwork` object for which the shuffle is to be performed. Returns ------- diff --git a/pathpy/algorithms/shortest_paths.py b/pathpy/algorithms/shortest_paths.py index 6436795..8cde062 100644 --- a/pathpy/algorithms/shortest_paths.py +++ b/pathpy/algorithms/shortest_paths.py @@ -207,9 +207,13 @@ def single_source_shortest_paths(network: Network, The uid of the source node - weight : Union[bool, str, None] = None + weight : bool = None Weight of the network edges, if weighted + + Returns + ------- + Array with the distance of each node corresponding the index """ Q: dict = dict() dist = dict() @@ -283,7 +287,7 @@ def shortest_path_tree(network: Network, The uid of the root node - weight : Union[bool, str, None] = None + weight : bool = None Weight of the network edges, if weighted """ diff --git a/pathpy/algorithms/trees.py b/pathpy/algorithms/trees.py index a7a3728..eb42387 100644 --- a/pathpy/algorithms/trees.py +++ b/pathpy/algorithms/trees.py @@ -27,7 +27,14 @@ def check_tree(network: Network): - + """Returns if the Networks' Graph is a rooted tree. + + Parameters + ---------- + network : Network + + The :py:class:`Network` object + """ if network.directed: # identify node with zero indegree @@ -64,6 +71,19 @@ def dfs(network: Network, node: str): def tree_size(network: Network, node: str): + """ Returns the size of the graph tree, using the passed node as root. + + Parameters + ---------- + + network : Network + + The :py:class:`Network` object used for the tree + + node : str + + Identitifier of the root node + """ size = 1 for v in network.successors[node]: diff --git a/pathpy/io/csv.py b/pathpy/io/csv.py index 924df16..1dfa9f0 100644 --- a/pathpy/io/csv.py +++ b/pathpy/io/csv.py @@ -109,6 +109,11 @@ def read_network(filename: Optional[str] = None, **kwargs : Any Arbitrary keyword arguments that will be set as network-level attributes + + Returns + ------- + An object of the :py:class:`Network` generated from the csv file. + """ # pylint: disable=too-many-arguments @@ -164,6 +169,11 @@ def read_temporal_network(filename: Optional[str] = None, **kwargs : Any Arbitrary keyword arguments that will be set as network-level attributes + + Returns + ------- + An object of the :py:class:`Network` generated from the csv database. + """ # pylint: disable=too-many-arguments @@ -188,18 +198,30 @@ def read_pathcollection(filename: str, separator: str = ',', Parameters ---------- filename : str + path to edgelist file + separator : str + character separating the nodes + frequency : bool + is a frequency given? if ``True`` it is the last element in the edge (i.e. ``a,b,2``) + directed : bool + are the edges directed or undirected + maxlines : int + number of lines to read (useful to test large files). None means the entire file is read + Returns + ------- + An object of the :py:class:`PathCollection` with all the paths generated from the file. """ from pathpy.core.path import Path, PathCollection @@ -310,7 +332,42 @@ def write(network: Union[Network, TemporalNetwork], include_edge_uid: bool = False, export_indices: bool = False, **pdargs: Any) -> None: - """Stores all edges including edge attributes in a csv file.""" + """Stores all edges including edge attributes from a static or temporal network in a csv file. + + Parameters + ---------- + network : Network, TemporalNetwork + + An object of the :py:class:`Network` or :py:class:`TemporalNetwork` + + path_or_buf : Any = None + + This can be a string, a file buffer, or None (default). Follows + pandas.DataFrame.to_csv semantics. If a string filename is given, the + network will be saved in a file. If None, the csv file contents is + returned as a string. If a file buffer is given, the csv file will be + saved to the file. + + include_edge_ui : bool = False + + Whether to exclude edge uids in the exported csv file or not + (default). If this is set to True, each edge between nodes with uids v + and w will be exported to a line w,v. If this is set to False + (default), the uid of the edge will be additionally included, + i.e. exporting v,w,e_uid. + + export_indices : bool = False + + Whether or not to replace node uids by integer node indices. If False + (default), string node uids in pp.Network instance will be used. If + True, node integer indices are exported instead. + + **pdargs : Any + + Keyword args that will be passed to pandas.DataFrame.to_csv. This + allows full control of the csv export. + + """ frame = to_dataframe(network=network, include_edge_uid=include_edge_uid, export_indices=export_indices) From a3961a2cade95b9f1e7d60a05611b5e68d46dd73 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Sun, 22 Aug 2021 13:12:14 +0200 Subject: [PATCH 15/16] - --- pathpy/algorithms/shortest_paths.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathpy/algorithms/shortest_paths.py b/pathpy/algorithms/shortest_paths.py index 8cde062..ca9bf66 100644 --- a/pathpy/algorithms/shortest_paths.py +++ b/pathpy/algorithms/shortest_paths.py @@ -209,7 +209,7 @@ def single_source_shortest_paths(network: Network, weight : bool = None - Weight of the network edges, if weighted + If True cheapest paths will be calculated. Returns ------- From 804380d3b12c1a865aee02df6873ef03876f2f39 Mon Sep 17 00:00:00 2001 From: Max Kortenbruck Date: Sun, 22 Aug 2021 13:13:13 +0200 Subject: [PATCH 16/16] - --- pathpy/algorithms/shortest_paths.py | 2 +- pathpy/core/temporal.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pathpy/algorithms/shortest_paths.py b/pathpy/algorithms/shortest_paths.py index ca9bf66..34c6994 100644 --- a/pathpy/algorithms/shortest_paths.py +++ b/pathpy/algorithms/shortest_paths.py @@ -289,7 +289,7 @@ def shortest_path_tree(network: Network, weight : bool = None - Weight of the network edges, if weighted + f True cheapest paths will be calculated. """ n_tree = net.Network(directed=True) diff --git a/pathpy/core/temporal.py b/pathpy/core/temporal.py index c3603dc..27cad35 100644 --- a/pathpy/core/temporal.py +++ b/pathpy/core/temporal.py @@ -31,7 +31,7 @@ class TemporalPathPyObject(PathPyObject): uid : Optional[str] = None - The parameter ``uid`` is the unique identifier for the path object. T + The parameter ``uid`` is the unique identifier for the path object. kwargs : Any