risk-network 0.0.8b7__py3-none-any.whl → 0.0.8b9__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/network/plot/__init__.py +6 -0
- risk/network/plot/canvas.py +229 -0
- risk/network/plot/contour.py +319 -0
- risk/network/plot/labels.py +848 -0
- risk/network/plot/network.py +269 -0
- risk/network/plot/plotter.py +134 -0
- risk/network/plot/utils.py +153 -0
- risk/risk.py +3 -5
- {risk_network-0.0.8b7.dist-info → risk_network-0.0.8b9.dist-info}/METADATA +1 -1
- {risk_network-0.0.8b7.dist-info → risk_network-0.0.8b9.dist-info}/RECORD +14 -8
- risk/network/plot/base.py +0 -1809
- {risk_network-0.0.8b7.dist-info → risk_network-0.0.8b9.dist-info}/LICENSE +0 -0
- {risk_network-0.0.8b7.dist-info → risk_network-0.0.8b9.dist-info}/WHEEL +0 -0
- {risk_network-0.0.8b7.dist-info → risk_network-0.0.8b9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,269 @@
|
|
1
|
+
"""
|
2
|
+
risk/network/plot/network
|
3
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~
|
4
|
+
"""
|
5
|
+
|
6
|
+
from typing import Any, List, Tuple, Union
|
7
|
+
|
8
|
+
import networkx as nx
|
9
|
+
import numpy as np
|
10
|
+
|
11
|
+
from risk.log import params
|
12
|
+
from risk.network.graph import NetworkGraph
|
13
|
+
from risk.network.plot.utils import to_rgba
|
14
|
+
|
15
|
+
|
16
|
+
class Network:
|
17
|
+
"""Class for plotting nodes and edges in a network graph."""
|
18
|
+
|
19
|
+
def __init__(self, graph: NetworkGraph, ax: Any = None) -> None:
|
20
|
+
"""Initialize the NetworkPlotter class.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
graph (NetworkGraph): The network data and attributes to be visualized.
|
24
|
+
ax (Any, optional): Axes object to plot the network graph. Defaults to None.
|
25
|
+
"""
|
26
|
+
self.graph = graph
|
27
|
+
self.ax = ax
|
28
|
+
|
29
|
+
def plot_network(
|
30
|
+
self,
|
31
|
+
node_size: Union[int, np.ndarray] = 50,
|
32
|
+
node_shape: str = "o",
|
33
|
+
node_edgewidth: float = 1.0,
|
34
|
+
edge_width: float = 1.0,
|
35
|
+
node_color: Union[str, List, Tuple, np.ndarray] = "white",
|
36
|
+
node_edgecolor: Union[str, List, Tuple, np.ndarray] = "black",
|
37
|
+
edge_color: Union[str, List, Tuple, np.ndarray] = "black",
|
38
|
+
node_alpha: Union[float, None] = 1.0,
|
39
|
+
edge_alpha: Union[float, None] = 1.0,
|
40
|
+
) -> None:
|
41
|
+
"""Plot the network graph with customizable node colors, sizes, edge widths, and node edge widths.
|
42
|
+
|
43
|
+
Args:
|
44
|
+
node_size (int or np.ndarray, optional): Size of the nodes. Can be a single integer or an array of sizes. Defaults to 50.
|
45
|
+
node_shape (str, optional): Shape of the nodes. Defaults to "o".
|
46
|
+
node_edgewidth (float, optional): Width of the node edges. Defaults to 1.0.
|
47
|
+
edge_width (float, optional): Width of the edges. Defaults to 1.0.
|
48
|
+
node_color (str, list, tuple, or np.ndarray, optional): Color of the nodes. Can be a single color or an array of colors.
|
49
|
+
Defaults to "white".
|
50
|
+
node_edgecolor (str, list, tuple, or np.ndarray, optional): Color of the node edges. Defaults to "black".
|
51
|
+
edge_color (str, list, tuple, or np.ndarray, optional): Color of the edges. Defaults to "black".
|
52
|
+
node_alpha (float, None, optional): Alpha value (transparency) for the nodes. If provided, it overrides any existing alpha
|
53
|
+
values found in node_color. Defaults to 1.0. Annotated node_color alphas will override this value.
|
54
|
+
edge_alpha (float, None, optional): Alpha value (transparency) for the edges. If provided, it overrides any existing alpha
|
55
|
+
values found in edge_color. Defaults to 1.0.
|
56
|
+
"""
|
57
|
+
# Log the plotting parameters
|
58
|
+
params.log_plotter(
|
59
|
+
network_node_size=(
|
60
|
+
"custom" if isinstance(node_size, np.ndarray) else node_size
|
61
|
+
), # np.ndarray usually indicates custom sizes
|
62
|
+
network_node_shape=node_shape,
|
63
|
+
network_node_edgewidth=node_edgewidth,
|
64
|
+
network_edge_width=edge_width,
|
65
|
+
network_node_color=(
|
66
|
+
"custom" if isinstance(node_color, np.ndarray) else node_color
|
67
|
+
), # np.ndarray usually indicates custom colors
|
68
|
+
network_node_edgecolor=node_edgecolor,
|
69
|
+
network_edge_color=edge_color,
|
70
|
+
network_node_alpha=node_alpha,
|
71
|
+
network_edge_alpha=edge_alpha,
|
72
|
+
)
|
73
|
+
|
74
|
+
# Convert colors to RGBA using the to_rgba helper function
|
75
|
+
# If node_colors was generated using get_annotated_node_colors, its alpha values will override node_alpha
|
76
|
+
node_color = to_rgba(
|
77
|
+
color=node_color, alpha=node_alpha, num_repeats=len(self.graph.network.nodes)
|
78
|
+
)
|
79
|
+
node_edgecolor = to_rgba(
|
80
|
+
color=node_edgecolor, alpha=1.0, num_repeats=len(self.graph.network.nodes)
|
81
|
+
)
|
82
|
+
edge_color = to_rgba(
|
83
|
+
color=edge_color, alpha=edge_alpha, num_repeats=len(self.graph.network.edges)
|
84
|
+
)
|
85
|
+
|
86
|
+
# Extract node coordinates from the network graph
|
87
|
+
node_coordinates = self.graph.node_coordinates
|
88
|
+
|
89
|
+
# Draw the nodes of the graph
|
90
|
+
nx.draw_networkx_nodes(
|
91
|
+
self.graph.network,
|
92
|
+
pos=node_coordinates,
|
93
|
+
node_size=node_size,
|
94
|
+
node_shape=node_shape,
|
95
|
+
node_color=node_color,
|
96
|
+
edgecolors=node_edgecolor,
|
97
|
+
linewidths=node_edgewidth,
|
98
|
+
ax=self.ax,
|
99
|
+
)
|
100
|
+
# Draw the edges of the graph
|
101
|
+
nx.draw_networkx_edges(
|
102
|
+
self.graph.network,
|
103
|
+
pos=node_coordinates,
|
104
|
+
width=edge_width,
|
105
|
+
edge_color=edge_color,
|
106
|
+
ax=self.ax,
|
107
|
+
)
|
108
|
+
|
109
|
+
def plot_subnetwork(
|
110
|
+
self,
|
111
|
+
nodes: Union[List, Tuple, np.ndarray],
|
112
|
+
node_size: Union[int, np.ndarray] = 50,
|
113
|
+
node_shape: str = "o",
|
114
|
+
node_edgewidth: float = 1.0,
|
115
|
+
edge_width: float = 1.0,
|
116
|
+
node_color: Union[str, List, Tuple, np.ndarray] = "white",
|
117
|
+
node_edgecolor: Union[str, List, Tuple, np.ndarray] = "black",
|
118
|
+
edge_color: Union[str, List, Tuple, np.ndarray] = "black",
|
119
|
+
node_alpha: Union[float, None] = None,
|
120
|
+
edge_alpha: Union[float, None] = None,
|
121
|
+
) -> None:
|
122
|
+
"""Plot a subnetwork of selected nodes with customizable node and edge attributes.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
nodes (list, tuple, or np.ndarray): List of node labels to include in the subnetwork. Accepts nested lists.
|
126
|
+
node_size (int or np.ndarray, optional): Size of the nodes. Can be a single integer or an array of sizes. Defaults to 50.
|
127
|
+
node_shape (str, optional): Shape of the nodes. Defaults to "o".
|
128
|
+
node_edgewidth (float, optional): Width of the node edges. Defaults to 1.0.
|
129
|
+
edge_width (float, optional): Width of the edges. Defaults to 1.0.
|
130
|
+
node_color (str, list, tuple, or np.ndarray, optional): Color of the nodes. Defaults to "white".
|
131
|
+
node_edgecolor (str, list, tuple, or np.ndarray, optional): Color of the node edges. Defaults to "black".
|
132
|
+
edge_color (str, list, tuple, or np.ndarray, optional): Color of the edges. Defaults to "black".
|
133
|
+
node_alpha (float, None, optional): Transparency for the nodes. If provided, it overrides any existing alpha values
|
134
|
+
found in node_color. Defaults to 1.0.
|
135
|
+
edge_alpha (float, None, optional): Transparency for the edges. If provided, it overrides any existing alpha values
|
136
|
+
found in node_color. Defaults to 1.0.
|
137
|
+
|
138
|
+
Raises:
|
139
|
+
ValueError: If no valid nodes are found in the network graph.
|
140
|
+
"""
|
141
|
+
# Flatten nested lists of nodes, if necessary
|
142
|
+
if any(isinstance(item, (list, tuple, np.ndarray)) for item in nodes):
|
143
|
+
nodes = [node for sublist in nodes for node in sublist]
|
144
|
+
|
145
|
+
# Filter to get node IDs and their coordinates
|
146
|
+
node_ids = [
|
147
|
+
self.graph.node_label_to_node_id_map.get(node)
|
148
|
+
for node in nodes
|
149
|
+
if node in self.graph.node_label_to_node_id_map
|
150
|
+
]
|
151
|
+
if not node_ids:
|
152
|
+
raise ValueError("No nodes found in the network graph.")
|
153
|
+
|
154
|
+
# Check if node_color is a single color or a list of colors
|
155
|
+
if not isinstance(node_color, (str, tuple, np.ndarray)):
|
156
|
+
node_color = [
|
157
|
+
node_color[nodes.index(node)]
|
158
|
+
for node in nodes
|
159
|
+
if node in self.graph.node_label_to_node_id_map
|
160
|
+
]
|
161
|
+
|
162
|
+
# Convert colors to RGBA using the to_rgba helper function
|
163
|
+
node_color = to_rgba(color=node_color, alpha=node_alpha, num_repeats=len(node_ids))
|
164
|
+
node_edgecolor = to_rgba(color=node_edgecolor, alpha=1.0, num_repeats=len(node_ids))
|
165
|
+
edge_color = to_rgba(
|
166
|
+
color=edge_color, alpha=edge_alpha, num_repeats=len(self.graph.network.edges)
|
167
|
+
)
|
168
|
+
|
169
|
+
# Get the coordinates of the filtered nodes
|
170
|
+
node_coordinates = {node_id: self.graph.node_coordinates[node_id] for node_id in node_ids}
|
171
|
+
|
172
|
+
# Draw the nodes in the subnetwork
|
173
|
+
nx.draw_networkx_nodes(
|
174
|
+
self.graph.network,
|
175
|
+
pos=node_coordinates,
|
176
|
+
nodelist=node_ids,
|
177
|
+
node_size=node_size,
|
178
|
+
node_shape=node_shape,
|
179
|
+
node_color=node_color,
|
180
|
+
edgecolors=node_edgecolor,
|
181
|
+
linewidths=node_edgewidth,
|
182
|
+
ax=self.ax,
|
183
|
+
)
|
184
|
+
# Draw the edges between the specified nodes in the subnetwork
|
185
|
+
subgraph = self.graph.network.subgraph(node_ids)
|
186
|
+
nx.draw_networkx_edges(
|
187
|
+
subgraph,
|
188
|
+
pos=node_coordinates,
|
189
|
+
width=edge_width,
|
190
|
+
edge_color=edge_color,
|
191
|
+
ax=self.ax,
|
192
|
+
)
|
193
|
+
|
194
|
+
def get_annotated_node_colors(
|
195
|
+
self,
|
196
|
+
cmap: str = "gist_rainbow",
|
197
|
+
color: Union[str, None] = None,
|
198
|
+
min_scale: float = 0.8,
|
199
|
+
max_scale: float = 1.0,
|
200
|
+
scale_factor: float = 1.0,
|
201
|
+
alpha: Union[float, None] = 1.0,
|
202
|
+
nonenriched_color: Union[str, List, Tuple, np.ndarray] = "white",
|
203
|
+
nonenriched_alpha: Union[float, None] = 1.0,
|
204
|
+
random_seed: int = 888,
|
205
|
+
) -> np.ndarray:
|
206
|
+
"""Adjust the colors of nodes in the network graph based on enrichment.
|
207
|
+
|
208
|
+
Args:
|
209
|
+
cmap (str, optional): Colormap to use for coloring the nodes. Defaults to "gist_rainbow".
|
210
|
+
color (str or None, optional): Color to use for the nodes. If None, the colormap will be used. Defaults to None.
|
211
|
+
min_scale (float, optional): Minimum scale for color intensity. Defaults to 0.8.
|
212
|
+
max_scale (float, optional): Maximum scale for color intensity. Defaults to 1.0.
|
213
|
+
scale_factor (float, optional): Factor for adjusting the color scaling intensity. Defaults to 1.0.
|
214
|
+
alpha (float, None, optional): Alpha value for enriched nodes. If provided, it overrides any existing alpha values
|
215
|
+
found in color. Defaults to 1.0.
|
216
|
+
nonenriched_color (str, list, tuple, or np.ndarray, optional): Color for non-enriched nodes. Defaults to "white".
|
217
|
+
nonenriched_alpha (float, None, optional): Alpha value for non-enriched nodes. If provided, it overrides any existing
|
218
|
+
alpha values found in nonenriched_color. Defaults to 1.0.
|
219
|
+
random_seed (int, optional): Seed for random number generation. Defaults to 888.
|
220
|
+
|
221
|
+
Returns:
|
222
|
+
np.ndarray: Array of RGBA colors adjusted for enrichment status.
|
223
|
+
"""
|
224
|
+
# Get the initial domain colors for each node, which are returned as RGBA
|
225
|
+
network_colors = self.graph.get_domain_colors(
|
226
|
+
cmap=cmap,
|
227
|
+
color=color,
|
228
|
+
min_scale=min_scale,
|
229
|
+
max_scale=max_scale,
|
230
|
+
scale_factor=scale_factor,
|
231
|
+
random_seed=random_seed,
|
232
|
+
)
|
233
|
+
# Apply the alpha value for enriched nodes
|
234
|
+
network_colors[:, 3] = alpha # Apply the alpha value to the enriched nodes' A channel
|
235
|
+
# Convert the non-enriched color to RGBA using the to_rgba helper function
|
236
|
+
nonenriched_color = to_rgba(color=nonenriched_color, alpha=nonenriched_alpha)
|
237
|
+
# Adjust node colors: replace any fully black nodes (RGB == 0) with the non-enriched color and its alpha
|
238
|
+
adjusted_network_colors = np.where(
|
239
|
+
np.all(network_colors[:, :3] == 0, axis=1, keepdims=True), # Check RGB values only
|
240
|
+
np.array(nonenriched_color), # Apply the non-enriched color with alpha
|
241
|
+
network_colors, # Keep the original colors for enriched nodes
|
242
|
+
)
|
243
|
+
return adjusted_network_colors
|
244
|
+
|
245
|
+
def get_annotated_node_sizes(
|
246
|
+
self, enriched_size: int = 50, nonenriched_size: int = 25
|
247
|
+
) -> np.ndarray:
|
248
|
+
"""Adjust the sizes of nodes in the network graph based on whether they are enriched or not.
|
249
|
+
|
250
|
+
Args:
|
251
|
+
enriched_size (int): Size for enriched nodes. Defaults to 50.
|
252
|
+
nonenriched_size (int): Size for non-enriched nodes. Defaults to 25.
|
253
|
+
|
254
|
+
Returns:
|
255
|
+
np.ndarray: Array of node sizes, with enriched nodes larger than non-enriched ones.
|
256
|
+
"""
|
257
|
+
# Merge all enriched nodes from the domain_id_to_node_ids_map dictionary
|
258
|
+
enriched_nodes = set()
|
259
|
+
for _, node_ids in self.graph.domain_id_to_node_ids_map.items():
|
260
|
+
enriched_nodes.update(node_ids)
|
261
|
+
|
262
|
+
# Initialize all node sizes to the non-enriched size
|
263
|
+
node_sizes = np.full(len(self.graph.network.nodes), nonenriched_size)
|
264
|
+
# Set the size for enriched nodes
|
265
|
+
for node in enriched_nodes:
|
266
|
+
if node in self.graph.network.nodes:
|
267
|
+
node_sizes[node] = enriched_size
|
268
|
+
|
269
|
+
return node_sizes
|
@@ -0,0 +1,134 @@
|
|
1
|
+
"""
|
2
|
+
risk/network/plot/plotter
|
3
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~
|
4
|
+
"""
|
5
|
+
|
6
|
+
from typing import List, Tuple, Union
|
7
|
+
|
8
|
+
import matplotlib.pyplot as plt
|
9
|
+
import numpy as np
|
10
|
+
|
11
|
+
from risk.log import params
|
12
|
+
from risk.network.graph import NetworkGraph
|
13
|
+
from risk.network.plot.canvas import Canvas
|
14
|
+
from risk.network.plot.contour import Contour
|
15
|
+
from risk.network.plot.labels import Labels
|
16
|
+
from risk.network.plot.network import Network
|
17
|
+
from risk.network.plot.utils import calculate_bounding_box, to_rgba
|
18
|
+
|
19
|
+
|
20
|
+
class NetworkPlotter(Canvas, Network, Contour, Labels):
|
21
|
+
"""A class for visualizing network graphs with customizable options.
|
22
|
+
|
23
|
+
The NetworkPlotter class uses a NetworkGraph object and provides methods to plot the network with
|
24
|
+
flexible node and edge properties. It also supports plotting labels, contours, drawing the network's
|
25
|
+
perimeter, and adjusting background colors.
|
26
|
+
"""
|
27
|
+
|
28
|
+
def __init__(
|
29
|
+
self,
|
30
|
+
graph: NetworkGraph,
|
31
|
+
figsize: Tuple = (10, 10),
|
32
|
+
background_color: Union[str, List, Tuple, np.ndarray] = "white",
|
33
|
+
background_alpha: Union[float, None] = 1.0,
|
34
|
+
pad: float = 0.3,
|
35
|
+
) -> None:
|
36
|
+
"""Initialize the NetworkPlotter with a NetworkGraph object and plotting parameters.
|
37
|
+
|
38
|
+
Args:
|
39
|
+
graph (NetworkGraph): The network data and attributes to be visualized.
|
40
|
+
figsize (tuple, optional): Size of the figure in inches (width, height). Defaults to (10, 10).
|
41
|
+
background_color (str, list, tuple, np.ndarray, optional): Background color of the plot. Defaults to "white".
|
42
|
+
background_alpha (float, None, optional): Transparency level of the background color. If provided, it overrides
|
43
|
+
any existing alpha values found in background_color. Defaults to 1.0.
|
44
|
+
pad (float, optional): Padding value to adjust the axis limits. Defaults to 0.3.
|
45
|
+
"""
|
46
|
+
self.graph = graph
|
47
|
+
# Initialize the plot with the specified parameters
|
48
|
+
self.ax = self._initialize_plot(
|
49
|
+
graph=graph,
|
50
|
+
figsize=figsize,
|
51
|
+
background_color=background_color,
|
52
|
+
background_alpha=background_alpha,
|
53
|
+
pad=pad,
|
54
|
+
)
|
55
|
+
super().__init__(graph=graph, ax=self.ax)
|
56
|
+
|
57
|
+
def _initialize_plot(
|
58
|
+
self,
|
59
|
+
graph: NetworkGraph,
|
60
|
+
figsize: Tuple,
|
61
|
+
background_color: Union[str, List, Tuple, np.ndarray],
|
62
|
+
background_alpha: Union[float, None],
|
63
|
+
pad: float,
|
64
|
+
) -> plt.Axes:
|
65
|
+
"""Set up the plot with figure size and background color.
|
66
|
+
|
67
|
+
Args:
|
68
|
+
graph (NetworkGraph): The network data and attributes to be visualized.
|
69
|
+
figsize (tuple): Size of the figure in inches (width, height).
|
70
|
+
background_color (str): Background color of the plot.
|
71
|
+
background_alpha (float, None, optional): Transparency level of the background color. If provided, it overrides any
|
72
|
+
existing alpha values found in background_color.
|
73
|
+
pad (float, optional): Padding value to adjust the axis limits.
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
plt.Axes: The axis object for the plot.
|
77
|
+
"""
|
78
|
+
# Log the plotter settings
|
79
|
+
params.log_plotter(
|
80
|
+
figsize=figsize,
|
81
|
+
background_color=background_color,
|
82
|
+
background_alpha=background_alpha,
|
83
|
+
pad=pad,
|
84
|
+
)
|
85
|
+
|
86
|
+
# Extract node coordinates from the network graph
|
87
|
+
node_coordinates = graph.node_coordinates
|
88
|
+
# Calculate the center and radius of the bounding box around the network
|
89
|
+
center, radius = calculate_bounding_box(node_coordinates)
|
90
|
+
|
91
|
+
# Create a new figure and axis for plotting
|
92
|
+
fig, ax = plt.subplots(figsize=figsize)
|
93
|
+
fig.tight_layout() # Adjust subplot parameters to give specified padding
|
94
|
+
# Set axis limits based on the calculated bounding box and radius
|
95
|
+
ax.set_xlim([center[0] - radius - pad, center[0] + radius + pad])
|
96
|
+
ax.set_ylim([center[1] - radius - pad, center[1] + radius + pad])
|
97
|
+
ax.set_aspect("equal") # Ensure the aspect ratio is equal
|
98
|
+
|
99
|
+
# Set the background color of the plot
|
100
|
+
# Convert color to RGBA using the to_rgba helper function
|
101
|
+
fig.patch.set_facecolor(to_rgba(color=background_color, alpha=background_alpha))
|
102
|
+
ax.invert_yaxis() # Invert the y-axis to match typical image coordinates
|
103
|
+
# Remove axis spines for a cleaner look
|
104
|
+
for spine in ax.spines.values():
|
105
|
+
spine.set_visible(False)
|
106
|
+
|
107
|
+
# Hide axis ticks and labels
|
108
|
+
ax.set_xticks([])
|
109
|
+
ax.set_yticks([])
|
110
|
+
ax.patch.set_visible(False) # Hide the axis background
|
111
|
+
|
112
|
+
return ax
|
113
|
+
|
114
|
+
@staticmethod
|
115
|
+
def savefig(*args, pad_inches: float = 0.5, dpi: int = 100, **kwargs) -> None:
|
116
|
+
"""Save the current plot to a file with additional export options.
|
117
|
+
|
118
|
+
Args:
|
119
|
+
*args: Positional arguments passed to `plt.savefig`.
|
120
|
+
pad_inches (float, optional): Padding around the figure when saving. Defaults to 0.5.
|
121
|
+
dpi (int, optional): Dots per inch (DPI) for the exported image. Defaults to 300.
|
122
|
+
**kwargs: Keyword arguments passed to `plt.savefig`, such as filename and format.
|
123
|
+
"""
|
124
|
+
plt.savefig(*args, bbox_inches="tight", pad_inches=pad_inches, dpi=dpi, **kwargs)
|
125
|
+
|
126
|
+
@staticmethod
|
127
|
+
def show(*args, **kwargs) -> None:
|
128
|
+
"""Display the current plot.
|
129
|
+
|
130
|
+
Args:
|
131
|
+
*args: Positional arguments passed to `plt.show`.
|
132
|
+
**kwargs: Keyword arguments passed to `plt.show`.
|
133
|
+
"""
|
134
|
+
plt.show(*args, **kwargs)
|
@@ -0,0 +1,153 @@
|
|
1
|
+
"""
|
2
|
+
risk/network/plot/utils
|
3
|
+
~~~~~~~~~~~~~~~~~~~~~~~
|
4
|
+
"""
|
5
|
+
|
6
|
+
from typing import List, Tuple, Union
|
7
|
+
|
8
|
+
import matplotlib.colors as mcolors
|
9
|
+
import numpy as np
|
10
|
+
|
11
|
+
from risk.network.graph import NetworkGraph
|
12
|
+
|
13
|
+
|
14
|
+
def get_annotated_domain_colors(
|
15
|
+
graph: NetworkGraph,
|
16
|
+
cmap: str = "gist_rainbow",
|
17
|
+
color: Union[str, None] = None,
|
18
|
+
min_scale: float = 0.8,
|
19
|
+
max_scale: float = 1.0,
|
20
|
+
scale_factor: float = 1.0,
|
21
|
+
random_seed: int = 888,
|
22
|
+
) -> np.ndarray:
|
23
|
+
"""Get colors for the domains based on node annotations, or use a specified color.
|
24
|
+
|
25
|
+
Args:
|
26
|
+
graph (NetworkGraph): The network data and attributes to be visualized.
|
27
|
+
cmap (str, optional): Colormap to use for generating domain colors. Defaults to "gist_rainbow".
|
28
|
+
color (str or None, optional): Color to use for the domains. If None, the colormap will be used. Defaults to None.
|
29
|
+
min_scale (float, optional): Minimum scale for color intensity when generating domain colors.
|
30
|
+
Defaults to 0.8.
|
31
|
+
max_scale (float, optional): Maximum scale for color intensity when generating domain colors.
|
32
|
+
Defaults to 1.0.
|
33
|
+
scale_factor (float, optional): Factor for adjusting the contrast in the colors generated based on
|
34
|
+
enrichment. Higher values increase the contrast. Defaults to 1.0.
|
35
|
+
random_seed (int, optional): Seed for random number generation to ensure reproducibility. Defaults to 888.
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
np.ndarray: Array of RGBA colors for each domain.
|
39
|
+
"""
|
40
|
+
# Generate domain colors based on the enrichment data
|
41
|
+
node_colors = graph.get_domain_colors(
|
42
|
+
cmap=cmap,
|
43
|
+
color=color,
|
44
|
+
min_scale=min_scale,
|
45
|
+
max_scale=max_scale,
|
46
|
+
scale_factor=scale_factor,
|
47
|
+
random_seed=random_seed,
|
48
|
+
)
|
49
|
+
annotated_colors = []
|
50
|
+
for _, node_ids in graph.domain_id_to_node_ids_map.items():
|
51
|
+
if len(node_ids) > 1:
|
52
|
+
# For multi-node domains, choose the brightest color based on RGB sum
|
53
|
+
domain_colors = np.array([node_colors[node] for node in node_ids])
|
54
|
+
brightest_color = domain_colors[
|
55
|
+
np.argmax(domain_colors[:, :3].sum(axis=1)) # Sum the RGB values
|
56
|
+
]
|
57
|
+
annotated_colors.append(brightest_color)
|
58
|
+
else:
|
59
|
+
# Single-node domains default to white (RGBA)
|
60
|
+
default_color = np.array([1.0, 1.0, 1.0, 1.0])
|
61
|
+
annotated_colors.append(default_color)
|
62
|
+
|
63
|
+
return np.array(annotated_colors)
|
64
|
+
|
65
|
+
|
66
|
+
def calculate_bounding_box(
|
67
|
+
node_coordinates: np.ndarray, radius_margin: float = 1.05
|
68
|
+
) -> Tuple[np.ndarray, float]:
|
69
|
+
"""Calculate the bounding box of the network based on node coordinates.
|
70
|
+
|
71
|
+
Args:
|
72
|
+
node_coordinates (np.ndarray): Array of node coordinates (x, y).
|
73
|
+
radius_margin (float, optional): Margin factor to apply to the bounding box radius. Defaults to 1.05.
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
tuple: Center of the bounding box and the radius (adjusted by the radius margin).
|
77
|
+
"""
|
78
|
+
# Find minimum and maximum x, y coordinates
|
79
|
+
x_min, y_min = np.min(node_coordinates, axis=0)
|
80
|
+
x_max, y_max = np.max(node_coordinates, axis=0)
|
81
|
+
# Calculate the center of the bounding box
|
82
|
+
center = np.array([(x_min + x_max) / 2, (y_min + y_max) / 2])
|
83
|
+
# Calculate the radius of the bounding box, adjusted by the margin
|
84
|
+
radius = max(x_max - x_min, y_max - y_min) / 2 * radius_margin
|
85
|
+
return center, radius
|
86
|
+
|
87
|
+
|
88
|
+
def to_rgba(
|
89
|
+
color: Union[str, List, Tuple, np.ndarray],
|
90
|
+
alpha: Union[float, None] = None,
|
91
|
+
num_repeats: Union[int, None] = None,
|
92
|
+
) -> np.ndarray:
|
93
|
+
"""Convert color(s) to RGBA format, applying alpha and repeating as needed.
|
94
|
+
|
95
|
+
Args:
|
96
|
+
color (Union[str, list, tuple, np.ndarray]): The color(s) to convert. Can be a string, list, tuple, or np.ndarray.
|
97
|
+
alpha (float, None, optional): Alpha value (transparency) to apply. If provided, it overrides any existing alpha values
|
98
|
+
found in color.
|
99
|
+
num_repeats (int, None, optional): If provided, the color(s) will be repeated this many times. Defaults to None.
|
100
|
+
|
101
|
+
Returns:
|
102
|
+
np.ndarray: Array of RGBA colors repeated `num_repeats` times, if applicable.
|
103
|
+
"""
|
104
|
+
|
105
|
+
def convert_to_rgba(c: Union[str, List, Tuple, np.ndarray]) -> np.ndarray:
|
106
|
+
"""Convert a single color to RGBA format, handling strings, hex, and RGB/RGBA lists."""
|
107
|
+
# Note: if no alpha is provided, the default alpha value is 1.0 by mcolors.to_rgba
|
108
|
+
if isinstance(c, str):
|
109
|
+
# Convert color names or hex values (e.g., 'red', '#FF5733') to RGBA
|
110
|
+
rgba = np.array(mcolors.to_rgba(c))
|
111
|
+
elif isinstance(c, (list, tuple, np.ndarray)) and len(c) in [3, 4]:
|
112
|
+
# Convert RGB (3) or RGBA (4) values to RGBA format
|
113
|
+
rgba = np.array(mcolors.to_rgba(c))
|
114
|
+
else:
|
115
|
+
raise ValueError(
|
116
|
+
f"Invalid color format: {c}. Must be a valid string or RGB/RGBA sequence."
|
117
|
+
)
|
118
|
+
|
119
|
+
if alpha is not None: # Override alpha if provided
|
120
|
+
rgba[3] = alpha
|
121
|
+
return rgba
|
122
|
+
|
123
|
+
# If color is a 2D array of RGBA values, convert it to a list of lists
|
124
|
+
if isinstance(color, np.ndarray) and color.ndim == 2 and color.shape[1] == 4:
|
125
|
+
color = [list(c) for c in color]
|
126
|
+
|
127
|
+
# Handle a single color (string or RGB/RGBA list/tuple)
|
128
|
+
if isinstance(color, (str, list, tuple)) and not any(
|
129
|
+
isinstance(c, (list, tuple, np.ndarray)) for c in color
|
130
|
+
):
|
131
|
+
rgba_color = convert_to_rgba(color)
|
132
|
+
if num_repeats:
|
133
|
+
return np.tile(
|
134
|
+
rgba_color, (num_repeats, 1)
|
135
|
+
) # Repeat the color if num_repeats is provided
|
136
|
+
return np.array([rgba_color]) # Return a single color wrapped in a numpy array
|
137
|
+
|
138
|
+
# Handle a list/array of colors
|
139
|
+
elif isinstance(color, (list, tuple, np.ndarray)):
|
140
|
+
rgba_colors = np.array(
|
141
|
+
[convert_to_rgba(c) for c in color]
|
142
|
+
) # Convert each color in the list to RGBA
|
143
|
+
# Handle repetition if num_repeats is provided
|
144
|
+
if num_repeats:
|
145
|
+
repeated_colors = np.array(
|
146
|
+
[rgba_colors[i % len(rgba_colors)] for i in range(num_repeats)]
|
147
|
+
)
|
148
|
+
return repeated_colors
|
149
|
+
|
150
|
+
return rgba_colors
|
151
|
+
|
152
|
+
else:
|
153
|
+
raise ValueError("Color must be a valid RGB/RGBA or array of RGB/RGBA colors.")
|
risk/risk.py
CHANGED
@@ -356,6 +356,7 @@ class RISK(NetworkIO, AnnotationsIO):
|
|
356
356
|
figsize: Tuple = (10, 10),
|
357
357
|
background_color: str = "white",
|
358
358
|
background_alpha: Union[float, None] = 1.0,
|
359
|
+
pad: float = 0.3,
|
359
360
|
) -> NetworkPlotter:
|
360
361
|
"""Get a NetworkPlotter object for plotting.
|
361
362
|
|
@@ -365,16 +366,12 @@ class RISK(NetworkIO, AnnotationsIO):
|
|
365
366
|
background_color (str, optional): Background color of the plot. Defaults to "white".
|
366
367
|
background_alpha (float, None, optional): Transparency level of the background color. If provided, it overrides
|
367
368
|
any existing alpha values found in background_color. Defaults to 1.0.
|
369
|
+
pad (float, optional): Padding value to adjust the axis limits. Defaults to 0.3.
|
368
370
|
|
369
371
|
Returns:
|
370
372
|
NetworkPlotter: A NetworkPlotter object configured with the given parameters.
|
371
373
|
"""
|
372
374
|
log_header("Loading plotter")
|
373
|
-
# Log the plotter settings
|
374
|
-
params.log_plotter(
|
375
|
-
figsize=figsize,
|
376
|
-
background_color=background_color,
|
377
|
-
)
|
378
375
|
|
379
376
|
# Initialize and return a NetworkPlotter object
|
380
377
|
return NetworkPlotter(
|
@@ -382,6 +379,7 @@ class RISK(NetworkIO, AnnotationsIO):
|
|
382
379
|
figsize=figsize,
|
383
380
|
background_color=background_color,
|
384
381
|
background_alpha=background_alpha,
|
382
|
+
pad=pad,
|
385
383
|
)
|
386
384
|
|
387
385
|
def _load_neighborhoods(
|
@@ -1,6 +1,6 @@
|
|
1
|
-
risk/__init__.py,sha256=
|
1
|
+
risk/__init__.py,sha256=ZdYPjV9cVMzz6tSQJbYp9MnzLO53YJLS50zbeWZ1SSI,112
|
2
2
|
risk/constants.py,sha256=XInRaH78Slnw_sWgAsBFbUHkyA0h0jL0DKGuQNbOvjM,550
|
3
|
-
risk/risk.py,sha256=
|
3
|
+
risk/risk.py,sha256=slJXca_a726_D7oXwe765HaKTv3ZrOvhttyrWdCGPkA,21231
|
4
4
|
risk/annotations/__init__.py,sha256=vUpVvMRE5if01Ic8QY6M2Ae3EFGJHdugEe9PdEkAW4Y,138
|
5
5
|
risk/annotations/annotations.py,sha256=ySc_N3nXnKx5RnOpFaEkM6zvTbswbrRcfFLzM0KdOck,11391
|
6
6
|
risk/annotations/io.py,sha256=TTXVJQgUGAlKpnGBcx7Dow146IGyozA03nSbl3S7M5M,9475
|
@@ -15,7 +15,13 @@ risk/network/__init__.py,sha256=iEPeJdZfqp0toxtbElryB8jbz9_t_k4QQ3iDvKE8C_0,126
|
|
15
15
|
risk/network/geometry.py,sha256=H1yGVVqgbfpzBzJwEheDLfvGLSA284jGQQTn612L4Vc,6759
|
16
16
|
risk/network/graph.py,sha256=EwD4-1THC5YNdP6PY01Oe35k2QYYqtZpxWraPVH6wa4,16426
|
17
17
|
risk/network/io.py,sha256=kY7HqmL3wa1NnqHu61_G8IpT21qpBijpAZ4ixmsseJA,22911
|
18
|
-
risk/network/plot/
|
18
|
+
risk/network/plot/__init__.py,sha256=MfmaXJgAZJgXZ2wrhK8pXwzETlcMaLChhWXKAozniAo,98
|
19
|
+
risk/network/plot/canvas.py,sha256=-Y2shCy4Udp-stB9tBXGZRTASQZiv8RVqVcQ5lBhVu0,10291
|
20
|
+
risk/network/plot/contour.py,sha256=YPG8Uz0VlJ4skLdGaTH_FmQN6A_ArK8XSTNo1LzkSws,14276
|
21
|
+
risk/network/plot/labels.py,sha256=o_V_eWQZB_otjXpw6aAwEPp1Uu-auQNcxQYpGBOL7uU,40777
|
22
|
+
risk/network/plot/network.py,sha256=83ZXjGGrgRprWvDldWfhRe6SFXTv_QoI20OWzyEmVJU,12593
|
23
|
+
risk/network/plot/plotter.py,sha256=rQV4Db6Ud86FJm11uaBvgSuzpmGsrZxnsRnUKjg6w84,5572
|
24
|
+
risk/network/plot/utils.py,sha256=jZgI8EysSjviQmdYAceZk2MwJXcdeFAkYp-odZNqV0k,6316
|
19
25
|
risk/stats/__init__.py,sha256=WcgoETQ-hS0LQqKRsAMIPtP15xZ-4eul6VUBuUx4Wzc,220
|
20
26
|
risk/stats/hypergeom.py,sha256=o6Qnj31gCAKxr2uQirXrbv7XvdDJGEq69MFW-ubx_hA,2272
|
21
27
|
risk/stats/poisson.py,sha256=8x9hB4DCukq4gNIlIKO-c_jYG1-BTwTX53oLauFyfj8,1793
|
@@ -23,8 +29,8 @@ risk/stats/stats.py,sha256=kvShov-94W6ffgDUTb522vB9hDJQSyTsYif_UIaFfSM,7059
|
|
23
29
|
risk/stats/permutation/__init__.py,sha256=neJp7FENC-zg_CGOXqv-iIvz1r5XUKI9Ruxhmq7kDOI,105
|
24
30
|
risk/stats/permutation/permutation.py,sha256=D84Rcpt6iTQniK0PfQGcw9bLcHbMt9p-ARcurUnIXZQ,10095
|
25
31
|
risk/stats/permutation/test_functions.py,sha256=lftOude6hee0pyR80HlBD32522JkDoN5hrKQ9VEbuoY,2345
|
26
|
-
risk_network-0.0.
|
27
|
-
risk_network-0.0.
|
28
|
-
risk_network-0.0.
|
29
|
-
risk_network-0.0.
|
30
|
-
risk_network-0.0.
|
32
|
+
risk_network-0.0.8b9.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
33
|
+
risk_network-0.0.8b9.dist-info/METADATA,sha256=Sq_d-xGJT_RHwo6lxwl0s9ydoIeNTRW-1vrG1V-NknA,47450
|
34
|
+
risk_network-0.0.8b9.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
35
|
+
risk_network-0.0.8b9.dist-info/top_level.txt,sha256=NX7C2PFKTvC1JhVKv14DFlFAIFnKc6Lpsu1ZfxvQwVw,5
|
36
|
+
risk_network-0.0.8b9.dist-info/RECORD,,
|