comparison env/lib/python3.9/site-packages/networkx/algorithms/centrality/trophic.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 """Trophic levels"""
2 import networkx as nx
3
4 from networkx.utils import not_implemented_for
5
6 __all__ = ["trophic_levels", "trophic_differences", "trophic_incoherence_parameter"]
7
8
9 @not_implemented_for("undirected")
10 def trophic_levels(G, weight="weight"):
11 r"""Compute the trophic levels of nodes.
12
13 The trophic level of a node $i$ is
14
15 .. math::
16
17 s_i = 1 + \frac{1}{k^{in}_i} \sum_{j} a_{ij} s_j
18
19 where $k^{in}_i$ is the in-degree of i
20
21 .. math::
22
23 k^{in}_i = \sum_{j} a_{ij}
24
25 and nodes with $k^{in}_i = 0$ have $s_i = 1$ by convention.
26
27 These are calculated using the method outlined in Levine [1]_.
28
29 Parameters
30 ----------
31 G : DiGraph
32 A directed networkx graph
33
34 Returns
35 -------
36 nodes : dict
37 Dictionary of nodes with trophic level as the vale.
38
39 References
40 ----------
41 .. [1] Stephen Levine (1980) J. theor. Biol. 83, 195-207
42 """
43 try:
44 import numpy as np
45 except ImportError as e:
46 raise ImportError("trophic_levels() requires NumPy: http://numpy.org/") from e
47
48 # find adjacency matrix
49 a = nx.adjacency_matrix(G, weight=weight).T.toarray()
50
51 # drop rows/columns where in-degree is zero
52 rowsum = np.sum(a, axis=1)
53 p = a[rowsum != 0][:, rowsum != 0]
54 # normalise so sum of in-degree weights is 1 along each row
55 p = p / rowsum[rowsum != 0][:, np.newaxis]
56
57 # calculate trophic levels
58 nn = p.shape[0]
59 i = np.eye(nn)
60 try:
61 n = np.linalg.inv(i - p)
62 except np.linalg.LinAlgError as err:
63 # LinAlgError is raised when there is a non-basal node
64 msg = (
65 "Trophic levels are only defined for graphs where every "
66 + "node has a path from a basal node (basal nodes are nodes "
67 + "with no incoming edges)."
68 )
69 raise nx.NetworkXError(msg) from err
70 y = n.sum(axis=1) + 1
71
72 levels = {}
73
74 # all nodes with in-degree zero have trophic level == 1
75 zero_node_ids = (node_id for node_id, degree in G.in_degree if degree == 0)
76 for node_id in zero_node_ids:
77 levels[node_id] = 1
78
79 # all other nodes have levels as calculated
80 nonzero_node_ids = (node_id for node_id, degree in G.in_degree if degree != 0)
81 for i, node_id in enumerate(nonzero_node_ids):
82 levels[node_id] = y[i]
83
84 return levels
85
86
87 @not_implemented_for("undirected")
88 def trophic_differences(G, weight="weight"):
89 r"""Compute the trophic differences of the edges of a directed graph.
90
91 The trophic difference $x_ij$ for each edge is defined in Johnson et al.
92 [1]_ as:
93
94 .. math::
95 x_ij = s_j - s_i
96
97 Where $s_i$ is the trophic level of node $i$.
98
99 Parameters
100 ----------
101 G : DiGraph
102 A directed networkx graph
103
104 Returns
105 -------
106 diffs : dict
107 Dictionary of edges with trophic differences as the value.
108
109 References
110 ----------
111 .. [1] Samuel Johnson, Virginia Dominguez-Garcia, Luca Donetti, Miguel A.
112 Munoz (2014) PNAS "Trophic coherence determines food-web stability"
113 """
114 levels = trophic_levels(G, weight=weight)
115 diffs = {}
116 for u, v in G.edges:
117 diffs[(u, v)] = levels[v] - levels[u]
118 return diffs
119
120
121 @not_implemented_for("undirected")
122 def trophic_incoherence_parameter(G, weight="weight", cannibalism=False):
123 r"""Compute the trophic incoherence parameter of a graph.
124
125 Trophic coherence is defined as the homogeneity of the distribution of
126 trophic distances: the more similar, the more coherent. This is measured by
127 the standard deviation of the trophic differences and referred to as the
128 trophic incoherence parameter $q$ by [1].
129
130 Parameters
131 ----------
132 G : DiGraph
133 A directed networkx graph
134
135 cannibalism: Boolean
136 If set to False, self edges are not considered in the calculation
137
138 Returns
139 -------
140 trophic_incoherence_parameter : float
141 The trophic coherence of a graph
142
143 References
144 ----------
145 .. [1] Samuel Johnson, Virginia Dominguez-Garcia, Luca Donetti, Miguel A.
146 Munoz (2014) PNAS "Trophic coherence determines food-web stability"
147 """
148 try:
149 import numpy as np
150 except ImportError as e:
151 raise ImportError(
152 "trophic_incoherence_parameter() requires NumPy: " "http://scipy.org/"
153 ) from e
154
155 if cannibalism:
156 diffs = trophic_differences(G, weight=weight)
157 else:
158 # If no cannibalism, remove self-edges
159 self_loops = list(nx.selfloop_edges(G))
160 if self_loops:
161 # Make a copy so we do not change G's edges in memory
162 G_2 = G.copy()
163 G_2.remove_edges_from(self_loops)
164 else:
165 # Avoid copy otherwise
166 G_2 = G
167 diffs = trophic_differences(G_2, weight=weight)
168 return np.std(list(diffs.values()))