risk-network 0.0.9b11__py3-none-any.whl → 0.0.9b14__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 +1 -1
- risk/neighborhoods/community.py +149 -41
- risk/neighborhoods/neighborhoods.py +37 -86
- risk/network/io.py +5 -3
- risk/network/plot/network.py +2 -2
- {risk_network-0.0.9b11.dist-info → risk_network-0.0.9b14.dist-info}/METADATA +1 -1
- {risk_network-0.0.9b11.dist-info → risk_network-0.0.9b14.dist-info}/RECORD +10 -10
- {risk_network-0.0.9b11.dist-info → risk_network-0.0.9b14.dist-info}/LICENSE +0 -0
- {risk_network-0.0.9b11.dist-info → risk_network-0.0.9b14.dist-info}/WHEEL +0 -0
- {risk_network-0.0.9b11.dist-info → risk_network-0.0.9b14.dist-info}/top_level.txt +0 -0
risk/__init__.py
CHANGED
risk/neighborhoods/community.py
CHANGED
@@ -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(
|
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
|
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(
|
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
|
-
|
31
|
-
neighborhoods
|
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(
|
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(
|
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
|
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,
|
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(
|
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
|
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,
|
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
|
-
|
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
|
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(
|
152
|
-
|
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
|
-
#
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
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
|
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
|
-
|
173
|
-
|
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
|
178
|
-
original_node_i =
|
179
|
-
original_node_j =
|
180
|
-
|
181
|
-
|
182
|
-
|
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(
|
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
|
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(
|
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
|
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(
|
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(
|
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
|
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
|
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
|
71
|
-
for metric,
|
72
|
-
#
|
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(
|
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(
|
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
|
-
|
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
|
-
|
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(
|
97
|
+
neighborhoods = calculate_markov_clustering_neighborhoods(
|
98
|
+
network, edge_rank_percentile=percentile
|
99
|
+
)
|
90
100
|
elif metric == "spinglass":
|
91
|
-
neighborhoods = calculate_spinglass_neighborhoods(
|
101
|
+
neighborhoods = calculate_spinglass_neighborhoods(
|
102
|
+
network, edge_rank_percentile=percentile
|
103
|
+
)
|
92
104
|
elif metric == "walktrap":
|
93
|
-
neighborhoods = calculate_walktrap_neighborhoods(
|
105
|
+
neighborhoods = calculate_walktrap_neighborhoods(
|
106
|
+
network, edge_rank_percentile=percentile
|
107
|
+
)
|
94
108
|
else:
|
95
109
|
raise ValueError(
|
96
|
-
"
|
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
|
-
#
|
101
|
-
|
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
|
-
#
|
108
|
-
|
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
|
risk/network/io.py
CHANGED
@@ -379,15 +379,17 @@ class NetworkIO:
|
|
379
379
|
node_y_positions = {}
|
380
380
|
for node in cyjs_data["elements"]["nodes"]:
|
381
381
|
node_data = node["data"]
|
382
|
-
|
382
|
+
# Use the original node ID if available, otherwise use the default ID
|
383
|
+
node_id = node_data.get("id_original", node_data.get("id"))
|
383
384
|
node_x_positions[node_id] = node["position"]["x"]
|
384
385
|
node_y_positions[node_id] = node["position"]["y"]
|
385
386
|
|
386
387
|
# Process edges and add them to the graph
|
387
388
|
for edge in cyjs_data["elements"]["edges"]:
|
388
389
|
edge_data = edge["data"]
|
389
|
-
source
|
390
|
-
|
390
|
+
# Use the original source and target labels if available, otherwise fall back to default labels
|
391
|
+
source = edge_data.get(f"{source_label}_original", edge_data.get(source_label))
|
392
|
+
target = edge_data.get(f"{target_label}_original", edge_data.get(target_label))
|
391
393
|
# Add the edge to the graph, optionally including weights
|
392
394
|
if self.weight_label is not None and self.weight_label in edge_data:
|
393
395
|
weight = float(edge_data[self.weight_label])
|
risk/network/plot/network.py
CHANGED
@@ -250,11 +250,11 @@ class Network:
|
|
250
250
|
nonsignificant_color_rgba = to_rgba(
|
251
251
|
color=nonsignificant_color, alpha=nonsignificant_alpha, num_repeats=1
|
252
252
|
) # num_repeats=1 for a single color
|
253
|
-
# Adjust node colors: replace any nodes where all three RGB values are equal and less than 0.1
|
253
|
+
# Adjust node colors: replace any nodes where all three RGB values are equal and less than or equal to 0.1
|
254
254
|
# 0.1 is a predefined threshold for the minimum color intensity
|
255
255
|
adjusted_network_colors = np.where(
|
256
256
|
(
|
257
|
-
np.all(network_colors[:, :3]
|
257
|
+
np.all(network_colors[:, :3] <= 0.1, axis=1)
|
258
258
|
& np.all(network_colors[:, :3] == network_colors[:, 0:1], axis=1)
|
259
259
|
)[:, None],
|
260
260
|
np.tile(
|
@@ -1,4 +1,4 @@
|
|
1
|
-
risk/__init__.py,sha256=
|
1
|
+
risk/__init__.py,sha256=Iidh958zzqC-3UdCs4vJpPixUJXUPBHxeQJYNHO4IHI,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,12 +8,12 @@ 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=
|
11
|
+
risk/neighborhoods/community.py,sha256=hsWr6sNW3lCZn9L2f8oYBVmIANnJpoAL9194fg6K1eQ,15408
|
12
12
|
risk/neighborhoods/domains.py,sha256=t91xSpx9Ty9hSlhRq2_XwyPpBP7sjKhovcPPvkwWtf0,11398
|
13
|
-
risk/neighborhoods/neighborhoods.py,sha256=
|
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
|
-
risk/network/io.py,sha256=
|
16
|
+
risk/network/io.py,sha256=Dl-Xwv1gWdmvDkZ77581s_JYO5ujZjvmHG7wq_-ApZU,23239
|
17
17
|
risk/network/graph/__init__.py,sha256=H0YEiwqZ02LBTkH4blPwUjQ-DOUnhaTTNHM0BcXii6U,81
|
18
18
|
risk/network/graph/network.py,sha256=JzYbrgJLiNWFyPIR6_qNSjMtmXmfzRv2FwWSdyg8HjY,12205
|
19
19
|
risk/network/graph/summary.py,sha256=h2bpUjfwI1NMflkKwplGQEGPswfAtunormdTIEQYbvs,8987
|
@@ -21,7 +21,7 @@ risk/network/plot/__init__.py,sha256=MfmaXJgAZJgXZ2wrhK8pXwzETlcMaLChhWXKAozniAo
|
|
21
21
|
risk/network/plot/canvas.py,sha256=W8dFv4XYTzCWXBchgsc0esOQRn4usM4LkwNGPSDMobE,13357
|
22
22
|
risk/network/plot/contour.py,sha256=VONX9l6owrZvWtR0mWQ6z2GSd1YXIv5wV_sf5ROQLT4,15581
|
23
23
|
risk/network/plot/labels.py,sha256=aU_ClDGVPHyQ3H5E_ygx8hsMhrpJB0i9Cn65PlLmw7s,45679
|
24
|
-
risk/network/plot/network.py,sha256=
|
24
|
+
risk/network/plot/network.py,sha256=0j7pAZgt9PBfFCnOz4QwXnYWTlnLjTrtMm-50I_1G8o,14028
|
25
25
|
risk/network/plot/plotter.py,sha256=eS1vHqvOA2O001Rq7WiDcgqcehJ3fg4OPfvkezH4erw,5771
|
26
26
|
risk/network/plot/utils/colors.py,sha256=9zuU2O-Nkpljb1yVGUR_IjqD1y-wH6Bf6Vm1MMVB0Lo,18718
|
27
27
|
risk/network/plot/utils/layout.py,sha256=6o7idoWQnyzujSWOFXQykUvyPy8NuRtJV04TnlbXXBo,3647
|
@@ -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.
|
36
|
-
risk_network-0.0.
|
37
|
-
risk_network-0.0.
|
38
|
-
risk_network-0.0.
|
39
|
-
risk_network-0.0.
|
35
|
+
risk_network-0.0.9b14.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
36
|
+
risk_network-0.0.9b14.dist-info/METADATA,sha256=-H8Qrl5r36ZNGNJO3RHOzUOi_CzgplZf061rYGcIfJI,47552
|
37
|
+
risk_network-0.0.9b14.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
|
38
|
+
risk_network-0.0.9b14.dist-info/top_level.txt,sha256=NX7C2PFKTvC1JhVKv14DFlFAIFnKc6Lpsu1ZfxvQwVw,5
|
39
|
+
risk_network-0.0.9b14.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|