risk-network 0.0.9b11__py3-none-any.whl → 0.0.9b13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
risk/__init__.py CHANGED
@@ -7,4 +7,4 @@ RISK: RISK Infers Spatial Kinships
7
7
 
8
8
  from risk.risk import RISK
9
9
 
10
- __version__ = "0.0.9-beta.11"
10
+ __version__ = "0.0.9-beta.13"
@@ -12,23 +12,32 @@ from leidenalg import find_partition, RBConfigurationVertexPartition
12
12
  from networkx.algorithms.community import greedy_modularity_communities
13
13
 
14
14
 
15
- def calculate_greedy_modularity_neighborhoods(network: nx.Graph) -> np.ndarray:
15
+ def calculate_greedy_modularity_neighborhoods(
16
+ network: nx.Graph, edge_rank_percentile: float = 1.0
17
+ ) -> np.ndarray:
16
18
  """Calculate neighborhoods using the Greedy Modularity method.
17
19
 
18
20
  Args:
19
- network (nx.Graph): The network graph to analyze for community structure.
21
+ network (nx.Graph): The network graph.
22
+ edge_rank_percentile (float, optional): Shortest edge rank percentile threshold for creating
23
+ subgraphs before clustering.
20
24
 
21
25
  Returns:
22
26
  np.ndarray: A binary neighborhood matrix where nodes in the same community have 1, and others have 0.
23
27
  """
28
+ # Create a subgraph with the shortest edges based on the rank percentile
29
+ subnetwork = _create_percentile_limited_subgraph(
30
+ network, edge_rank_percentile=edge_rank_percentile
31
+ )
24
32
  # Detect communities using the Greedy Modularity method
25
- communities = greedy_modularity_communities(network)
33
+ communities = greedy_modularity_communities(subnetwork)
26
34
  # Get the list of nodes in the original NetworkX graph
27
35
  nodes = list(network.nodes())
28
36
  node_index_map = {node: idx for idx, node in enumerate(nodes)}
29
37
  # Create a binary neighborhood matrix
30
- n_nodes = len(nodes)
31
- neighborhoods = np.zeros((n_nodes, n_nodes), dtype=int)
38
+ num_nodes = len(nodes)
39
+ # Initialize neighborhoods with zeros and set self-self entries to 1
40
+ neighborhoods = np.eye(num_nodes, dtype=int)
32
41
  # Fill in the neighborhood matrix for nodes in the same community
33
42
  for community in communities:
34
43
  # Iterate through all pairs of nodes in the same community
@@ -42,23 +51,34 @@ def calculate_greedy_modularity_neighborhoods(network: nx.Graph) -> np.ndarray:
42
51
  return neighborhoods
43
52
 
44
53
 
45
- def calculate_label_propagation_neighborhoods(network: nx.Graph) -> np.ndarray:
54
+ def calculate_label_propagation_neighborhoods(
55
+ network: nx.Graph, edge_rank_percentile: float = 1.0
56
+ ) -> np.ndarray:
46
57
  """Apply Label Propagation to the network to detect communities.
47
58
 
48
59
  Args:
49
60
  network (nx.Graph): The network graph.
61
+ edge_rank_percentile (float, optional): Shortest edge rank percentile threshold for creating
62
+ subgraphs before clustering.
50
63
 
51
64
  Returns:
52
65
  np.ndarray: A binary neighborhood matrix on Label Propagation.
53
66
  """
67
+ # Create a subgraph with the shortest edges based on the rank percentile
68
+ subnetwork = _create_percentile_limited_subgraph(
69
+ network, edge_rank_percentile=edge_rank_percentile
70
+ )
54
71
  # Apply Label Propagation for community detection
55
- communities = nx.algorithms.community.label_propagation.label_propagation_communities(network)
72
+ communities = nx.algorithms.community.label_propagation.label_propagation_communities(
73
+ subnetwork
74
+ )
56
75
  # Get the list of nodes in the network
57
76
  nodes = list(network.nodes())
58
77
  node_index_map = {node: idx for idx, node in enumerate(nodes)}
