Skip to content

Commit df38b76

Browse files
committed
Rename G graph, iterate through sorted dicts of node metrics.
1 parent af0b03a commit df38b76

File tree

2 files changed

+72
-102
lines changed

2 files changed

+72
-102
lines changed

brainx/metrics.py

Lines changed: 66 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
# Functions
1414
#-----------------------------------------------------------------------------
1515

16-
def inter_node_distances(G, n_nodes):
17-
"""Compute the shortest path lengths between all nodes in G.
16+
def inter_node_distances(graph):
17+
"""Compute the shortest path lengths between all nodes in graph.
1818
1919
This performs the same operation as NetworkX's
2020
all_pairs_shortest_path_lengths with two exceptions: Here, self
@@ -25,24 +25,17 @@ def inter_node_distances(G, n_nodes):
2525
2626
Parameters
2727
----------
28-
G: networkx Graph
28+
graph: networkx Graph
2929
An undirected graph.
3030
31-
n_nodes: integer
32-
Number of nodes in G.
33-
3431
Returns
3532
-------
3633
lengths: dictionary
3734
Dictionary of shortest path lengths keyed by source and target.
3835
39-
Notes
40-
-----
41-
This function assumes the nodes are labeled 0 to n_nodes - 1.
42-
4336
"""
44-
lengths = nx.all_pairs_shortest_path_length(G)
45-
node_labels = range(n_nodes)
37+
lengths = nx.all_pairs_shortest_path_length(graph)
38+
node_labels = sorted(lengths)
4639
for src in node_labels:
4740
lengths[src].pop(src)
4841
for targ in node_labels:
@@ -66,17 +59,14 @@ def compute_sigma(arr,clustarr,lparr):
6659
return out
6760

6861

69-
def nodal_pathlengths(G, n_nodes):
62+
def nodal_pathlengths(graph):
7063
"""Compute mean path length for each node.
7164
7265
Parameters
7366
----------
74-
G: networkx Graph
67+
graph: networkx Graph
7568
An undirected graph.
7669
77-
n_nodes: integer
78-
Number of nodes in G.
79-
8070
Returns
8171
-------
8272
nodal_means: numpy array
@@ -85,28 +75,24 @@ def nodal_pathlengths(G, n_nodes):
8575
8676
Notes
8777
-----
88-
This function assumes the nodes are labeled 0 to n_nodes - 1.
89-
9078
Per the Brain Connectivity Toolbox for Matlab, the distance between
9179
one node and another that cannot be reached from it is set to
9280
infinity.
9381
9482
"""
95-
lengths = inter_node_distances(G, n_nodes)
96-
# It's important we iterate through range(n_nodes) rather than the keys
97-
# of lengths, as the keys are not guaranteed to be in ascending order.
98-
nodal_means = [np.mean(lengths[src].values()) for src in range(n_nodes)]
83+
lengths = inter_node_distances(graph)
84+
nodal_means = [np.mean(lengths[src].values()) for src in sorted(lengths)]
9985
return np.array(nodal_means)
10086

10187

102-
def assert_no_selfloops(G):
103-
"""Raise an error if the graph G has any selfloops.
88+
def assert_no_selfloops(graph):
89+
"""Raise an error if the graph graph has any selfloops.
10490
"""
105-
if G.nodes_with_selfloops():
91+
if graph.nodes_with_selfloops():
10692
raise ValueError("input graph can not have selfloops")
10793

10894

109-
def path_lengths(G):
95+
def path_lengths(graph):
11096
"""Compute array of all shortest path lengths for the given graph.
11197
11298
The length of the output array is the number of unique pairs of nodes that
@@ -118,12 +104,12 @@ def path_lengths(G):
118104
119105
Parameters
120106
----------
121-
G : an undirected graph object.
107+
graph : an undirected graph object.
122108
"""
123109

124-
assert_no_selfloops(G)
110+
assert_no_selfloops(graph)
125111

126-
length = nx.all_pairs_shortest_path_length(G)
112+
length = nx.all_pairs_shortest_path_length(graph)
127113
paths = []
128114
seen = set()
129115
for src,targets in length.iteritems():
@@ -136,7 +122,7 @@ def path_lengths(G):
136122

137123

138124
#@profile
139-
def path_lengthsSPARSE(G):
125+
def path_lengthsSPARSE(graph):
140126
"""Compute array of all shortest path lengths for the given graph.
141127
142128
XXX - implementation using scipy.sparse. This might be faster for very
@@ -153,14 +139,14 @@ def path_lengthsSPARSE(G):
153139
154140
Parameters
155141
----------
156-
G : an undirected graph object.
142+
graph : an undirected graph object.
157143
"""
158144

159-
assert_no_selfloops(G)
145+
assert_no_selfloops(graph)
160146

