risk-network 0.0.11__py3-none-any.whl → 0.0.12b0__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.
Files changed (42) hide show
  1. risk/__init__.py +1 -1
  2. risk/risk.py +5 -5
  3. {risk_network-0.0.11.dist-info → risk_network-0.0.12b0.dist-info}/METADATA +10 -12
  4. risk_network-0.0.12b0.dist-info/RECORD +7 -0
  5. {risk_network-0.0.11.dist-info → risk_network-0.0.12b0.dist-info}/WHEEL +1 -1
  6. risk/annotations/__init__.py +0 -7
  7. risk/annotations/annotations.py +0 -354
  8. risk/annotations/io.py +0 -240
  9. risk/annotations/nltk_setup.py +0 -85
  10. risk/log/__init__.py +0 -11
  11. risk/log/console.py +0 -141
  12. risk/log/parameters.py +0 -172
  13. risk/neighborhoods/__init__.py +0 -8
  14. risk/neighborhoods/api.py +0 -442
  15. risk/neighborhoods/community.py +0 -412
  16. risk/neighborhoods/domains.py +0 -358
  17. risk/neighborhoods/neighborhoods.py +0 -508
  18. risk/network/__init__.py +0 -6
  19. risk/network/geometry.py +0 -150
  20. risk/network/graph/__init__.py +0 -6
  21. risk/network/graph/api.py +0 -200
  22. risk/network/graph/graph.py +0 -269
  23. risk/network/graph/summary.py +0 -254
  24. risk/network/io.py +0 -550
  25. risk/network/plotter/__init__.py +0 -6
  26. risk/network/plotter/api.py +0 -54
  27. risk/network/plotter/canvas.py +0 -291
  28. risk/network/plotter/contour.py +0 -330
  29. risk/network/plotter/labels.py +0 -924
  30. risk/network/plotter/network.py +0 -294
  31. risk/network/plotter/plotter.py +0 -143
  32. risk/network/plotter/utils/colors.py +0 -416
  33. risk/network/plotter/utils/layout.py +0 -94
  34. risk/stats/__init__.py +0 -15
  35. risk/stats/permutation/__init__.py +0 -6
  36. risk/stats/permutation/permutation.py +0 -237
  37. risk/stats/permutation/test_functions.py +0 -70
  38. risk/stats/significance.py +0 -166
  39. risk/stats/stat_tests.py +0 -267
  40. risk_network-0.0.11.dist-info/RECORD +0 -41
  41. {risk_network-0.0.11.dist-info → risk_network-0.0.12b0.dist-info/licenses}/LICENSE +0 -0
  42. {risk_network-0.0.11.dist-info → risk_network-0.0.12b0.dist-info}/top_level.txt +0 -0