59
78
  # Create a binary neighborhood matrix
60
79
  num_nodes = len(nodes)
61
- neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
80
+ # Initialize neighborhoods with zeros and set self-self entries to 1
81
+ neighborhoods = np.eye(num_nodes, dtype=int)
62
82
  # Assign neighborhoods based on community labels using the mapped indices
63
83
  for community in communities:
64
84
  for node_i in community:
@@ -71,20 +91,29 @@ def calculate_label_propagation_neighborhoods(network: nx.Graph) -> np.ndarray:
71
91
 
72
92
 
73
93
  def calculate_leiden_neighborhoods(
74
- network: nx.Graph, resolution: float = 1.0, random_seed: int = 888
94
+ network: nx.Graph,
95
+ resolution: float = 1.0,
96
+ edge_rank_percentile: float = 1.0,
97
+ random_seed: int = 888,
75
98
  ) -> np.ndarray:
76
99
  """Calculate neighborhoods using the Leiden method.
77
100
 
78
101
  Args:
79
102
  network (nx.Graph): The network graph.
80
103
  resolution (float, optional): Resolution parameter for the Leiden method. Defaults to 1.0.
104
+ edge_rank_percentile (float, optional): Shortest edge rank percentile threshold for creating
105
+ subgraphs before clustering.
81
106
  random_seed (int, optional): Random seed for reproducibility. Defaults to 888.
82
107
 
83
108
  Returns:
84
109
  np.ndarray: A binary neighborhood matrix where nodes in the same community have 1, and others have 0.
85
110
  """
111
+ # Create a subgraph with the shortest edges based on the rank percentile
112
+ subnetwork = _create_percentile_limited_subgraph(
113
+ network, edge_rank_percentile=edge_rank_percentile
114
+ )
86
115
  # Convert NetworkX graph to iGraph
87
- igraph_network = ig.Graph.from_networkx(network)
116
+ igraph_network = ig.Graph.from_networkx(subnetwork)
88
117
  # Apply Leiden algorithm using RBConfigurationVertexPartition, which supports resolution
