def local_thresholding_dens(conn_matrix, thr): """ Threshold the adjacency matrix by building from the minimum spanning tree (MST) and adding successive N-nearest neighbour degree graphs to achieve target density threshold. Parameters ---------- conn_matrix : array Weighted NxN matrix. thr : float A density threshold, between 0 and 1, to achieve through local thresholding. Returns ------- conn_matrix_thr : array Weighted, MST local-thresholded, NxN matrix. """ from pynets import thresholding from pynets.stats import netstats fail_tol = 10 conn_matrix = np.nan_to_num(conn_matrix) G = nx.from_numpy_matrix(conn_matrix) if not nx.is_connected(G): [G, _] = netstats.prune_disconnected(G) maximum_edges = G.number_of_edges() G = thresholding.weight_to_distance(G) min_t = nx.minimum_spanning_tree(G, weight="distance") mst_density = nx.density(min_t) G_density = nx.density(G) if mst_density > G_density: print("%s%s%s" % ( 'Warning: The minimum spanning tree already has: ', thr, ' density. Local Threshold will be applied by just retaining the Minimum Spanning Tree' )) conn_matrix_thr = nx.to_numpy_array(G) return conn_matrix_thr k = 1 dense_list = [] while mst_density < float(thr) and (len(dense_list[-fail_tol:]) - len( set(dense_list[-fail_tol:]))) < (fail_tol - 1): print(k) print(mst_density) dense_list.append(mst_density) # Create nearest neighbour graph nng = thresholding.knn(conn_matrix, k) number_before = nng.number_of_edges() # Remove edges from the NNG that exist already in the new graph/MST nng.remove_edges_from(min_t.edges()) if nng.number_of_edges() == 0 and number_before >= maximum_edges: break # Add weights to NNG for e in nng.edges(): nng.edges[e[0], e[1]]['weight'] = float(conn_matrix[e[0], e[1]]) # Obtain list of edges from the NNG in order of weight edge_list = sorted(nng.edges(data=True), key=lambda t: t[2]['weight'], reverse=True) # Add edges in order of connectivity strength for edge in edge_list: min_t.add_edges_from([edge]) mst_density = thresholding.est_density((nx.to_numpy_array(min_t))) # print("%s%s" % ('Adding edge to mst: ', edge)) if mst_density >= G_density or mst_density >= float(thr): # print(mst_density) break if (len(dense_list[-fail_tol:]) - len(set(dense_list[-fail_tol:]))) >= (fail_tol - 1): print("%s%s%s" % ('Cannot apply local thresholding to achieve density of: ', thr, '. Using maximally saturated connected matrix instead...')) k += 1 conn_matrix_thr = nx.to_numpy_array(min_t, nodelist=sorted(min_t.nodes()), dtype=np.float64) if len(min_t.nodes()) < conn_matrix.shape[0]: raise RuntimeWarning( "%s%s%s" % ('Cannot apply local thresholding to achieve density of: ', thr, '. Try a higher -thr or -min_thr')) return conn_matrix_thr
def local_thresholding_prop(conn_matrix, thr): """ Threshold the adjacency matrix by building from the minimum spanning tree (MST) and adding successive N-nearest neighbour degree graphs to achieve target proportional threshold. Parameters ---------- conn_matrix : array Weighted NxN matrix. thr : float A proportional threshold, between 0 and 1, to achieve through local thresholding. Returns ------- conn_matrix_thr : array Weighted, MST local-thresholded, NxN matrix. """ from pynets import thresholding from pynets.stats import netstats fail_tol = 10 conn_matrix = np.nan_to_num(conn_matrix) G = nx.from_numpy_matrix(conn_matrix) if not nx.is_connected(G): [G, _] = netstats.prune_disconnected(G) maximum_edges = G.number_of_edges() G = thresholding.weight_to_distance(G) min_t = nx.minimum_spanning_tree(G, weight="distance") len_edges = min_t.number_of_edges() upper_values = np.triu_indices(np.shape(conn_matrix)[0], k=1) weights = np.array(conn_matrix[upper_values]) weights = weights[~np.isnan(weights)] edgenum = int(float(thr) * float(len(weights))) if len_edges > edgenum: print("%s%s%s" % ( 'Warning: The minimum spanning tree already has: ', len_edges, ' edges, select more edges. Local Threshold will be applied by just retaining the Minimum ' 'Spanning Tree')) conn_matrix_thr = nx.to_numpy_array(G) return conn_matrix_thr k = 1 len_edge_list = [] while len_edges < edgenum and k <= np.shape(conn_matrix)[0] and ( len(len_edge_list[-fail_tol:]) - len(set(len_edge_list[-fail_tol:]))) < (fail_tol - 1): print(k) print(len_edges) len_edge_list.append(len_edges) # Create nearest neighbour graph nng = thresholding.knn(conn_matrix, k) number_before = nng.number_of_edges() # Remove edges from the NNG that exist already in the new graph/MST nng.remove_edges_from(min_t.edges()) if nng.number_of_edges() == 0 and number_before >= maximum_edges: break # Add weights to NNG for e in nng.edges(): nng.edges[e[0], e[1]]['weight'] = float(conn_matrix[e[0], e[1]]) # Obtain list of edges from the NNG in order of weight edge_list = sorted(nng.edges(data=True), key=lambda t: t[2]['weight'], reverse=True) # Add edges in order of connectivity strength for edge in edge_list: # print("%s%s" % ('Adding edge to mst: ', edge)) min_t.add_edges_from([edge]) min_t_mx = nx.to_numpy_array(min_t) len_edges = nx.from_numpy_matrix(min_t_mx).number_of_edges() if len_edges >= edgenum: # print(len_edges) break if (len(len_edge_list[-fail_tol:]) - len(set(len_edge_list[-fail_tol:]))) >= (fail_tol - 1): print("%s%s%s" % ('Cannot apply local thresholding to achieve threshold of: ', thr, '. Using maximally saturated connected matrix instead...')) k += 1 conn_matrix_thr = nx.to_numpy_array(min_t, nodelist=sorted(min_t.nodes()), dtype=np.float64) if len(min_t.nodes()) < conn_matrix.shape[0]: raise RuntimeWarning( "%s%s%s" % ('Cannot apply local thresholding to achieve threshold of: ', thr, '. Try a higher -thr or -min_thr')) return conn_matrix_thr