66
77import numpy as np
88from scipy .linalg import expm
9-
9+ from scipy .stats import ttest_ind
10+ from bct import degrees_und
1011
1112def communicability_bin (adjacency , normalize = False ):
1213 """
@@ -99,3 +100,80 @@ def communicability_wei(adjacency):
99100 cmc [np .diag_indices_from (cmc )] = 0
100101
101102 return cmc
103+
104+ def rich_feeder_peripheral (x , sc , stat = 'median' ):
105+ """
106+ Calculates median or mean "connectivity" in rich (hub to hub), feeder (hub to non-hub),
107+ and peripheral (non-hub to non-hub) links.
108+
109+ This function takes a square symmetric correlation/connectivity matrix `x`
110+ and computes the median or mean value within rich, feeder, and peripheral links.
111+ Hubs are defined againt a threshold (from 0 to the maximum degree `k`,
112+ defined on the structural connectivity matrix, `sc`).
113+
114+
115+ Parameters
116+ ----------
117+ x : (N, N) symmetric numpy.ndarray.
118+ sc : (N, N) symmetric numpy.ndarray
119+ binary structural connectivity matrix
120+ stat : 'median' (default) or 'mean'.
121+ statistic to use over rich/feeder/peripheral links.
122+
123+ Returns
124+ -------
125+ rfp : (3, k) numpy.ndarray of median rich (0), feeder (1), and peripheral (2)
126+ values, defined by `x`. `k` is the maximum degree defined on `sc`.
127+ pvals : (3, k) numpy.ndarray p-value for each link, computed using Welch's t-test.
128+ Rich links are compared against non-rich links. Feeder links are
129+ compared against peripheral links. Peripheral links are compared
130+ against feeder links. T-test is two-sided.
131+
132+ Author
133+ ------
134+ This code was written by Justine Hansen who promises to fix and even
135+ optimize the code should any issues arise, provided you let her know.
136+
137+ """
138+ nnodes = len (sc )
139+ mask = np .triu (np .ones (nnodes ),1 ) > 0
140+ node_degree = degrees_und (sc )
141+ k = np .max (node_degree ).astype (np .int64 )
142+ rfp_label = np .zeros ((len (sc [mask ]),k ))
143+
144+ for i in range (k ): # for each degree threshold
145+ hub_idx = np .where (node_degree >= i ) # find the hubs
146+ hub = np .zeros ([nnodes ,1 ])
147+ hub [hub_idx ,:] = 1
148+
149+ rfp = np .zeros ([nnodes ,nnodes ]) # for each link, define rfp
150+ for ii in range (nnodes ):
151+ for iii in range (nnodes ):
152+ if hub [ii ] + hub [iii ] == 2 :
153+ rfp [ii ,iii ] = 1 # rich
154+ if hub [ii ] + hub [iii ] == 1 :
155+ rfp [ii ,iii ] = 2 # feeder
156+ if hub [ii ] + hub [iii ] == 0 :
157+ rfp [ii ,iii ] = 3 # peripheral
158+ rfp_label [:,i ] = rfp [mask ]
159+
160+ rfp = np .zeros ([3 ,k ])
161+ pvals = np .zeros ([3 ,k ])
162+ for i in range (k ):
163+
164+ if stat == 'median' :
165+ rfp [0 ,i ] = np .median (x [rfp_label [:,i ] == 1 ]) # rich
166+ rfp [1 ,i ] = np .median (x [rfp_label [:,i ] == 2 ]) # feeder
167+ rfp [2 ,i ] = np .median (x [rfp_label [:,i ] == 3 ]) # peripheral
168+
169+ if stat == 'mean' :
170+ rfp [0 ,i ] = np .mean (x [rfp_label [:,i ] == 1 ]) # rich
171+ rfp [1 ,i ] = np .mean (x [rfp_label [:,i ] == 2 ]) # feeder
172+ rfp [2 ,i ] = np .mean (x [rfp_label [:,i ] == 3 ]) # peripheral
173+
174+ # p-value
175+ _ , pvals [0 ,i ] = ttest_ind (x [rfp_label [:,i ] == 1 ], x [rfp_label [:,i ] != 1 ], equal_var = False ) # Welch's t-test
176+ _ , pvals [1 ,i ] = ttest_ind (x [rfp_label [:,i ] == 2 ], x [rfp_label [:,i ] == 3 ], equal_var = False )
177+ _ , pvals [2 ,i ] = ttest_ind (x [rfp_label [:,i ] == 3 ], x [rfp_label [:,i ] == 2 ], equal_var = False )
178+
179+ return rfp , pvals
0 commit comments