89
118
  partition = find_partition(
90
119
  igraph_network,
@@ -97,7 +126,8 @@ def calculate_leiden_neighborhoods(
97
126
  node_index_map = {node: idx for idx, node in enumerate(nodes)}
98
127
  # Create a binary neighborhood matrix
99
128
  num_nodes = len(nodes)
100
- neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
129
+ # Initialize neighborhoods with zeros and set self-self entries to 1
130
+ neighborhoods = np.eye(num_nodes, dtype=int)
101
131
  # Assign neighborhoods based on community partitions using the mapped indices
102
132
  for community in partition:
103
133
  for node_i in community:
@@ -110,28 +140,38 @@ def calculate_leiden_neighborhoods(
110
140
 
111
141
 
112
142
  def calculate_louvain_neighborhoods(
113
- network: nx.Graph, resolution: float, random_seed: int = 888
143
+ network: nx.Graph,
144
+ resolution: float = 0.1,
145
+ edge_rank_percentile: float = 1.0,
146
+ random_seed: int = 888,
114
147
  ) -> np.ndarray:
115
148
  """Calculate neighborhoods using the Louvain method.
116
149
 
117
150
  Args:
118
151
  network (nx.Graph): The network graph.
119
- resolution (float): Resolution parameter for the Louvain method.
152
+ resolution (float, optional): Resolution parameter for the Louvain method. Defaults to 0.1.
153
+ edge_rank_percentile (float, optional): Shortest edge rank percentile threshold for creating
154
+ subgraphs before clustering.
120
155
  random_seed (int, optional): Random seed for reproducibility. Defaults to 888.
121
156
 
122
157
  Returns:
123
158
  np.ndarray: A binary neighborhood matrix on the Louvain method.
124
159
  """
160
+ # Create a subgraph with the shortest edges based on the rank percentile
161
+ subnetwork = _create_percentile_limited_subgraph(
162
+ network, edge_rank_percentile=edge_rank_percentile
163
+ )
125
164
  # Apply Louvain method to partition the network
126
165
  partition = community_louvain.best_partition(
127
- network, resolution=resolution, random_state=random_seed
166
+ subnetwork, resolution=resolution, random_state=random_seed
128
167
  )
129
168
  # Get the list of nodes in the network and create a mapping to indices
130
169
  nodes = list(network.nodes())
131
170
  node_index_map = {node: idx for idx, node in enumerate(nodes)}
132
171
  # Create a binary neighborhood matrix
133
172
  num_nodes = len(nodes)
134
- neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
173
+ # Initialize neighborhoods with zeros and set self-self entries to 1
174
+ neighborhoods = np.eye(num_nodes, dtype=int)
135
175
  # Group nodes by community
136
176
  community_groups = {}
137
177
  for node, community in partition.items():
@@ -148,58 +188,76 @@ def calculate_louvain_neighborhoods(
148
188
  return neighborhoods
149
189
 
150
190
 
151
- def calculate_markov_clustering_neighborhoods(network: nx.Graph) -> np.ndarray:
152
- """Apply Markov Clustering (MCL) to the network.
191
+ def calculate_markov_clustering_neighborhoods(
192
+ network: nx.Graph, edge_rank_percentile: float = 1.0
193
+ ) -> np.ndarray:
194
+ """Apply Markov Clustering (MCL) to the network and return a binary neighborhood matrix.
153
195
 
154
196
  Args:
155
197
  network (nx.Graph): The network graph.
198
+ edge_rank_percentile (float, optional): Shortest edge rank percentile threshold for creating
199
+ subgraphs before clustering.
156
200
 
157
201
  Returns:
158
202
  np.ndarray: A binary neighborhood matrix on Markov Clustering.
159
203
  """
160
- # Step 1: Convert the graph to an adjacency matrix
161
- nodes = list(network.nodes())
162
- node_index_map = {node: idx for idx, node in enumerate(nodes)}
163
- # Step 2: Create a reverse mapping from index to node
164
- index_node_map = {idx: node for node, idx in node_index_map.items()}
165
- adjacency_matrix = nx.to_numpy_array(network, nodelist=nodes)
166
- # Step 3: Run Markov Clustering (MCL) on the adjacency matrix
204
+ # Create a subgraph with the shortest edges based on the rank percentile
205
+ subnetwork = _create_percentile_limited_subgraph(
206
+ network, edge_rank_percentile=edge_rank_percentile
207
+ )
208
+ # Step 1: Convert the subnetwork to an adjacency matrix
209
+ subnetwork_nodes = list(subnetwork.nodes())
210
+ adjacency_matrix = nx.to_numpy_array(subnetwork, nodelist=subnetwork_nodes)
211
+ # Step 2: Run Markov Clustering (MCL) on the subnetwork's adjacency matrix
167
212
  result = mc.run_mcl(adjacency_matrix)
168
- # Step 4: Get clusters (communities) from MCL result
169
213
  clusters = mc.get_clusters(result)
170
- # Step 5: Create a binary neighborhood matrix
214
+ # Step 3: Prepare the original network nodes and indices
215
+ nodes = list(network.nodes())
216
+ node_index_map = {node: idx for idx, node in enumerate(nodes)}
171
217
  num_nodes = len(nodes)
172
- neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
173
- # Step 6: Assign neighborhoods based on MCL clusters using the original node labels
218
+ # Step 4: Initialize the neighborhood matrix for the original network
219
+ neighborhoods = np.eye(num_nodes, dtype=int)
220
+ # Step 5: Fill the neighborhoods matrix using the clusters from the subnetwork
174
221
  for cluster in clusters:
175
222
  for node_i in cluster:
176
223
  for node_j in cluster:
177
- # Map the matrix indices back to the original node labels
178
- original_node_i = index_node_map[node_i]
179
- original_node_j = index_node_map[node_j]
180
- idx_i = node_index_map[original_node_i]
181
- idx_j = node_index_map[original_node_j]
182
- neighborhoods[idx_i, idx_j] = 1
224
+ # Map the indices back to the original network's node indices
225
+ original_node_i = subnetwork_nodes[node_i]
226
+ original_node_j = subnetwork_nodes[node_j]
227
+
228
+ if original_node_i in node_index_map and original_node_j in node_index_map:
229
+ idx_i = node_index_map[original_node_i]
230
+ idx_j = node_index_map[original_node_j]
231
+ neighborhoods[idx_i, idx_j] = 1
183
232
 
184
233
  return neighborhoods
185
234
 
186
235
 
187
- def calculate_spinglass_neighborhoods(network: nx.Graph) -> np.ndarray:
236
+ def calculate_spinglass_neighborhoods(
237
+ network: nx.Graph, edge_rank_percentile: float = 1.0
238
+ ) -> np.ndarray:
188
239
  """Apply Spinglass Community Detection to the network, handling disconnected components.
189
240
 
190
241
  Args:
191
- network (nx.Graph): The input network graph with 'x' and 'y' attributes for node positions.
242
+ network (nx.Graph): The network graph.
243
+ edge_rank_percentile (float, optional): Shortest edge rank percentile threshold for creating
244
+ subgraphs before clustering.
192
245
 
193
246
  Returns:
194
247
  np.ndarray: A binary neighborhood matrix based on Spinglass communities.
195
248
  """
249
+ # Create a subgraph with the shortest edges based on the rank percentile
250
+ subnetwork = _create_percentile_limited_subgraph(
251
+ network, edge_rank_percentile=edge_rank_percentile
252
+ )
196
253
  # Step 1: Find connected components in the graph
197
- components = list(nx.connected_components(network))
254
+ components = list(nx.connected_components(subnetwork))
198
255
  # Prepare to store community results
199
256
  nodes = list(network.nodes())
200
257
  node_index_map = {node: idx for idx, node in enumerate(nodes)}
201
258
  num_nodes = len(nodes)
202
- neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
259
+ # Initialize neighborhoods with zeros and set self-self entries to 1
260
+ neighborhoods = np.eye(num_nodes, dtype=int)
203
261
  # Step 2: Run Spinglass on each connected component
204
262
  for component in components:
205
263
  # Extract the subgraph corresponding to the current component
@@ -229,17 +287,25 @@ def calculate_spinglass_neighborhoods(network: nx.Graph) -> np.ndarray:
229
287
  return neighborhoods
230
288
 
231
289
 
232
- def calculate_walktrap_neighborhoods(network: nx.Graph) -> np.ndarray:
290
+ def calculate_walktrap_neighborhoods(
291
+ network: nx.Graph, edge_rank_percentile: float = 1.0
292
+ ) -> np.ndarray:
233
293
  """Apply Walktrap Community Detection to the network.
234
294
 
235
295
  Args:
236
296
  network (nx.Graph): The network graph.
297
+ edge_rank_percentile (float, optional): Shortest edge rank percentile threshold for creating
298
+ subgraphs before clustering.
237
299
 
238
300
  Returns:
239
301
  np.ndarray: A binary neighborhood matrix on Walktrap communities.
240
302
  """
303
+ # Create a subgraph with the shortest edges based on the rank percentile
304
+ subnetwork = _create_percentile_limited_subgraph(
305
+ network, edge_rank_percentile=edge_rank_percentile
306
+ )
241
307
  # Convert NetworkX graph to iGraph
242
- igraph_network = ig.Graph.from_networkx(network)
308
+ igraph_network = ig.Graph.from_networkx(subnetwork)
243
309
  # Apply Walktrap community detection
244
310
  communities = igraph_network.community_walktrap().as_clustering()
245
311
  # Get the list of nodes in the original NetworkX graph
@@ -247,7 +313,8 @@ def calculate_walktrap_neighborhoods(network: nx.Graph) -> np.ndarray:
247
313
  node_index_map = {node: idx for idx, node in enumerate(nodes)}
248
314
  # Create a binary neighborhood matrix
249
315
  num_nodes = len(nodes)
250
- neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
316
+ # Initialize neighborhoods with zeros and set self-self entries to 1
317
+ neighborhoods = np.eye(num_nodes, dtype=int)
251
318
  # Assign neighborhoods based on community labels
252
319
  for community in communities:
253
320
  for node_i in community:
@@ -257,3 +324,44 @@ def calculate_walktrap_neighborhoods(network: nx.Graph) -> np.ndarray:
257
324
  neighborhoods[idx_i, idx_j] = 1
258
325
 
259
326
  return neighborhoods
327
+
328
+
329
+ def _create_percentile_limited_subgraph(G: nx.Graph, edge_rank_percentile: float) -> nx.Graph:
330
+ """Create a subgraph containing the shortest edges based on the specified rank percentile
331
+ of all edge lengths in the input graph.
332
+
333
+ Args:
334
+ G (nx.Graph): The input graph with 'length' attributes on edges.
335
+ edge_rank_percentile (float): The rank percentile (between 0 and 1) to filter edges.
336
+
337
+ Returns:
338
+ nx.Graph: A subgraph with nodes and edges where the edges are within the shortest
339
+ specified rank percentile.
340
+ """
341
+ # Step 1: Extract edges with their lengths
342
+ edges_with_length = [(u, v, d) for u, v, d in G.edges(data=True) if "length" in d]
343
+ if not edges_with_length:
344
+ raise ValueError(
345
+ "No edge lengths found in the graph. Ensure edges have 'length' attributes."
346
+ )
347
+
348
+ # Step 2: Sort edges by length in ascending order
349
+ edges_with_length.sort(key=lambda x: x[2]["length"])
350
+ # Step 3: Calculate the cutoff index for the given rank percentile
351
+ cutoff_index = int(edge_rank_percentile * len(edges_with_length))
352
+ if cutoff_index == 0:
353
+ raise ValueError("The rank percentile is too low, resulting in no edges being included.")
354
+
355
+ # Step 4: Create the subgraph by selecting only the shortest edges within the rank percentile
356
+ subgraph = nx.Graph()
357
+ subgraph.add_nodes_from(G.nodes(data=True)) # Retain all nodes from the original graph
358
+ subgraph.add_edges_from(edges_with_length[:cutoff_index])
359
+ # Step 5: Remove nodes with no edges
360
+ subgraph.remove_nodes_from(list(nx.isolates(subgraph)))
361
+ # Step 6: Check if the resulting subgraph has no edges and issue a warning
362
+ if subgraph.number_of_edges() == 0:
363
+ raise Warning(
364
+ "The resulting subgraph has no edges. Consider adjusting the rank percentile."
365
+ )
366
+
367
+ return subgraph
@@ -52,12 +52,13 @@ def get_network_neighborhoods(
52
52
  random.seed(random_seed)
53
53
  np.random.seed(random_seed)
54
54
 
55
- # Ensure distance_metric and edge_rank_percentile are lists
55
+ # Ensure distance_metric is a list/tuple for multi-algorithm handling
56
56
  if isinstance(distance_metric, (str, np.ndarray)):
57
57
  distance_metric = [distance_metric]
58
+ # Ensure edge_rank_percentile is a list/tuple for multi-threshold handling
58
59
  if isinstance(edge_rank_percentile, (float, int)):
59
60
  edge_rank_percentile = [edge_rank_percentile] * len(distance_metric)
60
-
61
+ # Check that the number of distance metrics matches the number of edge length thresholds
61
62
  if len(distance_metric) != len(edge_rank_percentile):
62
63
  raise ValueError(
63
64
  "The number of distance metrics must match the number of edge length thresholds."
@@ -67,111 +68,61 @@ def get_network_neighborhoods(
67
68
  num_nodes = network.number_of_nodes()
68
69
  combined_neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
69
70
 
70
- # Loop through each distance metric and corresponding edge length threshold
71
- for metric, threshold in zip(distance_metric, edge_rank_percentile):
72
- # Create a subgraph based on the edge length threshold
73
- subgraph = _create_percentile_limited_subgraph(network, edge_rank_percentile=threshold)
74
- subgraph_nodes = list(subgraph.nodes)
75
- # Calculate neighborhoods based on the specified metric
71
+ # Loop through each distance metric and corresponding edge rank percentile
72
+ for metric, percentile in zip(distance_metric, edge_rank_percentile):
73
+ # Call the appropriate neighborhood function based on the metric
76
74
  if metric == "greedy_modularity":
77
- neighborhoods = calculate_greedy_modularity_neighborhoods(subgraph)
75
+ neighborhoods = calculate_greedy_modularity_neighborhoods(
76
+ network, edge_rank_percentile=percentile
77
+ )
78
78
  elif metric == "label_propagation":
79
- neighborhoods = calculate_label_propagation_neighborhoods(subgraph)
79
+ neighborhoods = calculate_label_propagation_neighborhoods(
80
+ network, edge_rank_percentile=percentile
81
+ )
80
82
  elif metric == "leiden":
81
83
  neighborhoods = calculate_leiden_neighborhoods(
82
- subgraph, leiden_resolution, random_seed=random_seed
84
+ network,
85
+ resolution=leiden_resolution,
86
+ edge_rank_percentile=percentile,
87
+ random_seed=random_seed,
83
88
  )
84
89
  elif metric == "louvain":
85
90
  neighborhoods = calculate_louvain_neighborhoods(
86
- subgraph, louvain_resolution, random_seed=random_seed
91
+ network,
92
+ resolution=louvain_resolution,
93
+ edge_rank_percentile=percentile,
94
+ random_seed=random_seed,
87
95
  )
88
96
  elif metric == "markov_clustering":
89
- neighborhoods = calculate_markov_clustering_neighborhoods(subgraph)
97
+ neighborhoods = calculate_markov_clustering_neighborhoods(
98
+ network, edge_rank_percentile=percentile
99
+ )
90
100
  elif metric == "spinglass":
91
- neighborhoods = calculate_spinglass_neighborhoods(subgraph)
101
+ neighborhoods = calculate_spinglass_neighborhoods(
102
+ network, edge_rank_percentile=percentile
103
+ )
92
104
  elif metric == "walktrap":
93
- neighborhoods = calculate_walktrap_neighborhoods(subgraph)
105
+ neighborhoods = calculate_walktrap_neighborhoods(
106
+ network, edge_rank_percentile=percentile
107
+ )
94
108
  else:
95
109
  raise ValueError(
96
- "Invalid distance metric specified. Please choose from 'greedy_modularity', 'label_propagation',"
110
+ "Incorrect distance metric specified. Please choose from 'greedy_modularity', 'label_propagation',"
97
111
  "'leiden', 'louvain', 'markov_clustering', 'spinglass', 'walktrap'."
98
112
  )
99
113
 
100
- # Expand the neighborhood matrix to match the original network's size
101
- expanded_neighborhoods = expand_neighborhood_matrix(
102
- neighborhoods, subgraph_nodes, num_nodes
103
- )
104
- # Sum the expanded neighborhood matrices
105
- combined_neighborhoods += expanded_neighborhoods
114
+ # Sum the neighborhood matrices
115
+ combined_neighborhoods += neighborhoods
106
116
 
107
- # Convert combined_neighborhoods to binary: values > 0 are set to 1
108
- combined_neighborhoods = (combined_neighborhoods > 0).astype(int)
117
+ # Ensure that the maximum value in each row is set to 1
118
+ # This ensures that for each row, only the strongest relationship (the maximum value) is retained,
119
+ # while all other values are reset to 0. This transformation simplifies the neighborhood matrix by
120
+ # focusing on the most significant connection per row (or nodes).
121
+ combined_neighborhoods = _set_max_row_value_to_one(combined_neighborhoods)
109
122
 
110
123
  return combined_neighborhoods
111
124
 
112
125
 
113
- def expand_neighborhood_matrix(
114
- subgraph_matrix: np.ndarray, subgraph_nodes: list, original_size: int
115
- ) -> np.ndarray:
116
- """Expand a subgraph neighborhood matrix back to the size of the original graph.
117
-
118
- Args:
119
- subgraph_matrix (np.ndarray): The neighborhood matrix for the subgraph.
120
- subgraph_nodes (list): List of nodes in the subgraph, corresponding to rows/columns in subgraph_matrix.
121
- original_size (int): The number of nodes in the original graph.
122
-
123
- Returns:
124
- np.ndarray: The expanded matrix with the original size, with subgraph values mapped correctly.
125
- """
126
- expanded_matrix = np.zeros((original_size, original_size), dtype=int)
127
- for i, node_i in enumerate(subgraph_nodes):
128
- for j, node_j in enumerate(subgraph_nodes):
129
- expanded_matrix[node_i, node_j] = subgraph_matrix[i, j]
130
- return expanded_matrix
131
-
132
-
133
- def _create_percentile_limited_subgraph(G: nx.Graph, edge_rank_percentile: float) -> nx.Graph:
134
- """Create a subgraph containing all nodes and edges where the edge length is within the
135
- specified rank percentile of all edges in the input graph. Isolated nodes are removed.
136
-
137
- Args:
138
- G (nx.Graph): The input graph with 'length' attributes on edges.
139
- edge_rank_percentile (float): The rank percentile (between 0 and 1) to filter edges.
140
-
141
- Returns:
142
- nx.Graph: A subgraph with nodes and edges where the edge length is within the
143
- specified percentile, with isolated nodes removed, retaining all original attributes.
144
- """
145
- # Extract edges with their lengths
146
- edges_with_length = [(u, v, d) for u, v, d in G.edges(data=True) if "length" in d]
147
- if not edges_with_length:
148
- raise ValueError("No edge lengths found. Ensure edges have 'length' attributes.")
149
-
150
- # Sort edges by length in ascending order
151
- edges_with_length.sort(key=lambda x: x[2]["length"])
152
- # Calculate the cutoff based on the specified rank percentile
153
- cutoff_index = int(edge_rank_percentile * len(edges_with_length))
154
- if cutoff_index == 0:
155
- raise ValueError("The rank percentile is too low, resulting in no edges being included.")
156
-
157
- # Keep only the edges within the specified percentile
158
- selected_edges = edges_with_length[:cutoff_index]
159
- # Create a new subgraph with the selected edges, retaining all attributes
160
- subgraph = nx.Graph()
161
- subgraph.add_edges_from((u, v, d) for u, v, d in selected_edges)
162
- # Copy over all node attributes from the original graph
163
- subgraph.add_nodes_from((node, G.nodes[node]) for node in subgraph.nodes())
164
-
165
- # Remove isolated nodes (if any)
166
- isolated_nodes = [node for node, degree in subgraph.degree() if degree == 0]
167
- subgraph.remove_nodes_from(isolated_nodes)
168
- # Check if the resulting subgraph has no edges
169
- if subgraph.number_of_edges() == 0:
170
- raise ValueError("The resulting subgraph has no edges. Adjust the rank percentile.")
171
-
172
- return subgraph
173
-
174
-
175
126
  def _set_max_row_value_to_one(matrix: np.ndarray) -> np.ndarray:
176
127
  """For each row in the input matrix, set the maximum value(s) to 1 and all other values to 0. This is particularly
177
128
  useful for neighborhood matrices that have undergone multiple neighborhood detection algorithms, where the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: risk-network
3
- Version: 0.0.9b11
3
+ Version: 0.0.9b13
4
4
  Summary: A Python package for biological network analysis
5
5
  Author: Ira Horecka
6
6
  Author-email: Ira Horecka <ira89@icloud.com>
@@ -1,4 +1,4 @@
1
- risk/__init__.py,sha256=lx2px2aUNVzyhWttIeSRddS0TyVt5tkNaoDp26k1OmE,113
1
+ risk/__init__.py,sha256=bXkN8xIF7g0uIiSoCAXatSRkI_KRTbjWye4l_trCCfk,113
2
2
  risk/constants.py,sha256=XInRaH78Slnw_sWgAsBFbUHkyA0h0jL0DKGuQNbOvjM,550
3
3
  risk/risk.py,sha256=MXu8T93NUgMDl3NaZDbm0j9c4KWwzx-kmp9Rd1ax0N4,23534
4
4
  risk/annotations/__init__.py,sha256=kXgadEXaCh0z8OyhOhTj7c3qXGmWgOhaSZ4gSzSb59U,147
@@ -8,9 +8,9 @@ risk/log/__init__.py,sha256=gy7C5L6D222AYUChq5lkc0LsCJ_QMQPaFiBJKbecdac,201
8
8
  risk/log/console.py,sha256=C52s3FgQ2e9kQWcXL8m7rs_pnKXt5Yy8PBHmQkOTiNo,4537
9
9
  risk/log/parameters.py,sha256=o4StqYCa0kt7_Ht4mKa1DwwvhGUwkC_dGBaiUIc0GB0,5683
10
10
  risk/neighborhoods/__init__.py,sha256=C-SD0G-9skSLjLFdAB6v6lAjO8la2v6Fqy63h2MY28k,186
11
- risk/neighborhoods/community.py,sha256=z8oZGBUZLriYBbT4-0uKDn8iM8SmN5dubrHb7zxcn4w,10431
11
+ risk/neighborhoods/community.py,sha256=hsWr6sNW3lCZn9L2f8oYBVmIANnJpoAL9194fg6K1eQ,15408
12
12
  risk/neighborhoods/domains.py,sha256=t91xSpx9Ty9hSlhRq2_XwyPpBP7sjKhovcPPvkwWtf0,11398
13
- risk/neighborhoods/neighborhoods.py,sha256=D-t1v6EcmKn6B8uZK5X5tU9uOV0OfkKzvETGfZWRnic,23561
13
+ risk/neighborhoods/neighborhoods.py,sha256=XB2Gd0xghKKBNkwp1H-1138NegTlAiyOqAkv_vaLEZM,21150
14
14
  risk/network/__init__.py,sha256=iEPeJdZfqp0toxtbElryB8jbz9_t_k4QQ3iDvKE8C_0,126
15
15
  risk/network/geometry.py,sha256=gFtYUj9j9aul4paKq_qSGJn39Nazxu_MXv8m-tYYtrk,6840
16
16
  risk/network/io.py,sha256=AWSbZGLZHtl72KSlafQlcYoG00YLSznG7UYDi_wDT7M,22958
@@ -32,8 +32,8 @@ risk/stats/stats.py,sha256=z8NrhiVj4BzJ250bVLfytpmfC7RzYu7mBuIZD_l0aCA,7222
32
32
  risk/stats/permutation/__init__.py,sha256=neJp7FENC-zg_CGOXqv-iIvz1r5XUKI9Ruxhmq7kDOI,105
33
33
  risk/stats/permutation/permutation.py,sha256=meBNSrbRa9P8WJ54n485l0H7VQJlMSfHqdN4aCKYCtQ,10105
34
34
  risk/stats/permutation/test_functions.py,sha256=lftOude6hee0pyR80HlBD32522JkDoN5hrKQ9VEbuoY,2345
35
- risk_network-0.0.9b11.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
36
- risk_network-0.0.9b11.dist-info/METADATA,sha256=38pUWpqTrjTbc5LQ1_JnRqOpXwgSS-J1wVHHBMTTQ6M,47552
37
- risk_network-0.0.9b11.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
38
- risk_network-0.0.9b11.dist-info/top_level.txt,sha256=NX7C2PFKTvC1JhVKv14DFlFAIFnKc6Lpsu1ZfxvQwVw,5
39
- risk_network-0.0.9b11.dist-info/RECORD,,
35
+ risk_network-0.0.9b13.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
36
+ risk_network-0.0.9b13.dist-info/METADATA,sha256=tbqUuKfdv5QjAprQruLMmTk5wzGWrwVqg528BeWcynQ,47552
37
+ risk_network-0.0.9b13.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
38
+ risk_network-0.0.9b13.dist-info/top_level.txt,sha256=NX7C2PFKTvC1JhVKv14DFlFAIFnKc6Lpsu1ZfxvQwVw,5
39
+ risk_network-0.0.9b13.dist-info/RECORD,,