161-
length = nx.all_pairs_shortest_path_length(G)
147+
length = nx.all_pairs_shortest_path_length(graph)
162148

163-
nnod = G.number_of_nodes()
149+
nnod = graph.number_of_nodes()
164150
paths_mat = sparse.dok_matrix((nnod,nnod))
165151

166152
for src,targets in length.iteritems():
@@ -170,66 +156,59 @@ def path_lengthsSPARSE(G):
170156
return sparse.triu(paths_mat,1).data
171157

172158

173-
def glob_efficiency(G):
159+
def glob_efficiency(graph):
174160
"""Compute array of global efficiency for the given graph.
175161
176162
Global efficiency: returns a list of the inverse path length matrix
177163
across all nodes The mean of this value is equal to the global efficiency
178164
of the network."""
179165

180-
return 1.0/path_lengths(G)
166+
return 1.0/path_lengths(graph)
181167

182168

183-
def nodal_efficiency(G, n_nodes):
184-
"""Return array with nodal efficiency for each node in G.
169+
def nodal_efficiency(graph):
170+
"""Return array with nodal efficiency for each node in graph.
185171
186172
See Achard and Bullmore (2007, PLoS Comput Biol) for the definition
187173
of nodal efficiency.
188174
189175
Parameters
190176
----------
191-
G: networkx Graph
177+
graph: networkx Graph
192178
An undirected graph.
193179
194-
n_nodes: integer
195-
Number of nodes in G.
196-
197180
Returns
198181
-------
199182
nodal_efficiencies: numpy array
200-
An array with the nodal efficiency for each node in G, in
183+
An array with the nodal efficiency for each node in graph, in
201184
the order specified by node_labels. The array is in ascending
202185
order of node labels.
203186
204187
Notes
205188
-----
206-
This function assumes the nodes are labeled 0 to n_nodes - 1.
207-
208189
Per the Brain Connectivity Toolbox for Matlab, the distance between
209190
one node and another that cannot be reached from it is set to
210191
infinity.
211192
212193
"""
213-
nodal_efficiencies = np.zeros(n_nodes, dtype=float)
214-
lengths = inter_node_distances(G, n_nodes)
215-
# It's important we iterate through range(n_nodes) rather than the keys
216-
# of lengths, as the keys are not guaranteed to be in ascending order.
217-
for src in range(n_nodes):
194+
lengths = inter_node_distances(graph)
195+
nodal_efficiencies = np.zeros(len(lengths), dtype=float)
196+
for src in sorted(lengths):
218197
inverse_paths = [1.0 / val for val in lengths[src].itervalues()]
219198
nodal_efficiencies[src] = np.mean(inverse_paths)
220199
return nodal_efficiencies
221200

222201

223-
def local_efficiency(G):
202+
def local_efficiency(graph):
224203
"""Compute array of global efficiency for the given grap.h
225204
226205
Local efficiency: returns a list of paths that represent the nodal
227206
efficiencies across all nodes with their direct neighbors"""
228207

229208
nodepaths=[]
230-
length=nx.all_pairs_shortest_path_length(G)
231-
for n in G.nodes():
232-
nneighb= nx.neighbors(G,n)
209+
length=nx.all_pairs_shortest_path_length(graph)
210+
for n in graph.nodes():
211+
nneighb= nx.neighbors(graph,n)
233212

234213
paths=[]
235214
for src,targets in length.iteritems():
@@ -251,18 +230,18 @@ def local_efficiency(G):
251230
return np.array(nodepaths)
252231

253232

254-
def local_efficiency(G):
233+
def local_efficiency(graph):
255234
"""Compute array of local efficiency for the given graph.
256235
257236
Local efficiency: returns a list of paths that represent the nodal
258237
efficiencies across all nodes with their direct neighbors"""
259238

260-
assert_no_selfloops(G)
239+
assert_no_selfloops(graph)
261240

262241
nodepaths = []
263-
length = nx.all_pairs_shortest_path_length(G)
264-
for n in G:
265-
nneighb = set(nx.neighbors(G,n))
242+
length = nx.all_pairs_shortest_path_length(graph)
243+
for n in graph:
244+
nneighb = set(nx.neighbors(graph,n))
266245

267246
paths = []
268247
for nei in nneighb:
@@ -279,20 +258,20 @@ def local_efficiency(G):
279258
return np.array(nodepaths)
280259

281260

282-
def dynamical_importance(G):
283-
"""Compute dynamical importance for G.
261+
def dynamical_importance(graph):
262+
"""Compute dynamical importance for graph.
284263
285264
Ref: Restrepo, Ott, Hunt. Phys. Rev. Lett. 97, 094102 (2006)
286265
"""
287266
# spectrum of the original graph
288-
eigvals = nx.adjacency_spectrum(G)
267+
eigvals = nx.adjacency_spectrum(graph)
289268
lambda0 = eigvals[0]
290-
# Now, loop over all nodes in G, and for each, make a copy of G, remove
269+
# Now, loop over all nodes in graph, and for each, make a copy of graph, remove
291270
# that node, and compute the change in lambda.
292-
nnod = G.number_of_nodes()
271+
nnod = graph.number_of_nodes()
293272
dyimp = np.empty(nnod,float)
294273
for n in range(nnod):
295-
gn = G.copy()
274+
gn = graph.copy()
296275
gn.remove_node(n)
297276
lambda_n = nx.adjacency_spectrum(gn)[0]
298277
dyimp[n] = lambda0 - lambda_n
@@ -301,22 +280,22 @@ def dynamical_importance(G):
301280
return dyimp
302281