@@ -1,412 +0,0 @@
1
- """
2
- risk/neighborhoods/community
3
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
- """
5
-
6
- import community as community_louvain
7
- import igraph as ig
8
- import markov_clustering as mc
9
- import networkx as nx
10
- import numpy as np
11
- from leidenalg import find_partition, RBConfigurationVertexPartition
12
- from networkx.algorithms.community import greedy_modularity_communities
13
- from scipy.sparse import csr_matrix
14
-
15
- from risk.log import logger
16
-
17
-
18
- def calculate_greedy_modularity_neighborhoods(
19
- network: nx.Graph, fraction_shortest_edges: float = 1.0
20
- ) -> csr_matrix:
21
- """Calculate neighborhoods using the Greedy Modularity method with CSR matrix output.
22
-
23
- Args:
24
- network (nx.Graph): The network graph.
25
- fraction_shortest_edges (float, optional): Shortest edge rank fraction threshold for creating
26
- subgraphs before clustering. Defaults to 1.0.
27
-
28
- Returns:
29
- csr_matrix: A binary neighborhood matrix (CSR) where nodes in the same community have 1, and others have 0.
30
- """
31
- # Create a subgraph with the shortest edges based on the rank fraction
32
- subnetwork = _create_percentile_limited_subgraph(
33
- network, fraction_shortest_edges=fraction_shortest_edges
34
- )
35
- # Detect communities using the Greedy Modularity method
36
- communities = greedy_modularity_communities(subnetwork)
37
- # Get the list of nodes in the original NetworkX graph
38
- nodes = list(network.nodes())
39
- node_index_map = {node: idx for idx, node in enumerate(nodes)}
40
- # Prepare data for CSR matrix
41
- row_indices = []
42
- col_indices = []
43
- for community in communities:
44
- mapped_indices = [node_index_map[node] for node in community]
45
- for i in mapped_indices:
46
- for j in mapped_indices:
47
- row_indices.append(i)
48
- col_indices.append(j)
49
-
50
- # Create a CSR matrix
51
- num_nodes = len(nodes)
52
- data = np.ones(len(row_indices), dtype=int)
53
- neighborhoods = csr_matrix((data, (row_indices, col_indices)), shape=(num_nodes, num_nodes))
54
-
55
- return neighborhoods
56
-
57
-
58
- def calculate_label_propagation_neighborhoods(
59
- network: nx.Graph, fraction_shortest_edges: float = 1.0
60
- ) -> csr_matrix:
61
- """Apply Label Propagation to the network to detect communities.
62
-
63
- Args:
64
- network (nx.Graph): The network graph.
65
- fraction_shortest_edges (float, optional): Shortest edge rank fraction threshold for creating
66
- subgraphs before clustering. Defaults to 1.0.
67
-
68
- Returns:
69
- csr_matrix: A binary neighborhood matrix (CSR) on Label Propagation.
70
- """
71
- # Create a subgraph with the shortest edges based on the rank fraction
72
- subnetwork = _create_percentile_limited_subgraph(
73
- network, fraction_shortest_edges=fraction_shortest_edges
74
- )
75
- # Apply Label Propagation for community detection
76
- communities = nx.algorithms.community.label_propagation.label_propagation_communities(
77
- subnetwork
78
- )
79
- # Get the list of nodes in the network
80
- nodes = list(network.nodes())
81
- node_index_map = {node: idx for idx, node in enumerate(nodes)}
82
- # Prepare data for CSR matrix
83
- row_indices = []
84
- col_indices = []
85
- # Assign neighborhoods based on community labels using the mapped indices
86
- for community in communities:
87
- mapped_indices = [node_index_map[node] for node in community]
88
- for i in mapped_indices:
89
- for j in mapped_indices:
90
- row_indices.append(i)
91
- col_indices.append(j)
92
-
93
- # Create a CSR matrix
94
- num_nodes = len(nodes)
95
- data = np.ones(len(row_indices), dtype=int)
96
- neighborhoods = csr_matrix((data, (row_indices, col_indices)), shape=(num_nodes, num_nodes))
97
-
98
- return neighborhoods
99
-
100
-
101
- def calculate_leiden_neighborhoods(
102
- network: nx.Graph,
103
- resolution: float = 1.0,
104
- fraction_shortest_edges: float = 1.0,
105
- random_seed: int = 888,
106
- ) -> csr_matrix:
107
- """Calculate neighborhoods using the Leiden method with CSR matrix output.
108
-
109
- Args:
110
- network (nx.Graph): The network graph.
111
- resolution (float, optional): Resolution parameter for the Leiden method. Defaults to 1.0.
112
- fraction_shortest_edges (float, optional): Shortest edge rank fraction threshold for creating
113
- subgraphs before clustering. Defaults to 1.0.
114
- random_seed (int, optional): Random seed for reproducibility. Defaults to 888.
115
-
116
- Returns:
117
- csr_matrix: A binary neighborhood matrix (CSR) where nodes in the same community have 1, and others have 0.
118
- """
119
- # Create a subgraph with the shortest edges based on the rank fraction
120
- subnetwork = _create_percentile_limited_subgraph(
121
- network, fraction_shortest_edges=fraction_shortest_edges
122
- )
123
- # Convert NetworkX graph to iGraph
124
- igraph_network = ig.Graph.from_networkx(subnetwork)
125
- # Apply Leiden algorithm using RBConfigurationVertexPartition, which supports resolution
126
- partition = find_partition(
127
- igraph_network,
128
- partition_type=RBConfigurationVertexPartition,
129
- resolution_parameter=resolution,
130
- seed=random_seed,
131
- )
132
- # Get the list of nodes in the original NetworkX graph
133
- nodes = list(network.nodes())
134
- node_index_map = {node: idx for idx, node in enumerate(nodes)}
135
- # Prepare data for CSR matrix
136
- row_indices = []
137
- col_indices = []
138
- for community in partition:
139
- mapped_indices = [node_index_map[igraph_network.vs[node]["_nx_name"]] for node in community]
140
- for i in mapped_indices:
141
- for j in mapped_indices:
142
- row_indices.append(i)
143
- col_indices.append(j)
144
-
145
- # Create a CSR matrix
146
- num_nodes = len(nodes)
147
- data = np.ones(len(row_indices), dtype=int)
148
- neighborhoods = csr_matrix((data, (row_indices, col_indices)), shape=(num_nodes, num_nodes))
149
-
150
- return neighborhoods
151
-
152
-
153
- def calculate_louvain_neighborhoods(
154
- network: nx.Graph,
155
- resolution: float = 0.1,
156
- fraction_shortest_edges: float = 1.0,
157
- random_seed: int = 888,
158
- ) -> csr_matrix:
159
- """Calculate neighborhoods using the Louvain method.
160
-
161
- Args:
162
- network (nx.Graph): The network graph.
163
- resolution (float, optional): Resolution parameter for the Louvain method. Defaults to 0.1.
164
- fraction_shortest_edges (float, optional): Shortest edge rank fraction threshold for creating
165
- subgraphs before clustering. Defaults to 1.0.
166
- random_seed (int, optional): Random seed for reproducibility. Defaults to 888.
167
-
168
- Returns:
169
- csr_matrix: A binary neighborhood matrix in CSR format.
170
- """
171
- # Create a subgraph with the shortest edges based on the rank fraction
172
- subnetwork = _create_percentile_limited_subgraph(
173
- network, fraction_shortest_edges=fraction_shortest_edges
174
- )
175
- # Apply Louvain method to partition the network
176
- partition = community_louvain.best_partition(
177
- subnetwork, resolution=resolution, random_state=random_seed
178
- )
179
- # Get the list of nodes in the network and create a mapping to indices
180
- nodes = list(network.nodes())
181
- node_index_map = {node: idx for idx, node in enumerate(nodes)}
182
- # Group nodes by community
183
- community_groups = {}
184
- for node, community in partition.items():
185
- community_groups.setdefault(community, []).append(node)
186
-
187
- # Prepare data for CSR matrix
188
- row_indices = []
189
- col_indices = []
190
- for community_nodes in community_groups.values():
191
- mapped_indices = [node_index_map[node] for node in community_nodes]
192
- for i in mapped_indices:
193
- for j in mapped_indices:
194
- row_indices.append(i)
195
- col_indices.append(j)
196
-
197
- # Create a CSR matrix
198
- num_nodes = len(nodes)
199
- data = np.ones(len(row_indices), dtype=int)
200
- neighborhoods = csr_matrix((data, (row_indices, col_indices)), shape=(num_nodes, num_nodes))
201
-
202
- return neighborhoods
203
-
204
-
205
- def calculate_markov_clustering_neighborhoods(
206
- network: nx.Graph, fraction_shortest_edges: float = 1.0
207
- ) -> csr_matrix:
208
- """Apply Markov Clustering (MCL) to the network and return a binary neighborhood matrix (CSR).
209
-
210
- Args:
211
- network (nx.Graph): The network graph.
212
- fraction_shortest_edges (float, optional): Shortest edge rank fraction threshold for creating
213
- subgraphs before clustering. Defaults to 1.0.
214
-
215
- Returns:
216
- csr_matrix: A binary neighborhood matrix (CSR) on Markov Clustering.
217
-
218
- Warning:
219
- This function temporarily converts the adjacency matrix to a dense format, which may lead to
220
- high memory consumption for large graphs.
221
- """
222
- # Create a subgraph with the shortest edges based on the rank fraction
223
- subnetwork = _create_percentile_limited_subgraph(
224
- network, fraction_shortest_edges=fraction_shortest_edges
225
- )
226
- # Check if the subgraph has edges
227
- if subnetwork.number_of_edges() == 0:
228
- raise ValueError("The subgraph has no edges. Adjust the fraction_shortest_edges parameter.")
229
-
230
- # Step 1: Convert the subnetwork to an adjacency matrix (CSR)
231
- subnetwork_nodes = list(subnetwork.nodes())
232
- adjacency_matrix = nx.to_scipy_sparse_array(subnetwork, nodelist=subnetwork_nodes)
233
- # Ensure the adjacency matrix is valid
234
- if adjacency_matrix.shape[0] == 0 or adjacency_matrix.shape[1] == 0:
235
- raise ValueError(
236
- "The adjacency matrix is empty. Check the input graph or filtering criteria."
237
- )
238
-
239
- # Convert the sparse matrix to dense format for MCL
240
- dense_matrix = adjacency_matrix.toarray()
241
- # Step 2: Run Markov Clustering (MCL) on the dense adjacency matrix
242
- try:
243
- result = mc.run_mcl(dense_matrix)
244
- except Exception as e:
245
- raise RuntimeError(f"Markov Clustering failed: {e}")
246
-
247
- clusters = mc.get_clusters(result)
248
- # Step 3: Prepare the original network nodes and indices
249
- nodes = list(network.nodes())
250
- node_index_map = {node: idx for idx, node in enumerate(nodes)}
251
- num_nodes = len(nodes)
252
- # Step 4: Prepare data for CSR matrix
253
- row_indices = []
254
- col_indices = []
255
- for cluster in clusters:
256
- for node_i in cluster:
257
- for node_j in cluster:
258
- # Map the indices back to the original network's node indices
259
- original_node_i = subnetwork_nodes[node_i]
260
- original_node_j = subnetwork_nodes[node_j]
261
- if original_node_i in node_index_map and original_node_j in node_index_map:
262
- idx_i = node_index_map[original_node_i]
263
- idx_j = node_index_map[original_node_j]
264
- row_indices.append(idx_i)
265
- col_indices.append(idx_j)
266
-
267
- # Step 5: Create a CSR matrix
268
- data = np.ones(len(row_indices), dtype=int)
269
- neighborhoods = csr_matrix((data, (row_indices, col_indices)), shape=(num_nodes, num_nodes))
270
-
271
- return neighborhoods
272
-
273
-
274
- def calculate_spinglass_neighborhoods(
275
- network: nx.Graph, fraction_shortest_edges: float = 1.0
276
- ) -> csr_matrix:
277
- """Apply Spinglass Community Detection to the network, handling disconnected components.
278
-
279
- Args:
280
- network (nx.Graph): The network graph.
281
- fraction_shortest_edges (float, optional): Shortest edge rank fraction threshold for creating
282
- subgraphs before clustering. Defaults to 1.0.
283
-
284
- Returns:
285
- csr_matrix: A binary neighborhood matrix (CSR) based on Spinglass communities.
286
- """
287
- # Create a subgraph with the shortest edges based on the rank fraction
288
- subnetwork = _create_percentile_limited_subgraph(
289
- network, fraction_shortest_edges=fraction_shortest_edges
290
- )
291
- # Step 1: Find connected components in the graph
292
- components = list(nx.connected_components(subnetwork))
293
- # Prepare data for CSR matrix
294
- nodes = list(network.nodes())
295
- node_index_map = {node: idx for idx, node in enumerate(nodes)}
296
- row_indices = []
297
- col_indices = []
298
- # Step 2: Run Spinglass on each connected component
299
- for component in components:
300
- # Extract the subgraph corresponding to the current component
301
- subgraph = network.subgraph(component)
302
- # Convert the subgraph to an iGraph object
303
- igraph_subgraph = ig.Graph.from_networkx(subgraph)
304
- # Ensure the subgraph is connected before running Spinglass
305
- if not igraph_subgraph.is_connected():
306
- logger.error("Warning: Subgraph is not connected. Skipping...")
307
- continue
308
-
309
- # Apply Spinglass community detection
310
- try:
311
- communities = igraph_subgraph.community_spinglass()
312
- except Exception as e:
313
- logger.error(f"Error running Spinglass on component: {e}")
314
- continue
315
-
316
- # Step 3: Assign neighborhoods based on community labels
317
- for community in communities:
318
- mapped_indices = [
319
- node_index_map[igraph_subgraph.vs[node]["_nx_name"]] for node in community
320
- ]
321
- for i in mapped_indices:
322
- for j in mapped_indices:
323
- row_indices.append(i)
324
- col_indices.append(j)
325
-
326
- # Step 4: Create a CSR matrix
327
- num_nodes = len(nodes)
328
- data = np.ones(len(row_indices), dtype=int)
329
- neighborhoods = csr_matrix((data, (row_indices, col_indices)), shape=(num_nodes, num_nodes))
330
-
331
- return neighborhoods
332
-
333
-
334
- def calculate_walktrap_neighborhoods(
335
- network: nx.Graph, fraction_shortest_edges: float = 1.0
336
- ) -> csr_matrix:
337
- """Apply Walktrap Community Detection to the network with CSR matrix output.
338
-
339
- Args:
340
- network (nx.Graph): The network graph.
341
- fraction_shortest_edges (float, optional): Shortest edge rank fraction threshold for creating
342
- subgraphs before clustering. Defaults to 1.0.
343
-
344
- Returns:
345
- csr_matrix: A binary neighborhood matrix (CSR) on Walktrap communities.
346
- """
347
- # Create a subgraph with the shortest edges based on the rank fraction
348
- subnetwork = _create_percentile_limited_subgraph(
349
- network, fraction_shortest_edges=fraction_shortest_edges
350
- )
351
- # Convert NetworkX graph to iGraph
352
- igraph_network = ig.Graph.from_networkx(subnetwork)
353
- # Apply Walktrap community detection
354
- communities = igraph_network.community_walktrap().as_clustering()
355
- # Get the list of nodes in the original NetworkX graph
356
- nodes = list(network.nodes())
357
- node_index_map = {node: idx for idx, node in enumerate(nodes)}
358
- # Prepare data for CSR matrix
359
- row_indices = []
360
- col_indices = []
361
- for community in communities:
362
- mapped_indices = [node_index_map[igraph_network.vs[node]["_nx_name"]] for node in community]
363
- for i in mapped_indices:
364
- for j in mapped_indices:
365
- row_indices.append(i)
366
- col_indices.append(j)
367
-
368
- # Create a CSR matrix
369
- num_nodes = len(nodes)
370
- data = np.ones(len(row_indices), dtype=int)
371
- neighborhoods = csr_matrix((data, (row_indices, col_indices)), shape=(num_nodes, num_nodes))
372
-
373
- return neighborhoods
374
-
375
-
376
- def _create_percentile_limited_subgraph(G: nx.Graph, fraction_shortest_edges: float) -> nx.Graph:
377
- """Create a subgraph containing the shortest edges based on the specified rank fraction
378
- of all edge lengths in the input graph.
379
-
380
- Args:
381
- G (nx.Graph): The input graph with 'length' attributes on edges.
382
- fraction_shortest_edges (float): The rank fraction (between 0 and 1) to filter edges.
383
-
384
- Returns:
385
- nx.Graph: A subgraph with nodes and edges where the edges are within the shortest
386
- specified rank fraction.
387
- """
388
- # Step 1: Extract edges with their lengths
389
- edges_with_length = [(u, v, d) for u, v, d in G.edges(data=True) if "length" in d]
390
- if not edges_with_length:
391
- raise ValueError(
392
- "No edge lengths found in the graph. Ensure edges have 'length' attributes."
393
- )
394
-
395
- # Step 2: Sort edges by length in ascending order
396
- edges_with_length.sort(key=lambda x: x[2]["length"])
397
- # Step 3: Calculate the cutoff index for the given rank fraction
398
- cutoff_index = int(fraction_shortest_edges * len(edges_with_length))
399
- if cutoff_index == 0:
400
- raise ValueError("The rank fraction is too low, resulting in no edges being included.")
401
-
402
- # Step 4: Create the subgraph by selecting only the shortest edges within the rank fraction
403
- subgraph = nx.Graph()
404
- subgraph.add_nodes_from(G.nodes(data=True)) # Retain all nodes from the original graph
405
- subgraph.add_edges_from(edges_with_length[:cutoff_index])
406
- # Step 5: Remove nodes with no edges
407
- subgraph.remove_nodes_from(list(nx.isolates(subgraph)))
408
- # Step 6: Check if the resulting subgraph has no edges and issue a warning
409
- if subgraph.number_of_edges() == 0:
410
- raise Warning("The resulting subgraph has no edges. Consider adjusting the rank fraction.")
411
-
412
- return subgraph