Skip to content

Commit 45a7716

Browse files
authored
Merge pull request #118 from liuzhenqi77/add-spl
2 parents 4f2b50d + ae96e7c commit 45a7716

File tree

1 file changed

+154
-1
lines changed

1 file changed

+154
-1
lines changed

netneurotools/metrics.py

Lines changed: 154 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,160 @@
88
import numpy as np
99
from scipy.linalg import expm
1010
from scipy.stats import ttest_ind
11-
from bct import degrees_und
11+
from scipy.sparse.csgraph import shortest_path
12+
13+
try:
14+
from numba import njit
15+
use_numba = True
16+
except ImportError:
17+
use_numba = False
18+
19+
20+
def _binarize(W):
21+
"""
22+
Binarizes a matrix
23+
24+
Parameters
25+
----------
26+
W : (N, N) array_like
27+
Matrix to be binarized
28+
29+
Returns
30+
-------
31+
binarized : (N, N) numpy.ndarray
32+
Binarized matrix
33+
"""
34+
return (W > 0) * 1
35+
36+
37+
if use_numba:
38+
_binarize = njit(_binarize)
39+
40+
41+
def degrees_und(W):
42+
"""
43+
Computes the degree of each node in `W`
44+
45+
Parameters
46+
----------
47+
W : (N, N) array_like
48+
Unweighted, undirected connection weight array.
49+
Weighted array will be binarized prior to calculation.
50+
Directedness will be ignored (out degree / row sum taken).
51+
52+
Returns
53+
-------
54+
deg : (N,) numpy.ndarray
55+
Degree of each node in `W`
56+
"""
57+
return np.sum(_binarize(W), axis=0)
58+
59+
60+
def degrees_dir(W):
61+
"""
62+
Computes the in degree and out degree of each node in `W`
63+
64+
Parameters
65+
----------
66+
W : (N, N) array_like
67+
Unweighted, directed connection weight array.
68+
Weighted array will be binarized prior to calculation.
69+
70+
Returns
71+
-------
72+
deg_in : (N,) numpy.ndarray
73+
In-degree (column sum) of each node in `W`
74+
deg_out : (N,) numpy.ndarray
75+
Out-degree (row sum) of each node in `W`
76+
deg : (N,) numpy.ndarray
77+
Degree (in-degree + out-degree) of each node in `W`
78+
"""
79+
W_bin = _binarize(W)
80+
deg_in = np.sum(W_bin, axis=0)
81+
deg_out = np.sum(W_bin, axis=1)
82+
deg = deg_in + deg_out
83+
return deg_in, deg_out, deg
84+
85+
86+
def distance_wei_floyd(D):
87+
"""
88+
Computes the shortest path length between all pairs of nodes using
89+
Floyd-Warshall algorithm.
90+
91+
Parameters
92+
----------
93+
D : (N, N) array_like
94+
Connection length or distance matrix.
95+
Please do the weight-to-distance beforehand.
96+
97+
Returns
98+
-------
99+
spl_mat : (N, N) array_like
100+
Shortest path length matrix
101+
p_mat : (N, N) array_like
102+
Predecessor matrix returned from `scipy.sparse.csgraph.shortest_path`
103+
104+
Notes
105+
-----
106+
This function is a wrapper for `scipy.sparse.csgraph.shortest_path`.
107+
There may be more than one shortest path between two nodes, and we
108+
only return the first one found by the algorithm.
109+
110+
References
111+
----------
112+
.. [1] Floyd, R. W. (1962). Algorithm 97: shortest path. Communications of
113+
the ACM, 5(6), 345.
114+
.. [2] Roy, B. (1959). Transitivite et connexite. Comptes Rendus
115+
Hebdomadaires Des Seances De L Academie Des Sciences, 249(2), 216-218.
116+
.. [3] Warshall, S. (1962). A theorem on boolean matrices. Journal of the
117+
ACM (JACM), 9(1), 11-12.
118+
.. [4] https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm
119+
120+
See Also
121+
--------
122+
netneurotools.metrics.retrieve_shortest_paths
123+
"""
124+
spl_mat, p_mat = shortest_path(
125+
D, method="FW", directed=False, return_predecessors=True,
126+
unweighted=False, overwrite=False
127+
)
128+
return spl_mat, p_mat
129+
130+
131+
def retrieve_shortest_paths(s, t, p_mat):
132+
"""
133+
Returns the shortest paths between two nodes.
134+
135+
Parameters
136+
----------
137+
s : int
138+
Source node
139+
t : int
140+
Target node
141+
p_mat : (N, N) array_like
142+
Predecessor matrix returned from `distance_wei_floyd`
143+
144+
Returns
145+
-------
146+
path : list of int
147+
List of nodes in the shortest path from `s` to `t`. If no path
148+
exists, returns `[-1]`.
149+
150+
See Also
151+
--------
152+
netneurotools.metrics.distance_wei_floyd
153+
"""
154+
if p_mat[s, t] == -9999:
155+
return [-1]
156+
path = [t]
157+
while path[-1] != s:
158+
t = p_mat[s, t]
159+
path.append(t)
160+
return path[::-1]
161+
162+
163+
if use_numba:
164+
retrieve_shortest_paths = njit(retrieve_shortest_paths)
12165

13166

14167
def communicability_bin(adjacency, normalize=False):

0 commit comments

Comments
 (0)