risk-network 0.0.3b4__py3-none-any.whl → 0.0.4b1__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/annotations.py +3 -1
- risk/annotations/io.py +1 -1
- risk/neighborhoods/neighborhoods.py +10 -1
- risk/network/graph.py +4 -4
- risk/network/io.py +189 -23
- risk/network/plot.py +142 -56
- risk/risk.py +22 -62
- risk/stats/stats.py +2 -2
- {risk_network-0.0.3b4.dist-info → risk_network-0.0.4b1.dist-info}/METADATA +5 -5
- risk_network-0.0.4b1.dist-info/RECORD +26 -0
- {risk_network-0.0.3b4.dist-info → risk_network-0.0.4b1.dist-info}/WHEEL +1 -1
- risk_network-0.0.3b4.dist-info/RECORD +0 -26
- {risk_network-0.0.3b4.dist-info → risk_network-0.0.4b1.dist-info}/LICENSE +0 -0
- {risk_network-0.0.3b4.dist-info → risk_network-0.0.4b1.dist-info}/top_level.txt +0 -0
risk/__init__.py
CHANGED
risk/annotations/annotations.py
CHANGED
@@ -171,7 +171,9 @@ def get_description(words_column: pd.Series) -> str:
|
|
171
171
|
stop_words = set(stopwords.words("english"))
|
172
172
|
# Tokenize the concatenated string and filter out stopwords and non-alphabetic words
|
173
173
|
words = [
|
174
|
-
|
174
|
+
(
|
175
|
+
word.lower() if word.istitle() else word
|
176
|
+
) # Lowercase all words except proper nouns (e.g., RNA, mRNA)
|
175
177
|
for word in word_tokenize(words_column.str.cat(sep=" "))
|
176
178
|
if word.isalpha() and word.lower() not in stop_words
|
177
179
|
]
|
risk/annotations/io.py
CHANGED
@@ -25,7 +25,7 @@ class AnnotationsIO:
|
|
25
25
|
def __init__(self):
|
26
26
|
pass
|
27
27
|
|
28
|
-
def
|
28
|
+
def load_json_annotation(self, filepath: str, network: nx.Graph) -> Dict[str, Any]:
|
29
29
|
"""Load annotations from a JSON file and convert them to a DataFrame.
|
30
30
|
|
31
31
|
Args:
|
@@ -170,7 +170,16 @@ def _impute_neighbors(
|
|
170
170
|
# Calculate shortest distances for each node to determine the distance threshold
|
171
171
|
shortest_distances = []
|
172
172
|
for node in network.nodes():
|
173
|
-
|
173
|
+
try:
|
174
|
+
neighbors = [
|
175
|
+
n for n in network.neighbors(node) if binary_enrichment_matrix[n].sum() != 0
|
176
|
+
]
|
177
|
+
except IndexError as e:
|
178
|
+
raise IndexError(
|
179
|
+
f"Failed to find neighbors for node '{node}': Ensure that the node exists in the network and that the binary enrichment matrix is correctly indexed."
|
180
|
+
) from e
|
181
|
+
|
182
|
+
# Calculate the shortest distance to a neighbor
|
174
183
|
if neighbors:
|
175
184
|
shortest_distance = min([_get_euclidean_distance(node, n, network) for n in neighbors])
|
176
185
|
shortest_distances.append(shortest_distance)
|
risk/network/graph.py
CHANGED
@@ -49,8 +49,8 @@ class NetworkGraph:
|
|
49
49
|
self.trimmed_domains = trimmed_domains
|
50
50
|
self.node_label_to_id_map = node_label_to_id_map
|
51
51
|
self.node_enrichment_sums = node_enrichment_sums
|
52
|
-
# NOTE: self.
|
53
|
-
self.
|
52
|
+
# NOTE: self.network and self.node_coordinates are declared in _initialize_network
|
53
|
+
self.network = None
|
54
54
|
self.node_coordinates = None
|
55
55
|
self._initialize_network(network)
|
56
56
|
|
@@ -95,8 +95,8 @@ class NetworkGraph:
|
|
95
95
|
"""
|
96
96
|
# Unfold the network's 3D coordinates to 2D
|
97
97
|
G_2d = _unfold_sphere_to_plane(G)
|
98
|
-
# Assign the unfolded graph to self.
|
99
|
-
self.
|
98
|
+
# Assign the unfolded graph to self.network
|
99
|
+
self.network = G_2d
|
100
100
|
# Extract 2D coordinates of nodes
|
101
101
|
self.node_coordinates = _extract_node_coordinates(G_2d)
|
102
102
|
|
risk/network/io.py
CHANGED
@@ -29,25 +29,67 @@ class NetworkIO:
|
|
29
29
|
self,
|
30
30
|
compute_sphere: bool = True,
|
31
31
|
surface_depth: float = 0.0,
|
32
|
-
distance_metric: str = "dijkstra",
|
33
|
-
edge_length_threshold: float = 0.5,
|
34
|
-
louvain_resolution: float = 0.1,
|
35
32
|
min_edges_per_node: int = 0,
|
36
33
|
include_edge_weight: bool = True,
|
37
34
|
weight_label: str = "weight",
|
38
35
|
):
|
36
|
+
"""Initialize the NetworkIO class.
|
37
|
+
|
38
|
+
Args:
|
39
|
+
compute_sphere (bool, optional): Whether to map nodes to a sphere. Defaults to True.
|
40
|
+
surface_depth (float, optional): Surface depth for the sphere. Defaults to 0.0.
|
41
|
+
min_edges_per_node (int, optional): Minimum number of edges per node. Defaults to 0.
|
42
|
+
include_edge_weight (bool, optional): Whether to include edge weights in calculations. Defaults to True.
|
43
|
+
weight_label (str, optional): Label for edge weights. Defaults to "weight".
|
44
|
+
"""
|
39
45
|
self.compute_sphere = compute_sphere
|
40
46
|
self.surface_depth = surface_depth
|
47
|
+
self.min_edges_per_node = min_edges_per_node
|
41
48
|
self.include_edge_weight = include_edge_weight
|
42
49
|
self.weight_label = weight_label
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
50
|
+
params.log_network(
|
51
|
+
compute_sphere=compute_sphere,
|
52
|
+
surface_depth=surface_depth,
|
53
|
+
min_edges_per_node=min_edges_per_node,
|
54
|
+
include_edge_weight=include_edge_weight,
|
55
|
+
weight_label=weight_label,
|
56
|
+
)
|
47
57
|
|
48
|
-
|
58
|
+
@classmethod
|
59
|
+
def load_gpickle_network(
|
60
|
+
cls,
|
61
|
+
filepath: str,
|
62
|
+
compute_sphere: bool = True,
|
63
|
+
surface_depth: float = 0.0,
|
64
|
+
min_edges_per_node: int = 0,
|
65
|
+
include_edge_weight: bool = True,
|
66
|
+
weight_label: str = "weight",
|
67
|
+
) -> nx.Graph:
|
49
68
|
"""Load a network from a GPickle file.
|
50
69
|
|
70
|
+
Args:
|
71
|
+
filepath (str): Path to the GPickle file.
|
72
|
+
compute_sphere (bool, optional): Whether to map nodes to a sphere. Defaults to True.
|
73
|
+
surface_depth (float, optional): Surface depth for the sphere. Defaults to 0.0.
|
74
|
+
min_edges_per_node (int, optional): Minimum number of edges per node. Defaults to 0.
|
75
|
+
include_edge_weight (bool, optional): Whether to include edge weights in calculations. Defaults to True.
|
76
|
+
weight_label (str, optional): Label for edge weights. Defaults to "weight".
|
77
|
+
|
78
|
+
Returns:
|
79
|
+
nx.Graph: Loaded and processed network.
|
80
|
+
"""
|
81
|
+
networkio = cls(
|
82
|
+
compute_sphere=compute_sphere,
|
83
|
+
surface_depth=surface_depth,
|
84
|
+
min_edges_per_node=min_edges_per_node,
|
85
|
+
include_edge_weight=include_edge_weight,
|
86
|
+
weight_label=weight_label,
|
87
|
+
)
|
88
|
+
return networkio._load_gpickle_network(filepath=filepath)
|
89
|
+
|
90
|
+
def _load_gpickle_network(self, filepath: str) -> nx.Graph:
|
91
|
+
"""Private method to load a network from a GPickle file.
|
92
|
+
|
51
93
|
Args:
|
52
94
|
filepath (str): Path to the GPickle file.
|
53
95
|
|
@@ -62,11 +104,43 @@ class NetworkIO:
|
|
62
104
|
|
63
105
|
return self._initialize_graph(G)
|
64
106
|
|
65
|
-
|
107
|
+
@classmethod
|
108
|
+
def load_networkx_network(
|
109
|
+
cls,
|
110
|
+
network: nx.Graph,
|
111
|
+
compute_sphere: bool = True,
|
112
|
+
surface_depth: float = 0.0,
|
113
|
+
min_edges_per_node: int = 0,
|
114
|
+
include_edge_weight: bool = True,
|
115
|
+
weight_label: str = "weight",
|
116
|
+
) -> nx.Graph:
|
66
117
|
"""Load a NetworkX graph.
|
67
118
|
|
68
119
|
Args:
|
69
|
-
|
120
|
+
network (nx.Graph): A NetworkX graph object.
|
121
|
+
compute_sphere (bool, optional): Whether to map nodes to a sphere. Defaults to True.
|
122
|
+
surface_depth (float, optional): Surface depth for the sphere. Defaults to 0.0.
|
123
|
+
min_edges_per_node (int, optional): Minimum number of edges per node. Defaults to 0.
|
124
|
+
include_edge_weight (bool, optional): Whether to include edge weights in calculations. Defaults to True.
|
125
|
+
weight_label (str, optional): Label for edge weights. Defaults to "weight".
|
126
|
+
|
127
|
+
Returns:
|
128
|
+
nx.Graph: Loaded and processed network.
|
129
|
+
"""
|
130
|
+
networkio = cls(
|
131
|
+
compute_sphere=compute_sphere,
|
132
|
+
surface_depth=surface_depth,
|
133
|
+
min_edges_per_node=min_edges_per_node,
|
134
|
+
include_edge_weight=include_edge_weight,
|
135
|
+
weight_label=weight_label,
|
136
|
+
)
|
137
|
+
return networkio._load_networkx_network(network=network)
|
138
|
+
|
139
|
+
def _load_networkx_network(self, network: nx.Graph) -> nx.Graph:
|
140
|
+
"""Private method to load a NetworkX graph.
|
141
|
+
|
142
|
+
Args:
|
143
|
+
network (nx.Graph): A NetworkX graph object.
|
70
144
|
|
71
145
|
Returns:
|
72
146
|
nx.Graph: Processed network.
|
@@ -74,17 +148,60 @@ class NetworkIO:
|
|
74
148
|
filetype = "NetworkX"
|
75
149
|
params.log_network(filetype=filetype)
|
76
150
|
self._log_loading(filetype)
|
77
|
-
return self._initialize_graph(
|
151
|
+
return self._initialize_graph(network)
|
78
152
|
|
153
|
+
@classmethod
|
79
154
|
def load_cytoscape_network(
|
80
|
-
|
155
|
+
cls,
|
81
156
|
filepath: str,
|
82
157
|
source_label: str = "source",
|
83
158
|
target_label: str = "target",
|
159
|
+
compute_sphere: bool = True,
|
160
|
+
surface_depth: float = 0.0,
|
161
|
+
min_edges_per_node: int = 0,
|
162
|
+
include_edge_weight: bool = True,
|
163
|
+
weight_label: str = "weight",
|
84
164
|
view_name: str = "",
|
85
165
|
) -> nx.Graph:
|
86
166
|
"""Load a network from a Cytoscape file.
|
87
167
|
|
168
|
+
Args:
|
169
|
+
filepath (str): Path to the Cytoscape file.
|
170
|
+
source_label (str, optional): Source node label. Defaults to "source".
|
171
|
+
target_label (str, optional): Target node label. Defaults to "target".
|
172
|
+
view_name (str, optional): Specific view name to load. Defaults to None.
|
173
|
+
compute_sphere (bool, optional): Whether to map nodes to a sphere. Defaults to True.
|
174
|
+
surface_depth (float, optional): Surface depth for the sphere. Defaults to 0.0.
|
175
|
+
min_edges_per_node (int, optional): Minimum number of edges per node. Defaults to 0.
|
176
|
+
include_edge_weight (bool, optional): Whether to include edge weights in calculations. Defaults to True.
|
177
|
+
weight_label (str, optional): Label for edge weights. Defaults to "weight".
|
178
|
+
|
179
|
+
Returns:
|
180
|
+
nx.Graph: Loaded and processed network.
|
181
|
+
"""
|
182
|
+
networkio = cls(
|
183
|
+
compute_sphere=compute_sphere,
|
184
|
+
surface_depth=surface_depth,
|
185
|
+
min_edges_per_node=min_edges_per_node,
|
186
|
+
include_edge_weight=include_edge_weight,
|
187
|
+
weight_label=weight_label,
|
188
|
+
)
|
189
|
+
return networkio._load_cytoscape_network(
|
190
|
+
filepath=filepath,
|
191
|
+
source_label=source_label,
|
192
|
+
target_label=target_label,
|
193
|
+
view_name=view_name,
|
194
|
+
)
|
195
|
+
|
196
|
+
def _load_cytoscape_network(
|
197
|
+
self,
|
198
|
+
filepath: str,
|
199
|
+
source_label: str = "source",
|
200
|
+
target_label: str = "target",
|
201
|
+
view_name: str = "",
|
202
|
+
) -> nx.Graph:
|
203
|
+
"""Private method to load a network from a Cytoscape file.
|
204
|
+
|
88
205
|
Args:
|
89
206
|
filepath (str): Path to the Cytoscape file.
|
90
207
|
source_label (str, optional): Source node label. Defaults to "source".
|
@@ -179,9 +296,49 @@ class NetworkIO:
|
|
179
296
|
for dirname in cys_dirnames:
|
180
297
|
shutil.rmtree(dirname)
|
181
298
|
|
182
|
-
|
299
|
+
@classmethod
|
300
|
+
def load_cytoscape_json_network(
|
301
|
+
cls,
|
302
|
+
filepath: str,
|
303
|
+
source_label: str = "source",
|
304
|
+
target_label: str = "target",
|
305
|
+
compute_sphere: bool = True,
|
306
|
+
surface_depth: float = 0.0,
|
307
|
+
min_edges_per_node: int = 0,
|
308
|
+
include_edge_weight: bool = True,
|
309
|
+
weight_label: str = "weight",
|
310
|
+
) -> nx.Graph:
|
183
311
|
"""Load a network from a Cytoscape JSON (.cyjs) file.
|
184
312
|
|
313
|
+
Args:
|
314
|
+
filepath (str): Path to the Cytoscape JSON file.
|
315
|
+
source_label (str, optional): Source node label. Default is "source".
|
316
|
+
target_label (str, optional): Target node label. Default is "target".
|
317
|
+
compute_sphere (bool, optional): Whether to map nodes to a sphere. Defaults to True.
|
318
|
+
surface_depth (float, optional): Surface depth for the sphere. Defaults to 0.0.
|
319
|
+
min_edges_per_node (int, optional): Minimum number of edges per node. Defaults to 0.
|
320
|
+
include_edge_weight (bool, optional): Whether to include edge weights in calculations. Defaults to True.
|
321
|
+
weight_label (str, optional): Label for edge weights. Defaults to "weight".
|
322
|
+
|
323
|
+
Returns:
|
324
|
+
NetworkX graph: Loaded and processed network.
|
325
|
+
"""
|
326
|
+
networkio = cls(
|
327
|
+
compute_sphere=compute_sphere,
|
328
|
+
surface_depth=surface_depth,
|
329
|
+
min_edges_per_node=min_edges_per_node,
|
330
|
+
include_edge_weight=include_edge_weight,
|
331
|
+
weight_label=weight_label,
|
332
|
+
)
|
333
|
+
return networkio._load_cytoscape_json_network(
|
334
|
+
filepath=filepath,
|
335
|
+
source_label=source_label,
|
336
|
+
target_label=target_label,
|
337
|
+
)
|
338
|
+
|
339
|
+
def _load_cytoscape_json_network(self, filepath, source_label="source", target_label="target"):
|
340
|
+
"""Private method to load a network from a Cytoscape JSON (.cyjs) file.
|
341
|
+
|
185
342
|
Args:
|
186
343
|
filepath (str): Path to the Cytoscape JSON file.
|
187
344
|
source_label (str, optional): Source node label. Default is "source".
|
@@ -193,36 +350,46 @@ class NetworkIO:
|
|
193
350
|
filetype = "Cytoscape JSON"
|
194
351
|
params.log_network(filetype=filetype, filepath=str(filepath))
|
195
352
|
self._log_loading(filetype, filepath=filepath)
|
353
|
+
|
196
354
|
# Load the Cytoscape JSON file
|
197
355
|
with open(filepath, "r") as f:
|
198
356
|
cyjs_data = json.load(f)
|
199
357
|
|
200
358
|
# Create a graph
|
201
359
|
G = nx.Graph()
|
202
|
-
#
|
360
|
+
# Store node positions for later use
|
203
361
|
node_x_positions = {}
|
204
362
|
node_y_positions = {}
|
205
363
|
for node in cyjs_data["elements"]["nodes"]:
|
206
364
|
node_data = node["data"]
|
207
|
-
node_id = node_data["
|
365
|
+
node_id = node_data["id_original"]
|
208
366
|
node_x_positions[node_id] = node["position"]["x"]
|
209
367
|
node_y_positions[node_id] = node["position"]["y"]
|
210
|
-
G.add_node(node_id)
|
211
|
-
G.nodes[node_id]["label"] = node_data.get("name", node_id)
|
212
|
-
G.nodes[node_id]["x"] = node["position"]["x"]
|
213
|
-
G.nodes[node_id]["y"] = node["position"]["y"]
|
214
368
|
|
215
|
-
# Process edges
|
369
|
+
# Process edges and add them to the graph
|
216
370
|
for edge in cyjs_data["elements"]["edges"]:
|
217
371
|
edge_data = edge["data"]
|
218
|
-
source = edge_data[source_label]
|
219
|
-
target = edge_data[target_label]
|
372
|
+
source = edge_data[f"{source_label}_original"]
|
373
|
+
target = edge_data[f"{target_label}_original"]
|
374
|
+
# Add the edge to the graph, optionally including weights
|
220
375
|
if self.weight_label is not None and self.weight_label in edge_data:
|
221
376
|
weight = float(edge_data[self.weight_label])
|
222
377
|
G.add_edge(source, target, weight=weight)
|
223
378
|
else:
|
224
379
|
G.add_edge(source, target)
|
225
380
|
|
381
|
+
# Ensure nodes exist in the graph and add them if not present
|
382
|
+
if source not in G:
|
383
|
+
G.add_node(source)
|
384
|
+
if target not in G:
|
385
|
+
G.add_node(target)
|
386
|
+
|
387
|
+
# Add node attributes (like label, x, y positions)
|
388
|
+
for node in G.nodes():
|
389
|
+
G.nodes[node]["label"] = node
|
390
|
+
G.nodes[node]["x"] = node_x_positions.get(node, 0) # Use stored positions
|
391
|
+
G.nodes[node]["y"] = node_y_positions.get(node, 0) # Use stored positions
|
392
|
+
|
226
393
|
# Initialize the graph
|
227
394
|
return self._initialize_graph(G)
|
228
395
|
|
@@ -320,7 +487,6 @@ class NetworkIO:
|
|
320
487
|
print(f"Projection: {'Sphere' if self.compute_sphere else 'Plane'}")
|
321
488
|
if self.compute_sphere:
|
322
489
|
print(f"Surface depth: {self.surface_depth}")
|
323
|
-
print(f"Edge length threshold: {self.edge_length_threshold}")
|
324
490
|
print(f"Edge weight: {'Included' if self.include_edge_weight else 'Excluded'}")
|
325
491
|
if self.include_edge_weight:
|
326
492
|
print(f"Weight label: {self.weight_label}")
|
risk/network/plot.py
CHANGED
@@ -27,7 +27,7 @@ class NetworkPlotter:
|
|
27
27
|
|
28
28
|
def __init__(
|
29
29
|
self,
|
30
|
-
|
30
|
+
graph: NetworkGraph,
|
31
31
|
figsize: tuple = (10, 10),
|
32
32
|
background_color: str = "white",
|
33
33
|
plot_outline: bool = True,
|
@@ -37,22 +37,22 @@ class NetworkPlotter:
|
|
37
37
|
"""Initialize the NetworkPlotter with a NetworkGraph object and plotting parameters.
|
38
38
|
|
39
39
|
Args:
|
40
|
-
|
40
|
+
graph (NetworkGraph): The network data and attributes to be visualized.
|
41
41
|
figsize (tuple, optional): Size of the figure in inches (width, height). Defaults to (10, 10).
|
42
42
|
background_color (str, optional): Background color of the plot. Defaults to "white".
|
43
43
|
plot_outline (bool, optional): Whether to plot the network perimeter circle. Defaults to True.
|
44
44
|
outline_color (str, optional): Color of the network perimeter circle. Defaults to "black".
|
45
45
|
outline_scale (float, optional): Outline scaling factor for the perimeter diameter. Defaults to 1.0.
|
46
46
|
"""
|
47
|
-
self.
|
47
|
+
self.graph = graph
|
48
48
|
# Initialize the plot with the specified parameters
|
49
49
|
self.ax = self._initialize_plot(
|
50
|
-
|
50
|
+
graph, figsize, background_color, plot_outline, outline_color, outline_scale
|
51
51
|
)
|
52
52
|
|
53
53
|
def _initialize_plot(
|
54
54
|
self,
|
55
|
-
|
55
|
+
graph: NetworkGraph,
|
56
56
|
figsize: tuple,
|
57
57
|
background_color: str,
|
58
58
|
plot_outline: bool,
|
@@ -62,7 +62,7 @@ class NetworkPlotter:
|
|
62
62
|
"""Set up the plot with figure size, optional circle perimeter, and background color.
|
63
63
|
|
64
64
|
Args:
|
65
|
-
|
65
|
+
graph (NetworkGraph): The network data and attributes to be visualized.
|
66
66
|
figsize (tuple): Size of the figure in inches (width, height).
|
67
67
|
background_color (str): Background color of the plot.
|
68
68
|
plot_outline (bool): Whether to plot the network perimeter circle.
|
@@ -73,7 +73,7 @@ class NetworkPlotter:
|
|
73
73
|
plt.Axes: The axis object for the plot.
|
74
74
|
"""
|
75
75
|
# Extract node coordinates from the network graph
|
76
|
-
node_coordinates =
|
76
|
+
node_coordinates = graph.node_coordinates
|
77
77
|
# Calculate the center and radius of the bounding box around the network
|
78
78
|
center, radius = _calculate_bounding_box(node_coordinates)
|
79
79
|
# Scale the radius by the outline_scale factor
|
@@ -141,10 +141,10 @@ class NetworkPlotter:
|
|
141
141
|
network_node_shape=node_shape,
|
142
142
|
)
|
143
143
|
# Extract node coordinates from the network graph
|
144
|
-
node_coordinates = self.
|
144
|
+
node_coordinates = self.graph.node_coordinates
|
145
145
|
# Draw the nodes of the graph
|
146
146
|
nx.draw_networkx_nodes(
|
147
|
-
self.
|
147
|
+
self.graph.network,
|
148
148
|
pos=node_coordinates,
|
149
149
|
node_size=node_size,
|
150
150
|
node_color=node_color,
|
@@ -155,7 +155,7 @@ class NetworkPlotter:
|
|
155
155
|
)
|
156
156
|
# Draw the edges of the graph
|
157
157
|
nx.draw_networkx_edges(
|
158
|
-
self.
|
158
|
+
self.graph.network,
|
159
159
|
pos=node_coordinates,
|
160
160
|
width=edge_width,
|
161
161
|
edge_color=edge_color,
|
@@ -197,20 +197,18 @@ class NetworkPlotter:
|
|
197
197
|
)
|
198
198
|
# Filter to get node IDs and their coordinates
|
199
199
|
node_ids = [
|
200
|
-
self.
|
200
|
+
self.graph.node_label_to_id_map.get(node)
|
201
201
|
for node in nodes
|
202
|
-
if node in self.
|
202
|
+
if node in self.graph.node_label_to_id_map
|
203
203
|
]
|
204
204
|
if not node_ids:
|
205
205
|
raise ValueError("No nodes found in the network graph.")
|
206
206
|
|
207
207
|
# Get the coordinates of the filtered nodes
|
208
|
-
node_coordinates = {
|
209
|
-
node_id: self.network_graph.node_coordinates[node_id] for node_id in node_ids
|
210
|
-
}
|
208
|
+
node_coordinates = {node_id: self.graph.node_coordinates[node_id] for node_id in node_ids}
|
211
209
|
# Draw the nodes in the subnetwork
|
212
210
|
nx.draw_networkx_nodes(
|
213
|
-
self.
|
211
|
+
self.graph.network,
|
214
212
|
pos=node_coordinates,
|
215
213
|
nodelist=node_ids,
|
216
214
|
node_size=node_size,
|
@@ -221,7 +219,7 @@ class NetworkPlotter:
|
|
221
219
|
ax=self.ax,
|
222
220
|
)
|
223
221
|
# Draw the edges between the specified nodes in the subnetwork
|
224
|
-
subgraph = self.
|
222
|
+
subgraph = self.graph.network.subgraph(node_ids)
|
225
223
|
nx.draw_networkx_edges(
|
226
224
|
subgraph,
|
227
225
|
pos=node_coordinates,
|
@@ -260,9 +258,9 @@ class NetworkPlotter:
|
|
260
258
|
color = self.get_annotated_contour_colors(color=color)
|
261
259
|
|
262
260
|
# Extract node coordinates from the network graph
|
263
|
-
node_coordinates = self.
|
261
|
+
node_coordinates = self.graph.node_coordinates
|
264
262
|
# Draw contours for each domain in the network
|
265
|
-
for idx, (_, nodes) in enumerate(self.
|
263
|
+
for idx, (_, nodes) in enumerate(self.graph.domain_to_nodes.items()):
|
266
264
|
if len(nodes) > 1:
|
267
265
|
self._draw_kde_contour(
|
268
266
|
self.ax,
|
@@ -299,23 +297,23 @@ class NetworkPlotter:
|
|
299
297
|
"""
|
300
298
|
# Log the plotting parameters
|
301
299
|
params.log_plotter(
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
300
|
+
subcontour_levels=levels,
|
301
|
+
subcontour_bandwidth=bandwidth,
|
302
|
+
subcontour_grid_size=grid_size,
|
303
|
+
subcontour_alpha=alpha,
|
304
|
+
subcontour_color="custom" if isinstance(color, np.ndarray) else color,
|
307
305
|
)
|
308
306
|
# Filter to get node IDs and their coordinates
|
309
307
|
node_ids = [
|
310
|
-
self.
|
308
|
+
self.graph.node_label_to_id_map.get(node)
|
311
309
|
for node in nodes
|
312
|
-
if node in self.
|
310
|
+
if node in self.graph.node_label_to_id_map
|
313
311
|
]
|
314
312
|
if not node_ids or len(node_ids) == 1:
|
315
313
|
raise ValueError("No nodes found in the network graph or insufficient nodes to plot.")
|
316
314
|
|
317
315
|
# Draw the KDE contour for the specified nodes
|
318
|
-
node_coordinates = self.
|
316
|
+
node_coordinates = self.graph.node_coordinates
|
319
317
|
self._draw_kde_contour(
|
320
318
|
self.ax,
|
321
319
|
node_coordinates,
|
@@ -402,7 +400,7 @@ class NetworkPlotter:
|
|
402
400
|
fontcolor: Union[str, np.ndarray] = "black",
|
403
401
|
arrow_linewidth: float = 1,
|
404
402
|
arrow_color: Union[str, np.ndarray] = "black",
|
405
|
-
|
403
|
+
max_words: int = 10,
|
406
404
|
min_words: int = 1,
|
407
405
|
) -> None:
|
408
406
|
"""Annotate the network graph with labels for different domains, positioned around the network for clarity.
|
@@ -415,7 +413,7 @@ class NetworkPlotter:
|
|
415
413
|
fontcolor (str or np.ndarray, optional): Color of the label text. Can be a string or RGBA array. Defaults to "black".
|
416
414
|
arrow_linewidth (float, optional): Line width of the arrows pointing to centroids. Defaults to 1.
|
417
415
|
arrow_color (str or np.ndarray, optional): Color of the arrows. Can be a string or RGBA array. Defaults to "black".
|
418
|
-
|
416
|
+
max_words (int, optional): Maximum number of words in a label. Defaults to 10.
|
419
417
|
min_words (int, optional): Minimum number of words required to display a label. Defaults to 1.
|
420
418
|
"""
|
421
419
|
# Log the plotting parameters
|
@@ -427,7 +425,7 @@ class NetworkPlotter:
|
|
427
425
|
label_fontcolor="custom" if isinstance(fontcolor, np.ndarray) else fontcolor,
|
428
426
|
label_arrow_linewidth=arrow_linewidth,
|
429
427
|
label_arrow_color="custom" if isinstance(arrow_color, np.ndarray) else arrow_color,
|
430
|
-
|
428
|
+
label_max_words=max_words,
|
431
429
|
label_min_words=min_words,
|
432
430
|
)
|
433
431
|
# Convert color strings to RGBA arrays if necessary
|
@@ -438,28 +436,38 @@ class NetworkPlotter:
|
|
438
436
|
|
439
437
|
# Calculate the center and radius of the network
|
440
438
|
domain_centroids = {}
|
441
|
-
for domain, nodes in self.
|
439
|
+
for domain, nodes in self.graph.domain_to_nodes.items():
|
442
440
|
if nodes: # Skip if the domain has no nodes
|
443
441
|
domain_centroids[domain] = self._calculate_domain_centroid(nodes)
|
444
442
|
|
443
|
+
# Initialize empty lists to collect valid indices
|
444
|
+
valid_indices = []
|
445
|
+
filtered_domain_centroids = {}
|
446
|
+
# Loop through domain_centroids with index
|
447
|
+
for idx, (domain, centroid) in enumerate(domain_centroids.items()):
|
448
|
+
# Check if the domain passes the word count condition
|
449
|
+
if len(self.graph.trimmed_domain_to_term[domain].split(" ")[:max_words]) >= min_words:
|
450
|
+
# Add to filtered_domain_centroids
|
451
|
+
filtered_domain_centroids[domain] = centroid
|
452
|
+
# Keep track of the valid index
|
453
|
+
valid_indices.append(idx)
|
454
|
+
|
455
|
+
# Now filter fontcolor and arrow_color to keep only the valid indices
|
456
|
+
fontcolor = fontcolor[valid_indices]
|
457
|
+
arrow_color = arrow_color[valid_indices]
|
458
|
+
|
445
459
|
# Calculate the bounding box around the network
|
446
460
|
center, radius = _calculate_bounding_box(
|
447
|
-
self.
|
461
|
+
self.graph.node_coordinates, radius_margin=perimeter_scale
|
448
462
|
)
|
449
|
-
|
450
|
-
# Filter out domains with insufficient words for labeling
|
451
|
-
filtered_domains = {
|
452
|
-
domain: centroid
|
453
|
-
for domain, centroid in domain_centroids.items()
|
454
|
-
if len(self.network_graph.trimmed_domain_to_term[domain].split(" ")[:num_words])
|
455
|
-
>= min_words
|
456
|
-
}
|
457
463
|
# Calculate the best positions for labels around the perimeter
|
458
|
-
best_label_positions = _best_label_positions(
|
464
|
+
best_label_positions = _best_label_positions(
|
465
|
+
filtered_domain_centroids, center, radius, offset
|
466
|
+
)
|
459
467
|
# Annotate the network with labels
|
460
468
|
for idx, (domain, pos) in enumerate(best_label_positions.items()):
|
461
|
-
centroid =
|
462
|
-
annotations = self.
|
469
|
+
centroid = filtered_domain_centroids[domain]
|
470
|
+
annotations = self.graph.trimmed_domain_to_term[domain].split(" ")[:max_words]
|
463
471
|
self.ax.annotate(
|
464
472
|
"\n".join(annotations),
|
465
473
|
xy=centroid,
|
@@ -473,6 +481,83 @@ class NetworkPlotter:
|
|
473
481
|
arrowprops=dict(arrowstyle="->", color=arrow_color[idx], linewidth=arrow_linewidth),
|
474
482
|
)
|
475
483
|
|
484
|
+
def plot_sublabel(
|
485
|
+
self,
|
486
|
+
nodes: list,
|
487
|
+
label: str,
|
488
|
+
radial_position: float = 0.0,
|
489
|
+
perimeter_scale: float = 1.05,
|
490
|
+
offset: float = 0.10,
|
491
|
+
font: str = "Arial",
|
492
|
+
fontsize: int = 10,
|
493
|
+
fontcolor: str = "black",
|
494
|
+
arrow_linewidth: float = 1,
|
495
|
+
arrow_color: str = "black",
|
496
|
+
) -> None:
|
497
|
+
"""Annotate the network graph with a single label for the given nodes, positioned at a specified radial angle.
|
498
|
+
|
499
|
+
Args:
|
500
|
+
nodes (List[str]): List of node labels to be used for calculating the centroid.
|
501
|
+
label (str): The label to be annotated on the network.
|
502
|
+
radial_position (float, optional): Radial angle for positioning the label, in degrees (0-360). Defaults to 0.0.
|
503
|
+
perimeter_scale (float, optional): Scale factor for positioning the label around the perimeter. Defaults to 1.05.
|
504
|
+
offset (float, optional): Offset distance for the label from the perimeter. Defaults to 0.10.
|
505
|
+
font (str, optional): Font name for the label. Defaults to "Arial".
|
506
|
+
fontsize (int, optional): Font size for the label. Defaults to 10.
|
507
|
+
fontcolor (str, optional): Color of the label text. Defaults to "black".
|
508
|
+
arrow_linewidth (float, optional): Line width of the arrow pointing to the centroid. Defaults to 1.
|
509
|
+
arrow_color (str, optional): Color of the arrow. Defaults to "black".
|
510
|
+
"""
|
511
|
+
# Log the plotting parameters
|
512
|
+
params.log_plotter(
|
513
|
+
sublabel_perimeter_scale=perimeter_scale,
|
514
|
+
sublabel_offset=offset,
|
515
|
+
sublabel_font=font,
|
516
|
+
sublabel_fontsize=fontsize,
|
517
|
+
sublabel_fontcolor="custom" if isinstance(fontcolor, np.ndarray) else fontcolor,
|
518
|
+
sublabel_arrow_linewidth=arrow_linewidth,
|
519
|
+
sublabel_arrow_color="custom" if isinstance(arrow_color, np.ndarray) else arrow_color,
|
520
|
+
sublabel_radial_position=radial_position,
|
521
|
+
)
|
522
|
+
|
523
|
+
# Map node labels to IDs
|
524
|
+
node_ids = [
|
525
|
+
self.graph.node_label_to_id_map.get(node)
|
526
|
+
for node in nodes
|
527
|
+
if node in self.graph.node_label_to_id_map
|
528
|
+
]
|
529
|
+
if not node_ids or len(node_ids) == 1:
|
530
|
+
raise ValueError("No nodes found in the network graph or insufficient nodes to plot.")
|
531
|
+
|
532
|
+
# Calculate the centroid of the provided nodes
|
533
|
+
centroid = self._calculate_domain_centroid(node_ids)
|
534
|
+
|
535
|
+
# Calculate the bounding box around the network
|
536
|
+
center, radius = _calculate_bounding_box(
|
537
|
+
self.graph.node_coordinates, radius_margin=perimeter_scale
|
538
|
+
)
|
539
|
+
|
540
|
+
# Convert radial position to radians, adjusting for a 90-degree rotation
|
541
|
+
radial_radians = np.deg2rad(radial_position - 90)
|
542
|
+
label_position = (
|
543
|
+
center[0] + (radius + offset) * np.cos(radial_radians),
|
544
|
+
center[1] + (radius + offset) * np.sin(radial_radians),
|
545
|
+
)
|
546
|
+
|
547
|
+
# Annotate the network with the label
|
548
|
+
self.ax.annotate(
|
549
|
+
label,
|
550
|
+
xy=centroid,
|
551
|
+
xytext=label_position,
|
552
|
+
textcoords="data",
|
553
|
+
ha="center",
|
554
|
+
va="center",
|
555
|
+
fontsize=fontsize,
|
556
|
+
fontname=font,
|
557
|
+
color=fontcolor,
|
558
|
+
arrowprops=dict(arrowstyle="->", color=arrow_color, linewidth=arrow_linewidth),
|
559
|
+
)
|
560
|
+
|
476
561
|
def _calculate_domain_centroid(self, nodes: list) -> tuple:
|
477
562
|
"""Calculate the most centrally located node in .
|
478
563
|
|
@@ -483,7 +568,7 @@ class NetworkPlotter:
|
|
483
568
|
tuple: A tuple containing the domain's central node coordinates.
|
484
569
|
"""
|
485
570
|
# Extract positions of all nodes in the domain
|
486
|
-
node_positions = self.
|
571
|
+
node_positions = self.graph.node_coordinates[nodes, :]
|
487
572
|
# Calculate the pairwise distance matrix between all nodes in the domain
|
488
573
|
distances_matrix = np.linalg.norm(node_positions[:, np.newaxis] - node_positions, axis=2)
|
489
574
|
# Sum the distances for each node to all other nodes in the domain
|
@@ -508,7 +593,7 @@ class NetworkPlotter:
|
|
508
593
|
np.ndarray: Array of RGBA colors adjusted for enrichment status.
|
509
594
|
"""
|
510
595
|
# Get the initial domain colors for each node
|
511
|
-
network_colors = self.
|
596
|
+
network_colors = self.graph.get_domain_colors(**kwargs, random_seed=random_seed)
|
512
597
|
if isinstance(nonenriched_color, str):
|
513
598
|
# Convert the non-enriched color from string to RGBA
|
514
599
|
nonenriched_color = mcolors.to_rgba(nonenriched_color)
|
@@ -535,14 +620,14 @@ class NetworkPlotter:
|
|
535
620
|
"""
|
536
621
|
# Merge all enriched nodes from the domain_to_nodes dictionary
|
537
622
|
enriched_nodes = set()
|
538
|
-
for _, nodes in self.
|
623
|
+
for _, nodes in self.graph.domain_to_nodes.items():
|
539
624
|
enriched_nodes.update(nodes)
|
540
625
|
|
541
626
|
# Initialize all node sizes to the non-enriched size
|
542
|
-
node_sizes = np.full(len(self.
|
627
|
+
node_sizes = np.full(len(self.graph.network.nodes), nonenriched_nodesize)
|
543
628
|
# Set the size for enriched nodes
|
544
629
|
for node in enriched_nodes:
|
545
|
-
if node in self.
|
630
|
+
if node in self.graph.network.nodes:
|
546
631
|
node_sizes[node] = enriched_nodesize
|
547
632
|
|
548
633
|
return node_sizes
|
@@ -587,12 +672,12 @@ class NetworkPlotter:
|
|
587
672
|
if isinstance(color, str):
|
588
673
|
# If a single color string is provided, convert it to RGBA and apply to all domains
|
589
674
|
rgba_color = np.array(matplotlib.colors.to_rgba(color))
|
590
|
-
return np.array([rgba_color for _ in self.
|
675
|
+
return np.array([rgba_color for _ in self.graph.domain_to_nodes])
|
591
676
|
|
592
677
|
# Generate colors for each domain using the provided arguments and random seed
|
593
|
-
node_colors = self.
|
678
|
+
node_colors = self.graph.get_domain_colors(**kwargs, random_seed=random_seed)
|
594
679
|
annotated_colors = []
|
595
|
-
for _, nodes in self.
|
680
|
+
for _, nodes in self.graph.domain_to_nodes.items():
|
596
681
|
if len(nodes) > 1:
|
597
682
|
# For domains with multiple nodes, choose the brightest color (sum of RGB values)
|
598
683
|
domain_colors = np.array([node_colors[node] for node in nodes])
|
@@ -662,12 +747,12 @@ def _calculate_bounding_box(
|
|
662
747
|
|
663
748
|
|
664
749
|
def _best_label_positions(
|
665
|
-
|
750
|
+
filtered_domain_centroids: Dict[str, Any], center: np.ndarray, radius: float, offset: float
|
666
751
|
) -> Dict[str, Any]:
|
667
752
|
"""Calculate and optimize label positions for clarity.
|
668
753
|
|
669
754
|
Args:
|
670
|
-
|
755
|
+
filtered_domain_centroids (dict): Centroids of the filtered domains.
|
671
756
|
center (np.ndarray): The center coordinates for label positioning.
|
672
757
|
radius (float): The radius for positioning labels around the center.
|
673
758
|
offset (float): The offset distance from the radius for positioning labels.
|
@@ -675,15 +760,16 @@ def _best_label_positions(
|
|
675
760
|
Returns:
|
676
761
|
dict: Optimized positions for labels.
|
677
762
|
"""
|
678
|
-
num_domains = len(
|
763
|
+
num_domains = len(filtered_domain_centroids)
|
679
764
|
# Calculate equidistant positions around the center for initial label placement
|
680
765
|
equidistant_positions = _equidistant_angles_around_center(center, radius, offset, num_domains)
|
681
766
|
# Create a mapping of domains to their initial label positions
|
682
767
|
label_positions = {
|
683
|
-
domain: position
|
768
|
+
domain: position
|
769
|
+
for domain, position in zip(filtered_domain_centroids.keys(), equidistant_positions)
|
684
770
|
}
|
685
771
|
# Optimize the label positions to minimize distance to domain centroids
|
686
|
-
return _optimize_label_positions(label_positions,
|
772
|
+
return _optimize_label_positions(label_positions, filtered_domain_centroids)
|
687
773
|
|
688
774
|
|
689
775
|
def _equidistant_angles_around_center(
|
risk/risk.py
CHANGED
@@ -27,64 +27,12 @@ class RISK(NetworkIO, AnnotationsIO):
|
|
27
27
|
and performing network-based statistical analysis, such as neighborhood significance testing.
|
28
28
|
"""
|
29
29
|
|
30
|
-
def __init__(
|
31
|
-
|
32
|
-
compute_sphere: bool = True,
|
33
|
-
surface_depth: float = 0.0,
|
34
|
-
distance_metric: str = "dijkstra",
|
35
|
-
louvain_resolution: float = 0.1,
|
36
|
-
min_edges_per_node: int = 0,
|
37
|
-
edge_length_threshold: float = 0.5,
|
38
|
-
include_edge_weight: bool = True,
|
39
|
-
weight_label: str = "weight",
|
40
|
-
):
|
41
|
-
"""Initialize the RISK class with configuration settings.
|
42
|
-
|
43
|
-
Args:
|
44
|
-
compute_sphere (bool, optional): Whether to map nodes to a sphere. Defaults to True.
|
45
|
-
surface_depth (float, optional): Surface depth for the sphere. Defaults to 0.0.
|
46
|
-
distance_metric (str, optional): Distance metric to use in network analysis. Defaults to "dijkstra".
|
47
|
-
louvain_resolution (float, optional): Resolution parameter for Louvain clustering. Defaults to 0.1.
|
48
|
-
min_edges_per_node (int, optional): Minimum number of edges per node. Defaults to 0.
|
49
|
-
edge_length_threshold (float, optional): Edge length threshold for analysis. Defaults to 0.5.
|
50
|
-
include_edge_weight (bool, optional): Whether to include edge weights in calculations. Defaults to True.
|
51
|
-
weight_label (str, optional): Label for edge weights. Defaults to "weight".
|
52
|
-
"""
|
30
|
+
def __init__(self, *args, **kwargs):
|
31
|
+
"""Initialize the RISK class with configuration settings."""
|
53
32
|
# Initialize and log network parameters
|
54
33
|
params.initialize()
|
55
|
-
|
56
|
-
|
57
|
-
surface_depth=surface_depth,
|
58
|
-
distance_metric=distance_metric,
|
59
|
-
louvain_resolution=louvain_resolution,
|
60
|
-
min_edges_per_node=min_edges_per_node,
|
61
|
-
edge_length_threshold=edge_length_threshold,
|
62
|
-
include_edge_weight=include_edge_weight,
|
63
|
-
weight_label=weight_label,
|
64
|
-
)
|
65
|
-
# Initialize parent classes
|
66
|
-
NetworkIO.__init__(
|
67
|
-
self,
|
68
|
-
compute_sphere=compute_sphere,
|
69
|
-
surface_depth=surface_depth,
|
70
|
-
distance_metric=distance_metric,
|
71
|
-
louvain_resolution=louvain_resolution,
|
72
|
-
min_edges_per_node=min_edges_per_node,
|
73
|
-
edge_length_threshold=edge_length_threshold,
|
74
|
-
include_edge_weight=include_edge_weight,
|
75
|
-
weight_label=weight_label,
|
76
|
-
)
|
77
|
-
AnnotationsIO.__init__(self)
|
78
|
-
|
79
|
-
# Set class attributes
|
80
|
-
self.compute_sphere = compute_sphere
|
81
|
-
self.surface_depth = surface_depth
|
82
|
-
self.distance_metric = distance_metric
|
83
|
-
self.louvain_resolution = louvain_resolution
|
84
|
-
self.min_edges_per_node = min_edges_per_node
|
85
|
-
self.edge_length_threshold = edge_length_threshold
|
86
|
-
self.include_edge_weight = include_edge_weight
|
87
|
-
self.weight_label = weight_label
|
34
|
+
# Initialize the parent classes
|
35
|
+
super().__init__(*args, **kwargs)
|
88
36
|
|
89
37
|
@property
|
90
38
|
def params(self):
|
@@ -95,6 +43,9 @@ class RISK(NetworkIO, AnnotationsIO):
|
|
95
43
|
self,
|
96
44
|
network: nx.Graph,
|
97
45
|
annotations: Dict[str, Any],
|
46
|
+
distance_metric: str = "dijkstra",
|
47
|
+
louvain_resolution: float = 0.1,
|
48
|
+
edge_length_threshold: float = 0.5,
|
98
49
|
score_metric: str = "sum",
|
99
50
|
null_distribution: str = "network",
|
100
51
|
num_permutations: int = 1000,
|
@@ -106,6 +57,9 @@ class RISK(NetworkIO, AnnotationsIO):
|
|
106
57
|
Args:
|
107
58
|
network (nx.Graph): The network graph.
|
108
59
|
annotations (pd.DataFrame): The matrix of annotations associated with the network.
|
60
|
+
distance_metric (str, optional): Distance metric for neighborhood analysis. Defaults to "dijkstra".
|
61
|
+
louvain_resolution (float, optional): Resolution parameter for Louvain clustering. Defaults to 0.1.
|
62
|
+
edge_length_threshold (float, optional): Edge length threshold for neighborhood analysis. Defaults to 0.5.
|
109
63
|
score_metric (str, optional): Scoring metric for neighborhood significance. Defaults to "sum".
|
110
64
|
null_distribution (str, optional): Distribution used for permutation tests. Defaults to "network".
|
111
65
|
num_permutations (int, optional): Number of permutations for significance testing. Defaults to 1000.
|
@@ -118,6 +72,9 @@ class RISK(NetworkIO, AnnotationsIO):
|
|
118
72
|
print_header("Running permutation test")
|
119
73
|
# Log neighborhood analysis parameters
|
120
74
|
params.log_neighborhoods(
|
75
|
+
distance_metric=distance_metric,
|
76
|
+
louvain_resolution=louvain_resolution,
|
77
|
+
edge_length_threshold=edge_length_threshold,
|
121
78
|
score_metric=score_metric,
|
122
79
|
null_distribution=null_distribution,
|
123
80
|
num_permutations=num_permutations,
|
@@ -126,17 +83,18 @@ class RISK(NetworkIO, AnnotationsIO):
|
|
126
83
|
)
|
127
84
|
|
128
85
|
# Display the chosen distance metric
|
129
|
-
if
|
130
|
-
for_print_distance_metric = f"louvain (resolution={
|
86
|
+
if distance_metric == "louvain":
|
87
|
+
for_print_distance_metric = f"louvain (resolution={louvain_resolution})"
|
131
88
|
else:
|
132
|
-
for_print_distance_metric =
|
89
|
+
for_print_distance_metric = distance_metric
|
133
90
|
print(f"Distance metric: '{for_print_distance_metric}'")
|
91
|
+
print(f"Edge length threshold: {edge_length_threshold}")
|
134
92
|
# Compute neighborhoods based on the network and distance metric
|
135
93
|
neighborhoods = get_network_neighborhoods(
|
136
94
|
network,
|
137
|
-
|
138
|
-
|
139
|
-
louvain_resolution=
|
95
|
+
distance_metric,
|
96
|
+
edge_length_threshold,
|
97
|
+
louvain_resolution=louvain_resolution,
|
140
98
|
random_seed=random_seed,
|
141
99
|
)
|
142
100
|
|
@@ -144,6 +102,8 @@ class RISK(NetworkIO, AnnotationsIO):
|
|
144
102
|
print(f"Null distribution: '{null_distribution}'")
|
145
103
|
print(f"Neighborhood scoring metric: '{score_metric}'")
|
146
104
|
print(f"Number of permutations: {num_permutations}")
|
105
|
+
print(f"Random seed: {random_seed}")
|
106
|
+
print(f"Maximum workers: {max_workers}")
|
147
107
|
# Run the permutation test to compute neighborhood significance
|
148
108
|
neighborhood_significance = compute_permutation(
|
149
109
|
neighborhoods=neighborhoods,
|
risk/stats/stats.py
CHANGED
@@ -150,14 +150,14 @@ def _run_permutation_test(
|
|
150
150
|
]
|
151
151
|
|
152
152
|
# Start the permutation process in parallel
|
153
|
-
results = pool.starmap_async(_permutation_process_subset, params_list)
|
153
|
+
results = pool.starmap_async(_permutation_process_subset, params_list, chunksize=1)
|
154
154
|
|
155
155
|
# Update progress bar based on progress_counter
|
156
156
|
# NOTE: Waiting for results to be ready while updating progress bar gives a big improvement
|
157
157
|
# in performance, especially for large number of permutations and workers
|
158
158
|
while not results.ready():
|
159
159
|
progress.update(progress_counter.value - progress.n)
|
160
|
-
results.wait(
|
160
|
+
results.wait(0.05) # Wait for 50ms
|
161
161
|
|
162
162
|
# Ensure progress bar reaches 100%
|
163
163
|
progress.update(total_progress - progress.n)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: risk-network
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.4b1
|
4
4
|
Summary: A Python package for biological network analysis
|
5
5
|
Author: Ira Horecka
|
6
6
|
Author-email: Ira Horecka <ira89@icloud.com>
|
@@ -684,14 +684,14 @@ Classifier: Intended Audience :: Science/Research
|
|
684
684
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
685
685
|
Classifier: Operating System :: OS Independent
|
686
686
|
Classifier: Programming Language :: Python :: 3
|
687
|
-
Classifier: Programming Language :: Python :: 3.
|
687
|
+
Classifier: Programming Language :: Python :: 3.8
|
688
688
|
Classifier: Programming Language :: Python :: 3 :: Only
|
689
689
|
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
690
690
|
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
691
691
|
Classifier: Topic :: Scientific/Engineering :: Visualization
|
692
692
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
693
693
|
Classifier: Development Status :: 4 - Beta
|
694
|
-
Requires-Python: >=3.
|
694
|
+
Requires-Python: >=3.8
|
695
695
|
Description-Content-Type: text/markdown
|
696
696
|
License-File: LICENSE
|
697
697
|
Requires-Dist: ipywidgets
|
@@ -716,7 +716,7 @@ Requires-Dist: tqdm
|
|
716
716
|
|
717
717
|
<p align="center">
|
718
718
|
<a href="https://pypi.python.org/pypi/risk-network"><img src="https://img.shields.io/pypi/v/risk-network.svg" alt="pypiv"></a>
|
719
|
-
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.
|
719
|
+
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.8+-blue.svg" alt="Python 3.8+"></a>
|
720
720
|
<a href="https://raw.githubusercontent.com/irahorecka/chrono24/main/LICENSE"><img src="https://img.shields.io/badge/License-GPLv3-blue.svg" alt="License: GPL v3"></a>
|
721
721
|
</p>
|
722
722
|
|
@@ -736,7 +736,7 @@ RISK is a software tool for visualizing spatial relationships in networks. It ai
|
|
736
736
|
|
737
737
|
*Saccharomyces cerevisiae* proteins oriented by physical interactions discovered through affinity enrichment and mass spectrometry (Michaelis et al., 2023).
|
738
738
|
|
739
|
-

|
740
740
|
|
741
741
|
## Installation
|
742
742
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
risk/__init__.py,sha256=mAHhUWFzKCookp6VYUp1WNQXgQStNGIUXaOZ2QfFtwc,122
|
2
|
+
risk/constants.py,sha256=AICk3x5qRQhls_ijTb4VdbdxU6mZ1aLGbAjLEdBwfJI,550
|
3
|
+
risk/risk.py,sha256=Kaju0siA2piDWuawSB1iZcngm9BND_R7iJAqAS_55E0,14717
|
4
|
+
risk/annotations/__init__.py,sha256=vUpVvMRE5if01Ic8QY6M2Ae3EFGJHdugEe9PdEkAW4Y,138
|
5
|
+
risk/annotations/annotations.py,sha256=0-Yf2XPVdMzpttLLgLxtTTnH0Eed_Uv8VXMur6E6xKw,10481
|
6
|
+
risk/annotations/io.py,sha256=TMicRACfY8bNtmbvVrxHoh8zkOVLOIhZwWrpxUlR28Q,7988
|
7
|
+
risk/log/__init__.py,sha256=xuLImfxFlKpnVhzi_gDYlr2_c9cLkrw2c_3iEsXb1as,107
|
8
|
+
risk/log/console.py,sha256=im9DRExwf6wHlcn9fewoDcKIpo3vPcorZIaNAl-0csY,355
|
9
|
+
risk/log/params.py,sha256=Tbb-sovFTptGBqPDKafUA8KOpby4zFObutAT_Iti1hE,6302
|
10
|
+
risk/neighborhoods/__init__.py,sha256=tKKEg4lsbqFukpgYlUGxU_v_9FOqK7V0uvM9T2QzoL0,206
|
11
|
+
risk/neighborhoods/community.py,sha256=eL2IGT-8sbiJIyfyb_FGngev7pEMxw7tZb8YzbzOYw8,6512
|
12
|
+
risk/neighborhoods/domains.py,sha256=HwuChmZH0RGD9eQOvk2-ezQDJRUHHn93vhVgHb-kX6I,10192
|
13
|
+
risk/neighborhoods/neighborhoods.py,sha256=benMk6ZCufhi9FKo6ByaeOzwJ8y43vkFbCD-wUNaCAU,13828
|
14
|
+
risk/network/__init__.py,sha256=iEPeJdZfqp0toxtbElryB8jbz9_t_k4QQ3iDvKE8C_0,126
|
15
|
+
risk/network/geometry.py,sha256=euBMOVvxpj-0WZam40IbHdsT7E4WXpTwSxuGbmAGTDg,6757
|
16
|
+
risk/network/graph.py,sha256=m3bFWU5528OEm246LPG5XP3l_30vaBiJv4AO4iq0pSA,11552
|
17
|
+
risk/network/io.py,sha256=Vn__hWla0EI9djIv7mWc1bFSTS2pRpUwOjPCqMWQOYI,19689
|
18
|
+
risk/network/plot.py,sha256=-8LyRqeQi4cxEVxNsTDCyHhmTfFuObLLaFbKQGZwHCI,38289
|
19
|
+
risk/stats/__init__.py,sha256=4s9gdJo5B1G_cQc0iMoeIBt5OrQNXkdtNXkAMFQkLxc,103
|
20
|
+
risk/stats/permutation.py,sha256=xgaZbaxo57t_FzPlpcb2nsq8oCzc_wj-zAm-xj3P2dA,3404
|
21
|
+
risk/stats/stats.py,sha256=7Z-1sJ5zvS3XDjG2UfOV0Y3c3xliYeB-6fk_UHNqfiE,16019
|
22
|
+
risk_network-0.0.4b1.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
23
|
+
risk_network-0.0.4b1.dist-info/METADATA,sha256=YyRQOzpjmA1i506SBsBljqbz2hthqVYMfaSL5xIyz7I,43250
|
24
|
+
risk_network-0.0.4b1.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
|
25
|
+
risk_network-0.0.4b1.dist-info/top_level.txt,sha256=NX7C2PFKTvC1JhVKv14DFlFAIFnKc6Lpsu1ZfxvQwVw,5
|
26
|
+
risk_network-0.0.4b1.dist-info/RECORD,,
|
@@ -1,26 +0,0 @@
|
|
1
|
-
risk/__init__.py,sha256=7JTz-sr7kIgP1-2x6p8-HirKCr90zZTsy-gIbKdeYMw,122
|
2
|
-
risk/constants.py,sha256=AICk3x5qRQhls_ijTb4VdbdxU6mZ1aLGbAjLEdBwfJI,550
|
3
|
-
risk/risk.py,sha256=cWpYogZ-vma4ZZjewVNRMzb2TqHv8YABuzP2brXpOqo,16399
|
4
|
-
risk/annotations/__init__.py,sha256=vUpVvMRE5if01Ic8QY6M2Ae3EFGJHdugEe9PdEkAW4Y,138
|
5
|
-
risk/annotations/annotations.py,sha256=gZ9gihK_eTWaX3eByh08xr97FX4-XKe6MBwCCjasEDU,10368
|
6
|
-
risk/annotations/io.py,sha256=ozi7aFn3_geB6G0kt7Ya1qVhNOqP6rB0YISjriSZyNw,7989
|
7
|
-
risk/log/__init__.py,sha256=xuLImfxFlKpnVhzi_gDYlr2_c9cLkrw2c_3iEsXb1as,107
|
8
|
-
risk/log/console.py,sha256=im9DRExwf6wHlcn9fewoDcKIpo3vPcorZIaNAl-0csY,355
|
9
|
-
risk/log/params.py,sha256=Tbb-sovFTptGBqPDKafUA8KOpby4zFObutAT_Iti1hE,6302
|
10
|
-
risk/neighborhoods/__init__.py,sha256=tKKEg4lsbqFukpgYlUGxU_v_9FOqK7V0uvM9T2QzoL0,206
|
11
|
-
risk/neighborhoods/community.py,sha256=eL2IGT-8sbiJIyfyb_FGngev7pEMxw7tZb8YzbzOYw8,6512
|
12
|
-
risk/neighborhoods/domains.py,sha256=HwuChmZH0RGD9eQOvk2-ezQDJRUHHn93vhVgHb-kX6I,10192
|
13
|
-
risk/neighborhoods/neighborhoods.py,sha256=zGtxVIs0_Bg0wt1By6d77_lqW0PGXpOtQxeCEtyZFzA,13475
|
14
|
-
risk/network/__init__.py,sha256=iEPeJdZfqp0toxtbElryB8jbz9_t_k4QQ3iDvKE8C_0,126
|
15
|
-
risk/network/geometry.py,sha256=euBMOVvxpj-0WZam40IbHdsT7E4WXpTwSxuGbmAGTDg,6757
|
16
|
-
risk/network/graph.py,sha256=a7gM1d2jHqscFVwn1GZaJWb3oZOFraNsQ2RxC4osaV4,11528
|
17
|
-
risk/network/io.py,sha256=KmdrsDZe-ZT4O59NYZM_nQd8Ew9qpbzQcqWS_PaE7eA,12559
|
18
|
-
risk/network/plot.py,sha256=fy21X677xqJPFkn564Jegxy05C9x0pJXovd5fm3NZ4Q,34554
|
19
|
-
risk/stats/__init__.py,sha256=4s9gdJo5B1G_cQc0iMoeIBt5OrQNXkdtNXkAMFQkLxc,103
|
20
|
-
risk/stats/permutation.py,sha256=xgaZbaxo57t_FzPlpcb2nsq8oCzc_wj-zAm-xj3P2dA,3404
|
21
|
-
risk/stats/stats.py,sha256=Yu9LMSUtCRkg-h0ErJurb-rkajHgTvdzBcymHldJs5k,16007
|
22
|
-
risk_network-0.0.3b4.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
23
|
-
risk_network-0.0.3b4.dist-info/METADATA,sha256=_xhdIlmS0XAYJWRI1yjQppksLevhfTX_wFjKzX5hf9Q,43256
|
24
|
-
risk_network-0.0.3b4.dist-info/WHEEL,sha256=HiCZjzuy6Dw0hdX5R3LCFPDmFS4BWl8H-8W39XfmgX4,91
|
25
|
-
risk_network-0.0.3b4.dist-info/top_level.txt,sha256=NX7C2PFKTvC1JhVKv14DFlFAIFnKc6Lpsu1ZfxvQwVw,5
|
26
|
-
risk_network-0.0.3b4.dist-info/RECORD,,
|
File without changes
|
File without changes
|