303282

304-
def weighted_degree(G):
283+
def weighted_degree(graph):
305284
"""Return an array of degrees that takes weights into account.
306285
307286
For unweighted graphs, this is the same as the normal degree() method
308287
(though we return an array instead of a list).
309288
"""
310-
amat = nx.adj_matrix(G).A # get a normal array out of it
289+
amat = nx.adj_matrix(graph).A # get a normal array out of it
311290
return abs(amat).sum(0) # weights are sums across rows
312291

313292

314-
def graph_summary(G):
293+
def graph_summary(graph):
315294
"""Compute a set of statistics summarizing the structure of a graph.
316295
317296
Parameters
318297
----------
319-
G : a graph object.
298+
graph : a graph object.
320299
321300
threshold : float, optional
322301
@@ -326,26 +305,23 @@ def graph_summary(G):
326305
"""
327306

328307
# Average path length
329-
lp = path_lengths(G)
330-
clust = np.array(nx.clustering(G).values())
331-
glob_eff = glob_efficiency(G)
332-
loc_eff = local_efficiency(G)
308+
lp = path_lengths(graph)
309+
clust = np.array(nx.clustering(graph).values())
310+
glob_eff = glob_efficiency(graph)
311+
loc_eff = local_efficiency(graph)
333312

334313
return dict( lp=lp.mean(), clust=clust.mean(), glob_eff=glob_eff.mean(),
335314
loc_eff=loc_eff.mean() )
336315

337316

338-
def nodal_summaryOut(G, n_nodes):
317+
def nodal_summaryOut(graph):
339318
"""Compute statistics for individual nodes.
340319
341320
Parameters
342321
----------
343-
G: networkx graph
322+
graph: networkx graph
344323
An undirected graph.
345324
346-
n_nodes: integer
347-
Number of nodes in G.
348-
349325
Returns
350326
-------
351327
dictionary
@@ -357,22 +333,16 @@ def nodal_summaryOut(G, n_nodes):
357333
ascending order of node labels.
358334
359335
"""
360-
lp = nodal_pathlengths(G, n_nodes)
361-
# As stated in the Python documentation, "Keys and values are listed in an
362-
# arbitrary order which is non-random, varies across Python
363-
# implementations, and depends on the dictionary's history of insertions
364-
# and deletions." Thus, we cannot expect, e.g., nx.clustering(G)
365-
# to have the nodes listed in ascending order, as we desire.
366-
node_labels = range(n_nodes)
367-
clust_dict = nx.clustering(G)
368-
clust = np.array([clust_dict[n] for n in node_labels])
369-
b_cen_dict = nx.betweenness_centrality(G)
370-
b_cen = np.array([b_cen_dict[n] for n in node_labels])
371-
c_cen_dict = nx.closeness_centrality(G)
372-
c_cen = np.array([c_cen_dict[n] for n in node_labels])
373-
nod_eff = nodal_efficiency(G, n_nodes)
374-
loc_eff = local_efficiency(G)
375-
deg_dict = G.degree()
376-
deg = [deg_dict[n] for n in node_labels]
336+
lp = nodal_pathlengths(graph)
337+
clust_dict = nx.clustering(graph)
338+
clust = np.array([clust_dict[n] for n in sorted(clust_dict)])
339+
b_cen_dict = nx.betweenness_centrality(graph)
340+
b_cen = np.array([b_cen_dict[n] for n in sorted(b_cen_dict)])
341+
c_cen_dict = nx.closeness_centrality(graph)
342+
c_cen = np.array([c_cen_dict[n] for n in sorted(c_cen_dict)])
343+
nod_eff = nodal_efficiency(graph)
344+
loc_eff = local_efficiency(graph)
345+
deg_dict = graph.degree()
346+
deg = [deg_dict[n] for n in sorted(deg_dict)]
377347
return dict(lp=lp, clust=clust, b_cen=b_cen, c_cen=c_cen, nod_eff=nod_eff,
378348
loc_eff=loc_eff, deg=deg)

0 commit comments

Comments
 (0)