risk-network 0.0.12b1__py3-none-any.whl → 0.0.12b3__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/annotation/__init__.py +10 -0
- risk/{annotations/annotations.py → annotation/annotation.py} +44 -44
- risk/{annotations → annotation}/io.py +46 -46
- risk/{annotations → annotation}/nltk_setup.py +4 -4
- risk/log/parameters.py +5 -5
- risk/neighborhoods/api.py +36 -36
- risk/neighborhoods/domains.py +20 -24
- risk/neighborhoods/neighborhoods.py +4 -4
- risk/neighborhoods/stats/permutation/permutation.py +17 -17
- risk/neighborhoods/stats/permutation/test_functions.py +2 -2
- risk/neighborhoods/stats/tests.py +41 -41
- risk/network/graph/api.py +17 -17
- risk/network/graph/graph.py +17 -11
- risk/network/graph/summary.py +10 -10
- risk/network/io.py +12 -12
- risk/network/plotter/canvas.py +1 -1
- risk/network/plotter/contour.py +3 -3
- risk/network/plotter/labels.py +72 -74
- risk/network/plotter/network.py +6 -6
- risk/network/plotter/plotter.py +6 -6
- risk/network/plotter/utils/colors.py +12 -8
- risk/network/plotter/utils/layout.py +3 -3
- risk/risk.py +2 -2
- {risk_network-0.0.12b1.dist-info → risk_network-0.0.12b3.dist-info}/METADATA +1 -1
- risk_network-0.0.12b3.dist-info/RECORD +40 -0
- {risk_network-0.0.12b1.dist-info → risk_network-0.0.12b3.dist-info}/WHEEL +1 -1
- risk/annotations/__init__.py +0 -10
- risk_network-0.0.12b1.dist-info/RECORD +0 -40
- {risk_network-0.0.12b1.dist-info → risk_network-0.0.12b3.dist-info}/licenses/LICENSE +0 -0
- {risk_network-0.0.12b1.dist-info → risk_network-0.0.12b3.dist-info}/top_level.txt +0 -0
@@ -12,15 +12,15 @@ from scipy.stats import binom, chi2, hypergeom, norm, poisson
|
|
12
12
|
|
13
13
|
def compute_binom_test(
|
14
14
|
neighborhoods: csr_matrix,
|
15
|
-
|
15
|
+
annotation: csr_matrix,
|
16
16
|
null_distribution: str = "network",
|
17
17
|
) -> Dict[str, Any]:
|
18
18
|
"""Compute Binomial test for enrichment and depletion in neighborhoods with selectable null distribution.
|
19
19
|
|
20
20
|
Args:
|
21
21
|
neighborhoods (csr_matrix): Sparse binary matrix representing neighborhoods.
|
22
|
-
|
23
|
-
null_distribution (str, optional): Type of null distribution ('network' or '
|
22
|
+
annotation (csr_matrix): Sparse binary matrix representing annotation.
|
23
|
+
null_distribution (str, optional): Type of null distribution ('network' or 'annotation'). Defaults to "network".
|
24
24
|
|
25
25
|
Returns:
|
26
26
|
Dict[str, Any]: Dictionary containing depletion and enrichment p-values.
|
@@ -33,19 +33,19 @@ def compute_binom_test(
|
|
33
33
|
|
34
34
|
# Compute sums (remain sparse here)
|
35
35
|
neighborhood_sizes = neighborhoods.sum(axis=1) # Row sums
|
36
|
-
annotation_totals =
|
36
|
+
annotation_totals = annotation.sum(axis=0) # Column sums
|
37
37
|
# Compute probabilities (convert to dense)
|
38
38
|
if null_distribution == "network":
|
39
39
|
p_values = (annotation_totals / total_nodes).A.flatten() # Dense 1D array
|
40
|
-
elif null_distribution == "
|
41
|
-
p_values = (annotation_totals /
|
40
|
+
elif null_distribution == "annotation":
|
41
|
+
p_values = (annotation_totals / annotation.sum()).A.flatten() # Dense 1D array
|
42
42
|
else:
|
43
43
|
raise ValueError(
|
44
|
-
"Invalid null_distribution value. Choose either 'network' or '
|
44
|
+
"Invalid null_distribution value. Choose either 'network' or 'annotation'."
|
45
45
|
)
|
46
46
|
|
47
47
|
# Observed counts (sparse matrix multiplication)
|
48
|
-
annotated_counts = neighborhoods @
|
48
|
+
annotated_counts = neighborhoods @ annotation # Sparse result
|
49
49
|
annotated_counts_dense = annotated_counts.toarray() # Convert for dense operations
|
50
50
|
|
51
51
|
# Compute enrichment and depletion p-values
|
@@ -57,15 +57,15 @@ def compute_binom_test(
|
|
57
57
|
|
58
58
|
def compute_chi2_test(
|
59
59
|
neighborhoods: csr_matrix,
|
60
|
-
|
60
|
+
annotation: csr_matrix,
|
61
61
|
null_distribution: str = "network",
|
62
62
|
) -> Dict[str, Any]:
|
63
63
|
"""Compute chi-squared test for enrichment and depletion in neighborhoods with selectable null distribution.
|
64
64
|
|
65
65
|
Args:
|
66
66
|
neighborhoods (csr_matrix): Sparse binary matrix representing neighborhoods.
|
67
|
-
|
68
|
-
null_distribution (str, optional): Type of null distribution ('network' or '
|
67
|
+
annotation (csr_matrix): Sparse binary matrix representing annotation.
|
68
|
+
null_distribution (str, optional): Type of null distribution ('network' or 'annotation'). Defaults to "network".
|
69
69
|
|
70
70
|
Returns:
|
71
71
|
Dict[str, Any]: Dictionary containing depletion and enrichment p-values.
|
@@ -80,22 +80,22 @@ def compute_chi2_test(
|
|
80
80
|
# Case 1: Use all nodes as the background
|
81
81
|
background_population = total_node_count
|
82
82
|
neighborhood_sums = neighborhoods.sum(axis=0) # Column sums of neighborhoods
|
83
|
-
annotation_sums =
|
84
|
-
elif null_distribution == "
|
83
|
+
annotation_sums = annotation.sum(axis=0) # Column sums of annotations
|
84
|
+
elif null_distribution == "annotation":
|
85
85
|
# Case 2: Only consider nodes with at least one annotation
|
86
86
|
annotated_nodes = (
|
87
|
-
np.ravel(
|
87
|
+
np.ravel(annotation.sum(axis=1)) > 0
|
88
88
|
) # Row-wise sum to filter nodes with annotations
|
89
89
|
background_population = annotated_nodes.sum() # Total number of annotated nodes
|
90
90
|
neighborhood_sums = neighborhoods[annotated_nodes].sum(
|
91
91
|
axis=0
|
92
92
|
) # Neighborhood sums for annotated nodes
|
93
|
-
annotation_sums =
|
93
|
+
annotation_sums = annotation[annotated_nodes].sum(
|
94
94
|
axis=0
|
95
95
|
) # Annotation sums for annotated nodes
|
96
96
|
else:
|
97
97
|
raise ValueError(
|
98
|
-
"Invalid null_distribution value. Choose either 'network' or '
|
98
|
+
"Invalid null_distribution value. Choose either 'network' or 'annotation'."
|
99
99
|
)
|
100
100
|
|
101
101
|
# Convert to dense arrays for downstream computations
|
@@ -103,7 +103,7 @@ def compute_chi2_test(
|
|
103
103
|
annotation_sums = np.asarray(annotation_sums).reshape(1, -1) # Ensure row vector shape
|
104
104
|
|
105
105
|
# Observed values: number of annotated nodes in each neighborhood
|
106
|
-
observed = neighborhoods.T @
|
106
|
+
observed = neighborhoods.T @ annotation # Shape: (neighborhoods, annotation)
|
107
107
|
# Expected values under the null
|
108
108
|
expected = (neighborhood_sums @ annotation_sums) / background_population
|
109
109
|
# Chi-squared statistic: sum((observed - expected)^2 / expected)
|
@@ -119,15 +119,15 @@ def compute_chi2_test(
|
|
119
119
|
|
120
120
|
def compute_hypergeom_test(
|
121
121
|
neighborhoods: csr_matrix,
|
122
|
-
|
122
|
+
annotation: csr_matrix,
|
123
123
|
null_distribution: str = "network",
|
124
124
|
) -> Dict[str, Any]:
|
125
125
|
"""Compute hypergeometric test for enrichment and depletion in neighborhoods with selectable null distribution.
|
126
126
|
|
127
127
|
Args:
|
128
128
|
neighborhoods (csr_matrix): Sparse binary matrix representing neighborhoods.
|
129
|
-
|
130
|
-
null_distribution (str, optional): Type of null distribution ('network' or '
|
129
|
+
annotation (csr_matrix): Sparse binary matrix representing annotation.
|
130
|
+
null_distribution (str, optional): Type of null distribution ('network' or 'annotation'). Defaults to "network".
|
131
131
|
|
132
132
|
Returns:
|
133
133
|
Dict[str, Any]: Dictionary containing depletion and enrichment p-values.
|
@@ -140,22 +140,22 @@ def compute_hypergeom_test(
|
|
140
140
|
|
141
141
|
# Compute sums
|
142
142
|
neighborhood_sums = neighborhoods.sum(axis=0).A.flatten() # Convert to dense array
|
143
|
-
annotation_sums =
|
143
|
+
annotation_sums = annotation.sum(axis=0).A.flatten() # Convert to dense array
|
144
144
|
|
145
145
|
if null_distribution == "network":
|
146
146
|
background_population = total_nodes
|
147
|
-
elif null_distribution == "
|
148
|
-
annotated_nodes =
|
147
|
+
elif null_distribution == "annotation":
|
148
|
+
annotated_nodes = annotation.sum(axis=1).A.flatten() > 0 # Boolean mask
|
149
149
|
background_population = annotated_nodes.sum()
|
150
150
|
neighborhood_sums = neighborhoods[annotated_nodes].sum(axis=0).A.flatten()
|
151
|
-
annotation_sums =
|
151
|
+
annotation_sums = annotation[annotated_nodes].sum(axis=0).A.flatten()
|
152
152
|
else:
|
153
153
|
raise ValueError(
|
154
|
-
"Invalid null_distribution value. Choose either 'network' or '
|
154
|
+
"Invalid null_distribution value. Choose either 'network' or 'annotation'."
|
155
155
|
)
|
156
156
|
|
157
157
|
# Observed counts
|
158
|
-
annotated_in_neighborhood = neighborhoods.T @
|
158
|
+
annotated_in_neighborhood = neighborhoods.T @ annotation # Sparse result
|
159
159
|
annotated_in_neighborhood = annotated_in_neighborhood.toarray() # Convert to dense
|
160
160
|
# Align shapes for broadcasting
|
161
161
|
neighborhood_sums = neighborhood_sums.reshape(-1, 1)
|
@@ -175,15 +175,15 @@ def compute_hypergeom_test(
|
|
175
175
|
|
176
176
|
def compute_poisson_test(
|
177
177
|
neighborhoods: csr_matrix,
|
178
|
-
|
178
|
+
annotation: csr_matrix,
|
179
179
|
null_distribution: str = "network",
|
180
180
|
) -> Dict[str, Any]:
|
181
181
|
"""Compute Poisson test for enrichment and depletion in neighborhoods with selectable null distribution.
|
182
182
|
|
183
183
|
Args:
|
184
184
|
neighborhoods (csr_matrix): Sparse binary matrix representing neighborhoods.
|
185
|
-
|
186
|
-
null_distribution (str, optional): Type of null distribution ('network' or '
|
185
|
+
annotation (csr_matrix): Sparse binary matrix representing annotation.
|
186
|
+
null_distribution (str, optional): Type of null distribution ('network' or 'annotation'). Defaults to "network".
|
187
187
|
|
188
188
|
Returns:
|
189
189
|
Dict[str, Any]: Dictionary containing depletion and enrichment p-values.
|
@@ -192,7 +192,7 @@ def compute_poisson_test(
|
|
192
192
|
ValueError: If an invalid null_distribution value is provided.
|
193
193
|
"""
|
194
194
|
# Matrix multiplication to get the number of annotated nodes in each neighborhood
|
195
|
-
annotated_in_neighborhood = neighborhoods @
|
195
|
+
annotated_in_neighborhood = neighborhoods @ annotation # Sparse result
|
196
196
|
# Convert annotated counts to dense for downstream calculations
|
197
197
|
annotated_in_neighborhood_dense = annotated_in_neighborhood.toarray()
|
198
198
|
|
@@ -200,12 +200,12 @@ def compute_poisson_test(
|
|
200
200
|
if null_distribution == "network":
|
201
201
|
# Use the mean across neighborhoods (axis=1)
|
202
202
|
lambda_expected = np.mean(annotated_in_neighborhood_dense, axis=1, keepdims=True)
|
203
|
-
elif null_distribution == "
|
203
|
+
elif null_distribution == "annotation":
|
204
204
|
# Use the mean across annotations (axis=0)
|
205
205
|
lambda_expected = np.mean(annotated_in_neighborhood_dense, axis=0, keepdims=True)
|
206
206
|
else:
|
207
207
|
raise ValueError(
|
208
|
-
"Invalid null_distribution value. Choose either 'network' or '
|
208
|
+
"Invalid null_distribution value. Choose either 'network' or 'annotation'."
|
209
209
|
)
|
210
210
|
|
211
211
|
# Compute p-values for enrichment and depletion using Poisson distribution
|
@@ -217,15 +217,15 @@ def compute_poisson_test(
|
|
217
217
|
|
218
218
|
def compute_zscore_test(
|
219
219
|
neighborhoods: csr_matrix,
|
220
|
-
|
220
|
+
annotation: csr_matrix,
|
221
221
|
null_distribution: str = "network",
|
222
222
|
) -> Dict[str, Any]:
|
223
223
|
"""Compute z-score test for enrichment and depletion in neighborhoods with selectable null distribution.
|
224
224
|
|
225
225
|
Args:
|
226
226
|
neighborhoods (csr_matrix): Sparse binary matrix representing neighborhoods.
|
227
|
-
|
228
|
-
null_distribution (str, optional): Type of null distribution ('network' or '
|
227
|
+
annotation (csr_matrix): Sparse binary matrix representing annotation.
|
228
|
+
null_distribution (str, optional): Type of null distribution ('network' or 'annotation'). Defaults to "network".
|
229
229
|
|
230
230
|
Returns:
|
231
231
|
Dict[str, Any]: Dictionary containing depletion and enrichment p-values.
|
@@ -240,19 +240,19 @@ def compute_zscore_test(
|
|
240
240
|
if null_distribution == "network":
|
241
241
|
background_population = total_node_count
|
242
242
|
neighborhood_sums = neighborhoods.sum(axis=0).A.flatten() # Dense column sums
|
243
|
-
annotation_sums =
|
244
|
-
elif null_distribution == "
|
245
|
-
annotated_nodes =
|
243
|
+
annotation_sums = annotation.sum(axis=0).A.flatten() # Dense row sums
|
244
|
+
elif null_distribution == "annotation":
|
245
|
+
annotated_nodes = annotation.sum(axis=1).A.flatten() > 0 # Dense boolean mask
|
246
246
|
background_population = annotated_nodes.sum()
|
247
247
|
neighborhood_sums = neighborhoods[annotated_nodes].sum(axis=0).A.flatten()
|
248
|
-
annotation_sums =
|
248
|
+
annotation_sums = annotation[annotated_nodes].sum(axis=0).A.flatten()
|
249
249
|
else:
|
250
250
|
raise ValueError(
|
251
|
-
"Invalid null_distribution value. Choose either 'network' or '
|
251
|
+
"Invalid null_distribution value. Choose either 'network' or 'annotation'."
|
252
252
|
)
|
253
253
|
|
254
254
|
# Observed values
|
255
|
-
observed = (neighborhoods.T @
|
255
|
+
observed = (neighborhoods.T @ annotation).toarray() # Convert sparse result to dense
|
256
256
|
# Expected values under the null
|
257
257
|
neighborhood_sums = neighborhood_sums.reshape(-1, 1) # Ensure correct shape
|
258
258
|
annotation_sums = annotation_sums.reshape(1, -1) # Ensure correct shape
|
risk/network/graph/api.py
CHANGED
@@ -9,7 +9,7 @@ from typing import Any, Dict, Union
|
|
9
9
|
import networkx as nx
|
10
10
|
import pandas as pd
|
11
11
|
|
12
|
-
from risk.
|
12
|
+
from risk.annotation import define_top_annotation
|
13
13
|
from risk.log import log_header, logger, params
|
14
14
|
from risk.neighborhoods import (
|
15
15
|
define_domains,
|
@@ -26,13 +26,13 @@ class GraphAPI:
|
|
26
26
|
The GraphAPI class provides methods to load and process network graphs, annotations, and neighborhoods.
|
27
27
|
"""
|
28
28
|
|
29
|
-
def __init__() -> None:
|
29
|
+
def __init__(self) -> None:
|
30
30
|
pass
|
31
31
|
|
32
32
|
def load_graph(
|
33
33
|
self,
|
34
34
|
network: nx.Graph,
|
35
|
-
|
35
|
+
annotation: Dict[str, Any],
|
36
36
|
neighborhoods: Dict[str, Any],
|
37
37
|
tail: str = "right",
|
38
38
|
pval_cutoff: float = 0.01,
|
@@ -50,7 +50,7 @@ class GraphAPI:
|
|
50
50
|
|
51
51
|
Args:
|
52
52
|
network (nx.Graph): The network graph.
|
53
|
-
|
53
|
+
annotation (Dict[str, Any]): The annotation associated with the network.
|
54
54
|
neighborhoods (Dict[str, Any]): Neighborhood significance data.
|
55
55
|
tail (str, optional): Type of significance tail ("right", "left", "both"). Defaults to "right".
|
56
56
|
pval_cutoff (float, optional): p-value cutoff for significance. Defaults to 0.01.
|
@@ -115,9 +115,9 @@ class GraphAPI:
|
|
115
115
|
logger.debug(f"Min cluster size: {min_cluster_size}")
|
116
116
|
logger.debug(f"Max cluster size: {max_cluster_size}")
|
117
117
|
# Define top annotations based on processed neighborhoods
|
118
|
-
|
118
|
+
top_annotation = self._define_top_annotation(
|
119
119
|
network=network,
|
120
|
-
|
120
|
+
annotation=annotation,
|
121
121
|
neighborhoods=processed_neighborhoods,
|
122
122
|
min_cluster_size=min_cluster_size,
|
123
123
|
max_cluster_size=max_cluster_size,
|
@@ -130,7 +130,7 @@ class GraphAPI:
|
|
130
130
|
]
|
131
131
|
# Define domains in the network using the specified clustering settings
|
132
132
|
domains = define_domains(
|
133
|
-
|
133
|
+
top_annotation=top_annotation,
|
134
134
|
significant_neighborhoods_significance=significant_neighborhoods_significance,
|
135
135
|
linkage_criterion=linkage_criterion,
|
136
136
|
linkage_method=linkage_method,
|
@@ -140,20 +140,20 @@ class GraphAPI:
|
|
140
140
|
# Trim domains and top annotations based on cluster size constraints
|
141
141
|
domains, trimmed_domains = trim_domains(
|
142
142
|
domains=domains,
|
143
|
-
|
143
|
+
top_annotation=top_annotation,
|
144
144
|
min_cluster_size=min_cluster_size,
|
145
145
|
max_cluster_size=max_cluster_size,
|
146
146
|
)
|
147
147
|
|
148
148
|
# Prepare node mapping and significance sums for the final Graph object
|
149
|
-
ordered_nodes =
|
149
|
+
ordered_nodes = annotation["ordered_nodes"]
|
150
150
|
node_label_to_id = dict(zip(ordered_nodes, range(len(ordered_nodes))))
|
151
151
|
node_significance_sums = processed_neighborhoods["node_significance_sums"]
|
152
152
|
|
153
153
|
# Return the fully initialized Graph object
|
154
154
|
return Graph(
|
155
155
|
network=network,
|
156
|
-
|
156
|
+
annotation=annotation,
|
157
157
|
neighborhoods=neighborhoods,
|
158
158
|
domains=domains,
|
159
159
|
trimmed_domains=trimmed_domains,
|
@@ -161,10 +161,10 @@ class GraphAPI:
|
|
161
161
|
node_significance_sums=node_significance_sums,
|
162
162
|
)
|
163
163
|
|
164
|
-
def
|
164
|
+
def _define_top_annotation(
|
165
165
|
self,
|
166
166
|
network: nx.Graph,
|
167
|
-
|
167
|
+
annotation: Dict[str, Any],
|
168
168
|
neighborhoods: Dict[str, Any],
|
169
169
|
min_cluster_size: int = 5,
|
170
170
|
max_cluster_size: int = 1000,
|
@@ -173,7 +173,7 @@ class GraphAPI:
|
|
173
173
|
|
174
174
|
Args:
|
175
175
|
network (nx.Graph): The network graph.
|
176
|
-
|
176
|
+
annotation (Dict[str, Any]): Annotation data for the network.
|
177
177
|
neighborhoods (Dict[str, Any]): Neighborhood significance data.
|
178
178
|
min_cluster_size (int, optional): Minimum size for clusters. Defaults to 5.
|
179
179
|
max_cluster_size (int, optional): Maximum size for clusters. Defaults to 1000.
|
@@ -181,17 +181,17 @@ class GraphAPI:
|
|
181
181
|
Returns:
|
182
182
|
Dict[str, Any]: Top annotations identified within the network.
|
183
183
|
"""
|
184
|
-
# Extract necessary data from
|
185
|
-
|
184
|
+
# Extract necessary data from annotation and neighborhoods
|
185
|
+
ordered_annotation = annotation["ordered_annotation"]
|
186
186
|
neighborhood_significance_sums = neighborhoods["neighborhood_significance_counts"]
|
187
187
|
significant_significance_matrix = neighborhoods["significant_significance_matrix"]
|
188
188
|
significant_binary_significance_matrix = neighborhoods[
|
189
189
|
"significant_binary_significance_matrix"
|
190
190
|
]
|
191
191
|
# Call external function to define top annotations
|
192
|
-
return
|
192
|
+
return define_top_annotation(
|
193
193
|
network=network,
|
194
|
-
ordered_annotation_labels=
|
194
|
+
ordered_annotation_labels=ordered_annotation,
|
195
195
|
neighborhood_significance_sums=neighborhood_significance_sums,
|
196
196
|
significant_significance_matrix=significant_significance_matrix,
|
197
197
|
significant_binary_significance_matrix=significant_binary_significance_matrix,
|
risk/network/graph/graph.py
CHANGED
@@ -17,7 +17,7 @@ class Graph:
|
|
17
17
|
"""A class to represent a network graph and process its nodes and edges.
|
18
18
|
|
19
19
|
The Graph class provides functionality to handle and manipulate a network graph,
|
20
|
-
including managing domains,
|
20
|
+
including managing domains, annotation, and node significance data. It also includes methods
|
21
21
|
for transforming and mapping graph coordinates, as well as generating colors based on node
|
22
22
|
significance.
|
23
23
|
"""
|
@@ -25,7 +25,7 @@ class Graph:
|
|
25
25
|
def __init__(
|
26
26
|
self,
|
27
27
|
network: nx.Graph,
|
28
|
-
|
28
|
+
annotation: Dict[str, Any],
|
29
29
|
neighborhoods: Dict[str, Any],
|
30
30
|
domains: pd.DataFrame,
|
31
31
|
trimmed_domains: pd.DataFrame,
|
@@ -36,7 +36,7 @@ class Graph:
|
|
36
36
|
|
37
37
|
Args:
|
38
38
|
network (nx.Graph): The network graph.
|
39
|
-
|
39
|
+
annotation (Dict[str, Any]): The annotation associated with the network.
|
40
40
|
neighborhoods (Dict[str, Any]): Neighborhood significance data.
|
41
41
|
domains (pd.DataFrame): DataFrame containing domain data for the network nodes.
|
42
42
|
trimmed_domains (pd.DataFrame): DataFrame containing trimmed domain data for the network nodes.
|
@@ -69,16 +69,20 @@ class Graph:
|
|
69
69
|
self.node_coordinates = self._extract_node_coordinates(self.network)
|
70
70
|
|
71
71
|
# NOTE: Only after the above attributes are initialized, we can create the summary
|
72
|
-
self.summary = Summary(
|
72
|
+
self.summary = Summary(annotation, neighborhoods, self)
|
73
73
|
|
74
|
-
def pop(self, domain_id:
|
75
|
-
"""Remove domain ID from
|
76
|
-
domain-specific mappings based on a given criterion, as domain attributes are stored and
|
77
|
-
accessed only in dictionaries modified by this method.
|
74
|
+
def pop(self, domain_id: int) -> List[str]:
|
75
|
+
"""Remove a domain ID from the graph and return the corresponding node labels.
|
78
76
|
|
79
77
|
Args:
|
80
|
-
key (
|
78
|
+
key (int): The domain ID key to be removed from each mapping.
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
List[str]: A list of node labels associated with the domain ID.
|
81
82
|
"""
|
83
|
+
# Get the node labels associated with the domain ID
|
84
|
+
node_labels = self.domain_id_to_node_labels_map.get(domain_id, [])
|
85
|
+
|
82
86
|
# Define the domain mappings to be updated
|
83
87
|
domain_mappings = [
|
84
88
|
self.domain_id_to_node_ids_map,
|
@@ -97,6 +101,8 @@ class Graph:
|
|
97
101
|
domain_info["domains"].remove(domain_id)
|
98
102
|
domain_info["significances"].pop(domain_id)
|
99
103
|
|
104
|
+
return node_labels
|
105
|
+
|
100
106
|
def _create_domain_id_to_node_ids_map(self, domains: pd.DataFrame) -> Dict[int, Any]:
|
101
107
|
"""Create a mapping from domains to the list of node IDs belonging to each domain.
|
102
108
|
|
@@ -163,8 +169,8 @@ class Graph:
|
|
163
169
|
sorted_descriptions, sorted_scores = zip(*descriptions_and_scores)
|
164
170
|
# Assign to the domain info map
|
165
171
|
domain_info_map[int(domain_id)] = {
|
166
|
-
"full_descriptions":
|
167
|
-
"significance_scores":
|
172
|
+
"full_descriptions": sorted_descriptions,
|
173
|
+
"significance_scores": sorted_scores,
|
168
174
|
}
|
169
175
|
|
170
176
|
return domain_info_map
|
risk/network/graph/summary.py
CHANGED
@@ -23,18 +23,18 @@ class Summary:
|
|
23
23
|
|
24
24
|
def __init__(
|
25
25
|
self,
|
26
|
-
|
26
|
+
annotation: Dict[str, Any],
|
27
27
|
neighborhoods: Dict[str, Any],
|
28
28
|
graph, # Avoid type hinting Graph to prevent circular imports
|
29
29
|
):
|
30
30
|
"""Initialize the Results object with analysis components.
|
31
31
|
|
32
32
|
Args:
|
33
|
-
|
33
|
+
annotation (Dict[str, Any]): Annotation data, including ordered annotations and matrix of associations.
|
34
34
|
neighborhoods (Dict[str, Any]): Neighborhood data containing p-values for significance and depletion analysis.
|
35
35
|
graph (Graph): Graph object representing domain-to-node and node-to-label mappings.
|
36
36
|
"""
|
37
|
-
self.
|
37
|
+
self.annotation = annotation
|
38
38
|
self.neighborhoods = neighborhoods
|
39
39
|
self.graph = graph
|
40
40
|
|
@@ -81,7 +81,7 @@ class Summary:
|
|
81
81
|
and annotation member information.
|
82
82
|
"""
|
83
83
|
log_header("Loading analysis summary")
|
84
|
-
# Calculate significance and depletion q-values from p-value matrices in
|
84
|
+
# Calculate significance and depletion q-values from p-value matrices in annotation
|
85
85
|
enrichment_pvals = self.neighborhoods["enrichment_pvals"]
|
86
86
|
depletion_pvals = self.neighborhoods["depletion_pvals"]
|
87
87
|
enrichment_qvals = self._calculate_qvalues(enrichment_pvals)
|
@@ -147,10 +147,10 @@ class Summary:
|
|
147
147
|
.reset_index(drop=True)
|
148
148
|
)
|
149
149
|
|
150
|
-
# Convert
|
151
|
-
|
150
|
+
# Convert annotation list to a DataFrame for comparison then merge with results
|
151
|
+
ordered_annotation = pd.DataFrame({"Annotation": self.annotation["ordered_annotation"]})
|
152
152
|
# Merge to ensure all annotations are present, filling missing rows with defaults
|
153
|
-
results = pd.merge(
|
153
|
+
results = pd.merge(ordered_annotation, results, on="Annotation", how="left").fillna(
|
154
154
|
{
|
155
155
|
"Domain ID": -1,
|
156
156
|
"Annotation Members in Network": "",
|
@@ -205,7 +205,7 @@ class Summary:
|
|
205
205
|
Minimum significance p-value, significance q-value, depletion p-value, depletion q-value.
|
206
206
|
"""
|
207
207
|
try:
|
208
|
-
annotation_idx = self.
|
208
|
+
annotation_idx = self.annotation["ordered_annotation"].index(description)
|
209
209
|
except ValueError:
|
210
210
|
return None, None, None, None # Description not found
|
211
211
|
|
@@ -235,12 +235,12 @@ class Summary:
|
|
235
235
|
str: ';'-separated string of node labels that are associated with the annotation.
|
236
236
|
"""
|
237
237
|
try:
|
238
|
-
annotation_idx = self.
|
238
|
+
annotation_idx = self.annotation["ordered_annotation"].index(description)
|
239
239
|
except ValueError:
|
240
240
|
return "" # Description not found
|
241
241
|
|
242
242
|
# Get the column (safely) from the sparse matrix
|
243
|
-
column = self.
|
243
|
+
column = self.annotation["matrix"][:, annotation_idx]
|
244
244
|
# Convert the column to a dense array if needed
|
245
245
|
column = column.toarray().ravel() # Convert to a 1D dense array
|
246
246
|
# Get nodes present for the annotation and sort by node label - use np.where on the dense array
|
risk/network/io.py
CHANGED
@@ -48,7 +48,7 @@ class NetworkIO:
|
|
48
48
|
min_edges_per_node=min_edges_per_node,
|
49
49
|
)
|
50
50
|
|
51
|
-
def
|
51
|
+
def load_network_gpickle(
|
52
52
|
self,
|
53
53
|
filepath: str,
|
54
54
|
compute_sphere: bool = True,
|
@@ -71,9 +71,9 @@ class NetworkIO:
|
|
71
71
|
surface_depth=surface_depth,
|
72
72
|
min_edges_per_node=min_edges_per_node,
|
73
73
|
)
|
74
|
-
return networkio.
|
74
|
+
return networkio._load_network_gpickle(filepath=filepath)
|
75
75
|
|
76
|
-
def
|
76
|
+
def _load_network_gpickle(self, filepath: str) -> nx.Graph:
|
77
77
|
"""Private method to load a network from a GPickle file.
|
78
78
|
|
79
79
|
Args:
|
@@ -93,7 +93,7 @@ class NetworkIO:
|
|
93
93
|
# Initialize the graph
|
94
94
|
return self._initialize_graph(G)
|
95
95
|
|
96
|
-
def
|
96
|
+
def load_network_networkx(
|
97
97
|
self,
|
98
98
|
network: nx.Graph,
|
99
99
|
compute_sphere: bool = True,
|
@@ -116,9 +116,9 @@ class NetworkIO:
|
|
116
116
|
surface_depth=surface_depth,
|
117
117
|
min_edges_per_node=min_edges_per_node,
|
118
118
|
)
|
119
|
-
return networkio.
|
119
|
+
return networkio._load_network_networkx(network=network)
|
120
120
|
|
121
|
-
def
|
121
|
+
def _load_network_networkx(self, network: nx.Graph) -> nx.Graph:
|
122
122
|
"""Private method to load a NetworkX graph.
|
123
123
|
|
124
124
|
Args:
|
@@ -137,7 +137,7 @@ class NetworkIO:
|
|
137
137
|
# Initialize the graph
|
138
138
|
return self._initialize_graph(network_copy)
|
139
139
|
|
140
|
-
def
|
140
|
+
def load_network_cytoscape(
|
141
141
|
self,
|
142
142
|
filepath: str,
|
143
143
|
source_label: str = "source",
|
@@ -166,14 +166,14 @@ class NetworkIO:
|
|
166
166
|
surface_depth=surface_depth,
|
167
167
|
min_edges_per_node=min_edges_per_node,
|
168
168
|
)
|
169
|
-
return networkio.
|
169
|
+
return networkio._load_network_cytoscape(
|
170
170
|
filepath=filepath,
|
171
171
|
source_label=source_label,
|
172
172
|
target_label=target_label,
|
173
173
|
view_name=view_name,
|
174
174
|
)
|
175
175
|
|
176
|
-
def
|
176
|
+
def _load_network_cytoscape(
|
177
177
|
self,
|
178
178
|
filepath: str,
|
179
179
|
source_label: str = "source",
|
@@ -307,7 +307,7 @@ class NetworkIO:
|
|
307
307
|
if os.path.exists(tmp_dir):
|
308
308
|
shutil.rmtree(tmp_dir)
|
309
309
|
|
310
|
-
def
|
310
|
+
def load_network_cyjs(
|
311
311
|
self,
|
312
312
|
filepath: str,
|
313
313
|
source_label: str = "source",
|
@@ -334,13 +334,13 @@ class NetworkIO:
|
|
334
334
|
surface_depth=surface_depth,
|
335
335
|
min_edges_per_node=min_edges_per_node,
|
336
336
|
)
|
337
|
-
return networkio.
|
337
|
+
return networkio._load_network_cyjs(
|
338
338
|
filepath=filepath,
|
339
339
|
source_label=source_label,
|
340
340
|
target_label=target_label,
|
341
341
|
)
|
342
342
|
|
343
|
-
def
|
343
|
+
def _load_network_cyjs(self, filepath, source_label="source", target_label="target"):
|
344
344
|
"""Private method to load a network from a Cytoscape JSON (.cyjs) file.
|
345
345
|
|
346
346
|
Args:
|
risk/network/plotter/canvas.py
CHANGED
@@ -76,7 +76,7 @@ class Canvas:
|
|
76
76
|
fig = self.ax.figure
|
77
77
|
# Use a tight layout to ensure that title and subtitle do not overlap with the original plot
|
78
78
|
fig.tight_layout(
|
79
|
-
rect=
|
79
|
+
rect=(0, 0, 1, 1 - title_space_offset)
|
80
80
|
) # Leave space above the plot for title
|
81
81
|
|
82
82
|
# Plot title if provided
|
risk/network/plotter/contour.py
CHANGED
@@ -282,8 +282,8 @@ class Contour:
|
|
282
282
|
scale_factor: float = 1.0,
|
283
283
|
ids_to_colors: Union[Dict[int, Any], None] = None,
|
284
284
|
random_seed: int = 888,
|
285
|
-
) ->
|
286
|
-
"""Get colors for the contours based on node
|
285
|
+
) -> List[Tuple]:
|
286
|
+
"""Get colors for the contours based on node annotation or a specified colormap.
|
287
287
|
|
288
288
|
Args:
|
289
289
|
cmap (str, optional): Name of the colormap to use for generating contour colors. Defaults to "gist_rainbow".
|
@@ -301,7 +301,7 @@ class Contour:
|
|
301
301
|
random_seed (int, optional): Seed for random number generation to ensure reproducibility. Defaults to 888.
|
302
302
|
|
303
303
|
Returns:
|
304
|
-
|
304
|
+
List[Tuple]: List of RGBA colors for the contours, one for each domain in the network graph.
|
305
305
|
"""
|
306
306
|
return get_annotated_domain_colors(
|
307
307
|
graph=self.graph,
|