def density_thresholding(conn_matrix, thr, max_iters=10000, interval=0.01): """ Iteratively apply an absolute threshold to achieve a target density. Parameters ---------- conn_matrix : np.ndarray Weighted connectivity matrix thr : float Density value between 0-1. max_iters : int Maximum number of iterations for performing absolute thresholding. Default is 1000. interval : float Interval for increasing the absolute threshold for each iteration. Default is 0.01. Returns ------- conn_matrix : np.ndarray Thresholded connectivity matrix References ---------- .. [1] van Wijk, B. C. M., Stam, C. J., & Daffertshofer, A. (2010). Comparing brain networks of different size and connectivity density using graph theory. PLoS ONE. https://doi.org/10.1371/journal.pone.0013701 .. [2] Complex network measures of brain connectivity: Uses and interpretations. Rubinov M, Sporns O (2010) NeuroImage 52:1059-69. """ from pynets.core import thresholding np.fill_diagonal(conn_matrix, 0) work_thr = 0 i = 1 density = nx.density(nx.from_numpy_matrix(conn_matrix)) if float(thr) < float(density): while float(i) < max_iters and float(work_thr) < float(1): work_thr = float(work_thr) + float(interval) density = nx.density( nx.from_numpy_matrix( thresholding.threshold_absolute(conn_matrix, work_thr))) print("%s%d%s%.2f%s%.2f%s" % ('Iteration ', i, ' -- with Thresh: ', float(work_thr), ' and Density: ', float(density), '...')) if float(thr) >= float(density): conn_matrix = thresholding.threshold_absolute( conn_matrix, work_thr) break i = i + 1 else: print( 'Density of raw matrix is already greater than or equal to the target density requested' ) return conn_matrix
def density_thresholding(conn_matrix, thr, max_iters=10000, interval=0.01): """ Iteratively apply an absolute threshold to achieve a target density. Parameters ---------- conn_matrix : np.ndarray Weighted connectivity matrix thr : float Density value between 0-1. max_iters : int Maximum number of iterations for performing absolute thresholding. Default is 1000. interval : float Interval for increasing the absolute threshold for each iteration. Default is 0.01. Returns ------- conn_matrix : np.ndarray Thresholded connectivity matrix References ---------- .. Adapted from Adapted from bctpy """ from pynets.core import thresholding np.fill_diagonal(conn_matrix, 0) work_thr = 0 i = 1 density = nx.density(nx.from_numpy_matrix(conn_matrix)) if float(thr) < float(density): while float(i) < max_iters and float(work_thr) < float(1): work_thr = float(work_thr) + float(interval) density = nx.density( nx.from_numpy_matrix( thresholding.threshold_absolute(conn_matrix, work_thr))) print("%s%d%s%.2f%s%.2f%s" % ('Iteration ', i, ' -- with Thresh: ', float(work_thr), ' and Density: ', float(density), '...')) if float(thr) >= float(density): conn_matrix = thresholding.threshold_absolute( conn_matrix, work_thr) break i = i + 1 else: print( 'Density of raw matrix is already greater than or equal to the target density requested' ) return conn_matrix
def test_thr2prob(x, thr): s = thresholding.threshold_absolute(thresholding.normalize(x), thr) s[0][0] = 0.0000001 t = thresholding.thr2prob(s) assert float(len(t[np.logical_and(t < 0.001, t > 0)])) == float(0.0)
def test_density(x, thr): d_known = thresholding.est_density( thresholding.threshold_absolute(x, thr, copy=True)) x = thresholding.density_thresholding(x, d_known) d_test = thresholding.est_density(x) assert np.equal(np.round(d_known, 1), np.round(d_test, 1))
def test_threshold_absolute(x, thr, cp): s = thresholding.threshold_absolute(x, thr, copy=cp) s_test = [val for arr in s for val in arr if val >= thr] # search for value > thr assert round(np.sum(s), 10) == round(np.sum(s_test), 10)
def compare_motifs(struct_mat, func_mat, name, namer_dir, bins=20, N=4): ''' Compare motif structure and population across structural and functional graphs to achieve a homeostatic absolute threshold of each that optimizes multiplex community detection and analysis. Parameters ---------- in_mat : ndarray M x M Connectivity matrix thr : float Absolute threshold [0, 1]. mlib : list List of motif classes. Returns ------- mf : ndarray 1D vector listing the total motifs of size N for each class of mlib. References ---------- .. [1] Battiston, F., Nicosia, V., Chavez, M., & Latora, V. (2017). Multilayer motif analysis of brain networks. Chaos. https://doi.org/10.1063/1.4979282 ''' from pynets.stats.netmotifs import adaptivethresh from pynets.core.thresholding import threshold_absolute from pynets.core.thresholding import standardize from scipy import spatial from nilearn.connectome import sym_matrix_to_vec import pandas as pd import gc mlib = ['1113', '1122', '1223', '2222', '2233', '3333'] # Standardize structural graph struct_mat = standardize(struct_mat) dims_struct = struct_mat.shape[0] struct_mat[range(dims_struct), range(dims_struct)] = 0 at_struct = adaptivethresh(struct_mat, float(0.0), mlib, N) print("%s%s%s" % ('Layer 1 (structural) has: ', np.sum(at_struct), ' total motifs')) # Functional graph threshold window func_mat = standardize(func_mat) dims_func = func_mat.shape[0] func_mat[range(dims_func), range(dims_func)] = 0 tmin_func = func_mat.min() tmax_func = func_mat.max() threshes_func = np.linspace(tmin_func, tmax_func, bins) assert np.all( struct_mat == struct_mat.T), "Structural Matrix must be symmetric" assert np.all( func_mat == func_mat.T), "Functional Matrix must be symmetric" # Count motifs print("%s%s%s%s" % ('Mining ', N, '-node motifs: ', mlib)) motif_dict = {} motif_dict['struct'] = {} motif_dict['func'] = {} mat_dict = {} mat_dict['struct'] = sym_matrix_to_vec(struct_mat, discard_diagonal=True) mat_dict['funcs'] = {} for thr_func in threshes_func: # Count at_func = adaptivethresh(func_mat, float(thr_func), mlib, N) motif_dict['struct']["%s%s" % ('thr-', np.round(thr_func, 4))] = at_struct motif_dict['func']["%s%s" % ('thr-', np.round(thr_func, 4))] = at_func mat_dict['funcs']["%s%s" % ('thr-', np.round(thr_func, 4))] = sym_matrix_to_vec( threshold_absolute(func_mat, thr_func), discard_diagonal=True) print("%s%s%s%s%s" % ('Layer 2 (functional) with absolute threshold of: ', np.round(thr_func, 2), ' yields ', np.sum(at_func), ' total motifs')) gc.collect() df = pd.DataFrame(motif_dict) for idx in range(len(df)): df.set_value( df.index[idx], 'motif_dist', spatial.distance.cosine(df['struct'][idx], df['func'][idx])) df = df[pd.notnull(df['motif_dist'])] for idx in range(len(df)): df.set_value( df.index[idx], 'graph_dist_cosine', spatial.distance.cosine( mat_dict['struct'].reshape(-1, 1), mat_dict['funcs'][df.index[idx]].reshape(-1, 1))) df.set_value( df.index[idx], 'graph_dist_correlation', spatial.distance.correlation( mat_dict['struct'].reshape(-1, 1), mat_dict['funcs'][df.index[idx]].reshape(-1, 1))) df['struct_func_3333'] = np.zeros(len(df)) df['struct_func_2233'] = np.zeros(len(df)) df['struct_func_2222'] = np.zeros(len(df)) df['struct_func_1223'] = np.zeros(len(df)) df['struct_func_1122'] = np.zeros(len(df)) df['struct_func_1113'] = np.zeros(len(df)) df['struct_3333'] = np.zeros(len(df)) df['func_3333'] = np.zeros(len(df)) df['struct_2233'] = np.zeros(len(df)) df['func_2233'] = np.zeros(len(df)) df['struct_2222'] = np.zeros(len(df)) df['func_2222'] = np.zeros(len(df)) df['struct_1223'] = np.zeros(len(df)) df['func_1223'] = np.zeros(len(df)) df['struct_1122'] = np.zeros(len(df)) df['func_1122'] = np.zeros(len(df)) df['struct_1113'] = np.zeros(len(df)) df['func_1113'] = np.zeros(len(df)) for idx in range(len(df)): df.set_value(df.index[idx], 'struct_3333', df['struct'][idx][-1]) df.set_value(df.index[idx], 'func_3333', df['func'][idx][-1]) df.set_value(df.index[idx], 'struct_2233', df['struct'][idx][-2]) df.set_value(df.index[idx], 'func_2233', df['func'][idx][-2]) df.set_value(df.index[idx], 'struct_2222', df['struct'][idx][-3]) df.set_value(df.index[idx], 'func_2222', df['func'][idx][-3]) df.set_value(df.index[idx], 'struct_1223', df['struct'][idx][-4]) df.set_value(df.index[idx], 'func_1223', df['func'][idx][-4]) df.set_value(df.index[idx], 'struct_1122', df['struct'][idx][-5]) df.set_value(df.index[idx], 'func_1122', df['func'][idx][-5]) df.set_value(df.index[idx], 'struct_1113', df['struct'][idx][-6]) df.set_value(df.index[idx], 'func_1113', df['func'][idx][-6]) df['struct_func_3333'] = np.abs(df['struct_3333'] - df['func_3333']) df['struct_func_2233'] = np.abs(df['struct_2233'] - df['func_2233']) df['struct_func_2222'] = np.abs(df['struct_2222'] - df['func_2222']) df['struct_func_1223'] = np.abs(df['struct_1223'] - df['func_1223']) df['struct_func_1122'] = np.abs(df['struct_1122'] - df['func_1122']) df['struct_func_1113'] = np.abs(df['struct_1113'] - df['func_1113']) df = df.drop(columns=['struct', 'func']) df = df.loc[~(df == 0).all(axis=1)] df = df.sort_values(by=[ 'motif_dist', 'graph_dist_cosine', 'graph_dist_correlation', 'struct_func_3333', 'struct_func_2233', 'struct_func_2222', 'struct_func_1223', 'struct_func_1122', 'struct_func_1113', 'struct_3333', 'func_3333', 'struct_2233', 'func_2233', 'struct_2222', 'func_2222', 'struct_1223', 'func_1223', 'struct_1122', 'func_1122', 'struct_1113', 'func_1113' ], ascending=[ True, True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False ]) # Take the top 25th percentile df = df.head(int(0.25 * len(df))) best_threshes = [] best_mats = [] best_multigraphs = [] for key in list(df.index): func_mat_tmp = func_mat.copy() struct_mat_tmp = struct_mat.copy() struct_thr = float(key.split('-')[-1]) func_thr = float(key.split('-')[-1]) best_threshes.append(str(func_thr)) func_mat_tmp[func_mat_tmp < func_thr] = 0 struct_mat_tmp[struct_mat_tmp < struct_thr] = 0 best_mats.append((func_mat_tmp, struct_mat_tmp)) mG = build_mx_multigraph(func_mat, struct_mat, f"{name}_{key}", namer_dir) best_multigraphs.append(mG) mg_dict = dict(zip(best_threshes, best_multigraphs)) g_dict = dict(zip(best_threshes, best_mats)) return mg_dict, g_dict