risk-network 0.0.7b12__py3-none-any.whl → 0.0.8__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/annotations/__init__.py +1 -1
- risk/annotations/annotations.py +85 -53
- risk/annotations/io.py +3 -3
- risk/log/__init__.py +1 -1
- risk/log/{config.py → console.py} +2 -2
- risk/log/params.py +6 -6
- risk/neighborhoods/community.py +68 -61
- risk/neighborhoods/domains.py +41 -18
- risk/neighborhoods/neighborhoods.py +134 -69
- risk/network/geometry.py +5 -2
- risk/network/graph.py +69 -235
- risk/network/io.py +44 -6
- risk/network/plot/__init__.py +6 -0
- risk/network/plot/canvas.py +290 -0
- risk/network/plot/contour.py +327 -0
- risk/network/plot/labels.py +929 -0
- risk/network/plot/network.py +288 -0
- risk/network/plot/plotter.py +137 -0
- risk/network/plot/utils/color.py +424 -0
- risk/network/plot/utils/layout.py +91 -0
- risk/risk.py +70 -37
- risk/stats/hypergeom.py +1 -1
- risk/stats/permutation/permutation.py +21 -8
- risk/stats/poisson.py +2 -2
- risk/stats/stats.py +12 -10
- {risk_network-0.0.7b12.dist-info → risk_network-0.0.8.dist-info}/METADATA +84 -21
- risk_network-0.0.8.dist-info/RECORD +37 -0
- {risk_network-0.0.7b12.dist-info → risk_network-0.0.8.dist-info}/WHEEL +1 -1
- risk/network/plot.py +0 -1450
- risk_network-0.0.7b12.dist-info/RECORD +0 -30
- {risk_network-0.0.7b12.dist-info → risk_network-0.0.8.dist-info}/LICENSE +0 -0
- {risk_network-0.0.7b12.dist-info → risk_network-0.0.8.dist-info}/top_level.txt +0 -0
risk/__init__.py
CHANGED
risk/annotations/__init__.py
CHANGED
risk/annotations/annotations.py
CHANGED
@@ -3,6 +3,7 @@ risk/annotations/annotations
|
|
3
3
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
4
4
|
"""
|
5
5
|
|
6
|
+
import re
|
6
7
|
from collections import Counter
|
7
8
|
from itertools import compress
|
8
9
|
from typing import Any, Dict, List, Set
|
@@ -30,27 +31,30 @@ def _setup_nltk():
|
|
30
31
|
|
31
32
|
# Ensure you have the necessary NLTK data
|
32
33
|
_setup_nltk()
|
34
|
+
# Initialize English stopwords
|
35
|
+
stop_words = set(stopwords.words("english"))
|
33
36
|
|
34
37
|
|
35
38
|
def load_annotations(network: nx.Graph, annotations_input: Dict[str, Any]) -> Dict[str, Any]:
|
36
39
|
"""Convert annotations input to a DataFrame and reindex based on the network's node labels.
|
37
40
|
|
38
41
|
Args:
|
39
|
-
|
42
|
+
network (nx.Graph): The network graph.
|
43
|
+
annotations_input (Dict[str, Any]): A dictionary with annotations.
|
40
44
|
|
41
45
|
Returns:
|
42
|
-
|
46
|
+
Dict[str, Any]: A dictionary containing ordered nodes, ordered annotations, and the binary annotations matrix.
|
43
47
|
"""
|
44
48
|
# Flatten the dictionary to a list of tuples for easier DataFrame creation
|
45
49
|
flattened_annotations = [
|
46
50
|
(node, annotation) for annotation, nodes in annotations_input.items() for node in nodes
|
47
51
|
]
|
48
52
|
# Create a DataFrame from the flattened list
|
49
|
-
annotations = pd.DataFrame(flattened_annotations, columns=["
|
50
|
-
annotations["
|
53
|
+
annotations = pd.DataFrame(flattened_annotations, columns=["node", "annotations"])
|
54
|
+
annotations["is_member"] = 1
|
51
55
|
# Pivot to create a binary matrix with nodes as rows and annotations as columns
|
52
56
|
annotations_pivot = annotations.pivot_table(
|
53
|
-
index="
|
57
|
+
index="node", columns="annotations", values="is_member", fill_value=0, dropna=False
|
54
58
|
)
|
55
59
|
# Reindex the annotations matrix based on the node labels from the network
|
56
60
|
node_label_order = list(nx.get_node_attributes(network, "label").values())
|
@@ -80,7 +84,8 @@ def define_top_annotations(
|
|
80
84
|
network: nx.Graph,
|
81
85
|
ordered_annotation_labels: List[str],
|
82
86
|
neighborhood_enrichment_sums: List[int],
|
83
|
-
|
87
|
+
significant_enrichment_matrix: np.ndarray,
|
88
|
+
significant_binary_enrichment_matrix: np.ndarray,
|
84
89
|
min_cluster_size: int = 5,
|
85
90
|
max_cluster_size: int = 1000,
|
86
91
|
) -> pd.DataFrame:
|
@@ -90,42 +95,52 @@ def define_top_annotations(
|
|
90
95
|
network (NetworkX graph): The network graph.
|
91
96
|
ordered_annotation_labels (list of str): List of ordered annotation labels.
|
92
97
|
neighborhood_enrichment_sums (list of int): List of neighborhood enrichment sums.
|
93
|
-
|
98
|
+
significant_enrichment_matrix (np.ndarray): Enrichment matrix below alpha threshold.
|
99
|
+
significant_binary_enrichment_matrix (np.ndarray): Binary enrichment matrix below alpha threshold.
|
94
100
|
min_cluster_size (int, optional): Minimum cluster size. Defaults to 5.
|
95
101
|
max_cluster_size (int, optional): Maximum cluster size. Defaults to 1000.
|
96
102
|
|
97
103
|
Returns:
|
98
104
|
pd.DataFrame: DataFrame with top annotations and their properties.
|
99
105
|
"""
|
100
|
-
#
|
106
|
+
# Sum the columns of the significant enrichment matrix (positive floating point values)
|
107
|
+
significant_enrichment_scores = significant_enrichment_matrix.sum(axis=0)
|
108
|
+
# Create DataFrame to store annotations, their neighborhood enrichment sums, and enrichment scores
|
101
109
|
annotations_enrichment_matrix = pd.DataFrame(
|
102
110
|
{
|
103
111
|
"id": range(len(ordered_annotation_labels)),
|
104
|
-
"
|
105
|
-
"
|
112
|
+
"full_terms": ordered_annotation_labels,
|
113
|
+
"significant_neighborhood_enrichment_sums": neighborhood_enrichment_sums,
|
114
|
+
"significant_enrichment_score": significant_enrichment_scores,
|
106
115
|
}
|
107
116
|
)
|
108
|
-
annotations_enrichment_matrix["
|
109
|
-
# Apply size constraints to identify potential
|
117
|
+
annotations_enrichment_matrix["significant_annotations"] = False
|
118
|
+
# Apply size constraints to identify potential significant annotations
|
110
119
|
annotations_enrichment_matrix.loc[
|
111
|
-
(
|
112
|
-
|
113
|
-
|
120
|
+
(
|
121
|
+
annotations_enrichment_matrix["significant_neighborhood_enrichment_sums"]
|
122
|
+
>= min_cluster_size
|
123
|
+
)
|
124
|
+
& (
|
125
|
+
annotations_enrichment_matrix["significant_neighborhood_enrichment_sums"]
|
126
|
+
<= max_cluster_size
|
127
|
+
),
|
128
|
+
"significant_annotations",
|
114
129
|
] = True
|
115
130
|
# Initialize columns for connected components analysis
|
116
|
-
annotations_enrichment_matrix["
|
117
|
-
annotations_enrichment_matrix["
|
118
|
-
annotations_enrichment_matrix["
|
119
|
-
"
|
131
|
+
annotations_enrichment_matrix["num_connected_components"] = 0
|
132
|
+
annotations_enrichment_matrix["size_connected_components"] = None
|
133
|
+
annotations_enrichment_matrix["size_connected_components"] = annotations_enrichment_matrix[
|
134
|
+
"size_connected_components"
|
120
135
|
].astype(object)
|
121
|
-
annotations_enrichment_matrix["
|
136
|
+
annotations_enrichment_matrix["num_large_connected_components"] = 0
|
122
137
|
|
123
138
|
for attribute in annotations_enrichment_matrix.index.values[
|
124
|
-
annotations_enrichment_matrix["
|
139
|
+
annotations_enrichment_matrix["significant_annotations"]
|
125
140
|
]:
|
126
141
|
# Identify enriched neighborhoods based on the binary enrichment matrix
|
127
142
|
enriched_neighborhoods = list(
|
128
|
-
compress(list(network),
|
143
|
+
compress(list(network), significant_binary_enrichment_matrix[:, attribute])
|
129
144
|
)
|
130
145
|
enriched_network = nx.subgraph(network, enriched_neighborhoods)
|
131
146
|
# Analyze connected components within the enriched subnetwork
|
@@ -144,57 +159,74 @@ def define_top_annotations(
|
|
144
159
|
num_large_connected_components = len(filtered_size_connected_components)
|
145
160
|
|
146
161
|
# Assign the number of connected components
|
147
|
-
annotations_enrichment_matrix.loc[attribute, "
|
162
|
+
annotations_enrichment_matrix.loc[attribute, "num_connected_components"] = (
|
148
163
|
num_connected_components
|
149
164
|
)
|
150
165
|
# Filter out attributes with more than one connected component
|
151
166
|
annotations_enrichment_matrix.loc[
|
152
|
-
annotations_enrichment_matrix["
|
167
|
+
annotations_enrichment_matrix["num_connected_components"] > 1, "significant_annotations"
|
153
168
|
] = False
|
154
169
|
# Assign the number of large connected components
|
155
|
-
annotations_enrichment_matrix.loc[attribute, "
|
170
|
+
annotations_enrichment_matrix.loc[attribute, "num_large_connected_components"] = (
|
156
171
|
num_large_connected_components
|
157
172
|
)
|
158
173
|
# Assign the size of connected components, ensuring it is always a list
|
159
|
-
annotations_enrichment_matrix.at[attribute, "
|
174
|
+
annotations_enrichment_matrix.at[attribute, "size_connected_components"] = (
|
160
175
|
filtered_size_connected_components.tolist()
|
161
176
|
)
|
162
177
|
|
163
178
|
return annotations_enrichment_matrix
|
164
179
|
|
165
180
|
|
166
|
-
def
|
167
|
-
"""
|
168
|
-
|
181
|
+
def get_weighted_description(words_column: pd.Series, scores_column: pd.Series) -> str:
|
182
|
+
"""Generate a weighted description from words and their corresponding scores,
|
183
|
+
with support for stopwords filtering and improved weighting logic.
|
169
184
|
|
170
185
|
Args:
|
171
186
|
words_column (pd.Series): A pandas Series containing strings to process.
|
187
|
+
scores_column (pd.Series): A pandas Series containing enrichment scores to weigh the terms.
|
172
188
|
|
173
189
|
Returns:
|
174
|
-
str: A coherent description formed from the most frequent and significant words.
|
190
|
+
str: A coherent description formed from the most frequent and significant words, weighed by enrichment scores.
|
175
191
|
"""
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
192
|
+
# Handle case where all scores are the same
|
193
|
+
if scores_column.max() == scores_column.min():
|
194
|
+
normalized_scores = pd.Series([1] * len(scores_column))
|
195
|
+
else:
|
196
|
+
# Normalize the enrichment scores to be between 0 and 1
|
197
|
+
normalized_scores = (scores_column - scores_column.min()) / (
|
198
|
+
scores_column.max() - scores_column.min()
|
199
|
+
)
|
200
|
+
|
201
|
+
# Combine words and normalized scores to create weighted words
|
202
|
+
weighted_words = []
|
203
|
+
for word, score in zip(words_column, normalized_scores):
|
204
|
+
word = str(word)
|
205
|
+
if word not in stop_words: # Skip stopwords
|
206
|
+
weight = max(1, int((0 if pd.isna(score) else score) * 10))
|
207
|
+
weighted_words.extend([word] * weight)
|
208
|
+
|
209
|
+
# Tokenize the weighted words, but preserve number-word patterns like '4-alpha'
|
210
|
+
tokens = word_tokenize(" ".join(weighted_words))
|
211
|
+
# Ensure we treat "4-alpha" or other "number-word" patterns as single tokens
|
212
|
+
combined_tokens = []
|
213
|
+
for token in tokens:
|
214
|
+
# Match patterns like '4-alpha' or '5-hydroxy' and keep them together
|
215
|
+
if re.match(r"^\d+-\w+", token):
|
216
|
+
combined_tokens.append(token)
|
217
|
+
elif token.replace(".", "", 1).isdigit(): # Handle pure numeric tokens
|
218
|
+
# Ignore pure numbers as descriptions unless necessary
|
219
|
+
continue
|
220
|
+
else:
|
221
|
+
combined_tokens.append(token)
|
222
|
+
|
223
|
+
# Prevent descriptions like just '4' from being selected
|
224
|
+
if len(combined_tokens) == 1 and combined_tokens[0].isdigit():
|
225
|
+
return "N/A" # Return "N/A" for cases where it's just a number
|
226
|
+
|
227
|
+
# Simplify the word list and generate the description
|
228
|
+
simplified_words = _simplify_word_list(combined_tokens)
|
229
|
+
description = _generate_coherent_description(simplified_words)
|
198
230
|
|
199
231
|
return description
|
200
232
|
|
@@ -257,7 +289,7 @@ def _generate_coherent_description(words: List[str]) -> str:
|
|
257
289
|
If there is only one unique entry, return it directly.
|
258
290
|
|
259
291
|
Args:
|
260
|
-
words (
|
292
|
+
words (List): A list of words or numerical string values.
|
261
293
|
|
262
294
|
Returns:
|
263
295
|
str: A coherent description formed by arranging the words in a logical sequence.
|
risk/annotations/io.py
CHANGED
@@ -33,7 +33,7 @@ class AnnotationsIO:
|
|
33
33
|
filepath (str): Path to the JSON annotations file.
|
34
34
|
|
35
35
|
Returns:
|
36
|
-
|
36
|
+
Dict[str, Any]: A dictionary containing ordered nodes, ordered annotations, and the annotations matrix.
|
37
37
|
"""
|
38
38
|
filetype = "JSON"
|
39
39
|
# Log the loading of the JSON file
|
@@ -158,10 +158,10 @@ class AnnotationsIO:
|
|
158
158
|
|
159
159
|
Args:
|
160
160
|
network (NetworkX graph): The network to which the annotations are related.
|
161
|
-
content (
|
161
|
+
content (Dict[str, Any]): The annotations dictionary to load.
|
162
162
|
|
163
163
|
Returns:
|
164
|
-
|
164
|
+
Dict[str, Any]: A dictionary containing ordered nodes, ordered annotations, and the annotations matrix.
|
165
165
|
"""
|
166
166
|
# Ensure the input content is a dictionary
|
167
167
|
if not isinstance(content, dict):
|
risk/log/__init__.py
CHANGED
risk/log/params.py
CHANGED
@@ -12,7 +12,7 @@ from typing import Any, Dict
|
|
12
12
|
|
13
13
|
import numpy as np
|
14
14
|
|
15
|
-
from .
|
15
|
+
from .console import logger, log_header
|
16
16
|
|
17
17
|
# Suppress all warnings - this is to resolve warnings from multiprocessing
|
18
18
|
warnings.filterwarnings("ignore")
|
@@ -159,7 +159,7 @@ class Params:
|
|
159
159
|
"""Load and process various parameters, converting any np.ndarray values to lists.
|
160
160
|
|
161
161
|
Returns:
|
162
|
-
|
162
|
+
Dict[str, Any]: A dictionary containing the processed parameters.
|
163
163
|
"""
|
164
164
|
log_header("Loading parameters")
|
165
165
|
return _convert_ndarray_to_list(
|
@@ -174,14 +174,14 @@ class Params:
|
|
174
174
|
)
|
175
175
|
|
176
176
|
|
177
|
-
def _convert_ndarray_to_list(d: Any) -> Any:
|
177
|
+
def _convert_ndarray_to_list(d: Dict[str, Any]) -> Dict[str, Any]:
|
178
178
|
"""Recursively convert all np.ndarray values in the dictionary to lists.
|
179
179
|
|
180
180
|
Args:
|
181
|
-
d (
|
181
|
+
d (Dict[str, Any]): The dictionary to process.
|
182
182
|
|
183
183
|
Returns:
|
184
|
-
|
184
|
+
Dict[str, Any]: The processed dictionary with np.ndarray values converted to lists.
|
185
185
|
"""
|
186
186
|
if isinstance(d, dict):
|
187
187
|
# Recursively process each value in the dictionary
|
@@ -193,5 +193,5 @@ def _convert_ndarray_to_list(d: Any) -> Any:
|
|
193
193
|
# Convert numpy arrays to lists
|
194
194
|
return d.tolist()
|
195
195
|
else:
|
196
|
-
# Return the value unchanged if it's not a dict,
|
196
|
+
# Return the value unchanged if it's not a dict, List, or ndarray
|
197
197
|
return d
|
risk/neighborhoods/community.py
CHANGED
@@ -21,15 +21,20 @@ def calculate_greedy_modularity_neighborhoods(network: nx.Graph) -> np.ndarray:
|
|
21
21
|
"""
|
22
22
|
# Detect communities using the Greedy Modularity method
|
23
23
|
communities = greedy_modularity_communities(network)
|
24
|
-
# Create a mapping from node to community
|
25
|
-
community_dict = {node: idx for idx, community in enumerate(communities) for node in community}
|
26
24
|
# Create a binary neighborhood matrix
|
27
|
-
|
25
|
+
n_nodes = network.number_of_nodes()
|
26
|
+
neighborhoods = np.zeros((n_nodes, n_nodes), dtype=int)
|
27
|
+
# Create a mapping from node to index in the matrix
|
28
28
|
node_index = {node: i for i, node in enumerate(network.nodes())}
|
29
|
-
for
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
# Fill in the neighborhood matrix for nodes in the same community
|
30
|
+
for community in communities:
|
31
|
+
# Iterate through all pairs of nodes in the same community
|
32
|
+
for node_i in community:
|
33
|
+
idx_i = node_index[node_i]
|
34
|
+
for node_j in community:
|
35
|
+
idx_j = node_index[node_j]
|
36
|
+
# Set them as neighbors (1) in the binary matrix
|
37
|
+
neighborhoods[idx_i, idx_j] = 1
|
33
38
|
|
34
39
|
return neighborhoods
|
35
40
|
|
@@ -43,22 +48,20 @@ def calculate_label_propagation_neighborhoods(network: nx.Graph) -> np.ndarray:
|
|
43
48
|
Returns:
|
44
49
|
np.ndarray: Binary neighborhood matrix on Label Propagation.
|
45
50
|
"""
|
46
|
-
# Apply Label Propagation
|
51
|
+
# Apply Label Propagation for community detection
|
47
52
|
communities = nx.algorithms.community.label_propagation.label_propagation_communities(network)
|
48
|
-
# Create a mapping from node to community
|
49
|
-
community_dict = {}
|
50
|
-
for community_id, community in enumerate(communities):
|
51
|
-
for node in community:
|
52
|
-
community_dict[node] = community_id
|
53
|
-
|
54
53
|
# Create a binary neighborhood matrix
|
55
54
|
num_nodes = network.number_of_nodes()
|
56
55
|
neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
|
56
|
+
# Create a mapping from node to index in the matrix
|
57
|
+
node_index = {node: i for i, node in enumerate(network.nodes())}
|
57
58
|
# Assign neighborhoods based on community labels
|
58
|
-
for
|
59
|
-
for
|
60
|
-
|
61
|
-
|
59
|
+
for community in communities:
|
60
|
+
for node_i in community:
|
61
|
+
idx_i = node_index[node_i]
|
62
|
+
for node_j in community:
|
63
|
+
idx_j = node_index[node_j]
|
64
|
+
neighborhoods[idx_i, idx_j] = 1
|
62
65
|
|
63
66
|
return neighborhoods
|
64
67
|
|
@@ -81,12 +84,22 @@ def calculate_louvain_neighborhoods(
|
|
81
84
|
network, resolution=resolution, random_state=random_seed
|
82
85
|
)
|
83
86
|
# Create a binary neighborhood matrix
|
84
|
-
|
87
|
+
num_nodes = network.number_of_nodes()
|
88
|
+
neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
|
89
|
+
# Create a mapping from node to index in the matrix
|
90
|
+
node_index = {node: i for i, node in enumerate(network.nodes())}
|
91
|
+
# Group nodes by community
|
92
|
+
community_groups = {}
|
93
|
+
for node, community in partition.items():
|
94
|
+
community_groups.setdefault(community, []).append(node)
|
95
|
+
|
85
96
|
# Assign neighborhoods based on community partitions
|
86
|
-
for
|
87
|
-
for
|
88
|
-
|
89
|
-
|
97
|
+
for community, nodes in community_groups.items():
|
98
|
+
for node_i in nodes:
|
99
|
+
idx_i = node_index[node_i]
|
100
|
+
for node_j in nodes:
|
101
|
+
idx_j = node_index[node_j]
|
102
|
+
neighborhoods[idx_i, idx_j] = 1
|
90
103
|
|
91
104
|
return neighborhoods
|
92
105
|
|
@@ -102,24 +115,22 @@ def calculate_markov_clustering_neighborhoods(network: nx.Graph) -> np.ndarray:
|
|
102
115
|
"""
|
103
116
|
# Convert the graph to an adjacency matrix
|
104
117
|
adjacency_matrix = nx.to_numpy_array(network)
|
105
|
-
# Run Markov Clustering
|
106
|
-
result = mc.run_mcl(adjacency_matrix) #
|
107
|
-
# Get clusters
|
118
|
+
# Run Markov Clustering (MCL)
|
119
|
+
result = mc.run_mcl(adjacency_matrix) # MCL with default parameters
|
120
|
+
# Get clusters (communities) from MCL result
|
108
121
|
clusters = mc.get_clusters(result)
|
109
|
-
# Create a community label for each node
|
110
|
-
community_dict = {}
|
111
|
-
for community_id, community in enumerate(clusters):
|
112
|
-
for node in community:
|
113
|
-
community_dict[node] = community_id
|
114
|
-
|
115
122
|
# Create a binary neighborhood matrix
|
116
123
|
num_nodes = network.number_of_nodes()
|
117
124
|
neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
|
118
|
-
#
|
119
|
-
for
|
120
|
-
|
121
|
-
|
122
|
-
|
125
|
+
# Create a mapping from node to index in the matrix
|
126
|
+
node_index = {node: i for i, node in enumerate(network.nodes())}
|
127
|
+
# Assign neighborhoods based on MCL clusters
|
128
|
+
for cluster in clusters:
|
129
|
+
for node_i in cluster:
|
130
|
+
idx_i = node_index[node_i]
|
131
|
+
for node_j in cluster:
|
132
|
+
idx_j = node_index[node_j]
|
133
|
+
neighborhoods[idx_i, idx_j] = 1
|
123
134
|
|
124
135
|
return neighborhoods
|
125
136
|
|
@@ -133,22 +144,20 @@ def calculate_spinglass_neighborhoods(network: nx.Graph) -> np.ndarray:
|
|
133
144
|
Returns:
|
134
145
|
np.ndarray: Binary neighborhood matrix on Spin Glass communities.
|
135
146
|
"""
|
136
|
-
#
|
147
|
+
# Apply Asynchronous Label Propagation (LPA)
|
137
148
|
communities = asyn_lpa_communities(network)
|
138
|
-
# Create a community label for each node
|
139
|
-
community_dict = {}
|
140
|
-
for community_id, community in enumerate(communities):
|
141
|
-
for node in community:
|
142
|
-
community_dict[node] = community_id
|
143
|
-
|
144
149
|
# Create a binary neighborhood matrix
|
145
150
|
num_nodes = network.number_of_nodes()
|
146
151
|
neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
|
147
|
-
#
|
148
|
-
for
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
+
# Create a mapping from node to index in the matrix
|
153
|
+
node_index = {node: i for i, node in enumerate(network.nodes())}
|
154
|
+
# Assign neighborhoods based on community labels from LPA
|
155
|
+
for community in communities:
|
156
|
+
for node_i in community:
|
157
|
+
idx_i = node_index[node_i]
|
158
|
+
for node_j in community:
|
159
|
+
idx_j = node_index[node_j]
|
160
|
+
neighborhoods[idx_i, idx_j] = 1
|
152
161
|
|
153
162
|
return neighborhoods
|
154
163
|
|
@@ -162,21 +171,19 @@ def calculate_walktrap_neighborhoods(network: nx.Graph) -> np.ndarray:
|
|
162
171
|
Returns:
|
163
172
|
np.ndarray: Binary neighborhood matrix on Walktrap communities.
|
164
173
|
"""
|
165
|
-
#
|
174
|
+
# Apply Asynchronous Label Propagation (LPA)
|
166
175
|
communities = asyn_lpa_communities(network)
|
167
|
-
# Create a community label for each node
|
168
|
-
community_dict = {}
|
169
|
-
for community_id, community in enumerate(communities):
|
170
|
-
for node in community:
|
171
|
-
community_dict[node] = community_id
|
172
|
-
|
173
176
|
# Create a binary neighborhood matrix
|
174
177
|
num_nodes = network.number_of_nodes()
|
175
178
|
neighborhoods = np.zeros((num_nodes, num_nodes), dtype=int)
|
176
|
-
#
|
177
|
-
for
|
178
|
-
|
179
|
-
|
180
|
-
|
179
|
+
# Create a mapping from node to index in the matrix
|
180
|
+
node_index = {node: i for i, node in enumerate(network.nodes())}
|
181
|
+
# Assign neighborhoods based on community labels from LPA
|
182
|
+
for community in communities:
|
183
|
+
for node_i in community:
|
184
|
+
idx_i = node_index[node_i]
|
185
|
+
for node_j in community:
|
186
|
+
idx_j = node_index[node_j]
|
187
|
+
neighborhoods[idx_i, idx_j] = 1
|
181
188
|
|
182
189
|
return neighborhoods
|