risk-network 0.0.7b1__tar.gz → 0.0.7b3__tar.gz
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_network-0.0.7b1 → risk_network-0.0.7b3}/PKG-INFO +1 -1
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/__init__.py +1 -1
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/network/graph.py +101 -39
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk_network.egg-info/PKG-INFO +1 -1
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/LICENSE +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/MANIFEST.in +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/README.md +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/pyproject.toml +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/annotations/__init__.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/annotations/annotations.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/annotations/io.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/constants.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/log/__init__.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/log/console.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/log/params.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/neighborhoods/__init__.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/neighborhoods/community.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/neighborhoods/domains.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/neighborhoods/neighborhoods.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/network/__init__.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/network/geometry.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/network/io.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/network/plot.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/risk.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/stats/__init__.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/stats/fisher_exact.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/stats/hypergeom.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/stats/permutation/__init__.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/stats/permutation/permutation.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/stats/permutation/test_functions.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk/stats/stats.py +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk_network.egg-info/SOURCES.txt +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk_network.egg-info/dependency_links.txt +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk_network.egg-info/requires.txt +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/risk_network.egg-info/top_level.txt +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/setup.cfg +0 -0
- {risk_network-0.0.7b1 → risk_network-0.0.7b3}/setup.py +0 -0
@@ -55,10 +55,9 @@ class NetworkGraph:
|
|
55
55
|
self.node_label_to_node_id_map = node_label_to_node_id_map
|
56
56
|
# NOTE: Below this point, instance attributes (i.e., self) will be used!
|
57
57
|
self.domain_id_to_node_labels_map = self._create_domain_id_to_node_labels_map()
|
58
|
-
#
|
59
|
-
self.network =
|
60
|
-
self.node_coordinates =
|
61
|
-
self._initialize_network(network)
|
58
|
+
# Unfold the network's 3D coordinates to 2D and extract node coordinates
|
59
|
+
self.network = _unfold_sphere_to_plane(network)
|
60
|
+
self.node_coordinates = _extract_node_coordinates(self.network)
|
62
61
|
|
63
62
|
def _create_domain_id_to_node_ids_map(self, domains: pd.DataFrame) -> Dict[str, Any]:
|
64
63
|
"""Create a mapping from domains to the list of node IDs belonging to each domain.
|
@@ -109,19 +108,6 @@ class NetworkGraph:
|
|
109
108
|
|
110
109
|
return domain_id_to_label_map
|
111
110
|
|
112
|
-
def _initialize_network(self, G: nx.Graph) -> None:
|
113
|
-
"""Initialize the network by unfolding it and extracting node coordinates.
|
114
|
-
|
115
|
-
Args:
|
116
|
-
G (nx.Graph): The input network graph with 3D node coordinates.
|
117
|
-
"""
|
118
|
-
# Unfold the network's 3D coordinates to 2D
|
119
|
-
G_2d = _unfold_sphere_to_plane(G)
|
120
|
-
# Assign the unfolded graph to self.network
|
121
|
-
self.network = G_2d
|
122
|
-
# Extract 2D coordinates of nodes
|
123
|
-
self.node_coordinates = _extract_node_coordinates(G_2d)
|
124
|
-
|
125
111
|
def get_domain_colors(
|
126
112
|
self,
|
127
113
|
cmap: str = "gist_rainbow",
|
@@ -200,14 +186,15 @@ class NetworkGraph:
|
|
200
186
|
Returns:
|
201
187
|
dict: A dictionary mapping domain keys to their corresponding RGBA colors.
|
202
188
|
"""
|
203
|
-
#
|
204
|
-
numeric_domains = [
|
205
|
-
col for col in self.domains.columns if isinstance(col, (int, np.integer))
|
206
|
-
]
|
207
|
-
domains = np.sort(numeric_domains)
|
189
|
+
# Get colors for each domain based on node positions
|
208
190
|
domain_colors = _get_colors(
|
209
|
-
|
191
|
+
self.network,
|
192
|
+
self.domain_id_to_node_ids_map,
|
193
|
+
cmap=cmap,
|
194
|
+
color=color,
|
195
|
+
random_seed=random_seed,
|
210
196
|
)
|
197
|
+
self.network, self.domain_id_to_node_ids_map
|
211
198
|
return dict(zip(self.domain_id_to_node_ids_map.keys(), domain_colors))
|
212
199
|
|
213
200
|
|
@@ -300,35 +287,110 @@ def _extract_node_coordinates(G: nx.Graph) -> np.ndarray:
|
|
300
287
|
|
301
288
|
|
302
289
|
def _get_colors(
|
303
|
-
|
290
|
+
network,
|
291
|
+
domain_id_to_node_ids_map,
|
304
292
|
cmap: str = "gist_rainbow",
|
305
293
|
color: Union[str, None] = None,
|
306
294
|
random_seed: int = 888,
|
307
295
|
) -> List[Tuple]:
|
308
|
-
"""Generate a list of RGBA colors
|
296
|
+
"""Generate a list of RGBA colors based on domain centroids, ensuring that domains
|
297
|
+
close in space get maximally separated colors, while keeping some randomness.
|
309
298
|
|
310
299
|
Args:
|
311
|
-
|
300
|
+
network (NetworkX graph): The graph representing the network.
|
301
|
+
domain_id_to_node_ids_map (dict): Mapping from domain IDs to lists of node IDs.
|
312
302
|
cmap (str, optional): The name of the colormap to use. Defaults to "gist_rainbow".
|
313
303
|
color (str or None, optional): A specific color to use for all generated colors.
|
314
304
|
random_seed (int): Seed for random number generation. Defaults to 888.
|
315
|
-
Defaults to None.
|
316
305
|
|
317
306
|
Returns:
|
318
|
-
|
307
|
+
List[Tuple]: List of RGBA colors.
|
319
308
|
"""
|
320
309
|
# Set random seed for reproducibility
|
321
310
|
random.seed(random_seed)
|
311
|
+
# Determine the number of colors to generate based on the number of domains
|
312
|
+
num_colors_to_generate = len(domain_id_to_node_ids_map)
|
322
313
|
if color:
|
323
|
-
#
|
314
|
+
# Generate all colors as the same specified color
|
324
315
|
rgba = matplotlib.colors.to_rgba(color)
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
316
|
+
return [rgba] * num_colors_to_generate
|
317
|
+
|
318
|
+
# Load colormap
|
319
|
+
colormap = matplotlib.colormaps.get_cmap(cmap)
|
320
|
+
# Step 1: Calculate centroids for each domain
|
321
|
+
centroids = _calculate_centroids(network, domain_id_to_node_ids_map)
|
322
|
+
# Step 2: Calculate pairwise distances between centroids
|
323
|
+
centroid_array = np.array(centroids)
|
324
|
+
dist_matrix = np.linalg.norm(centroid_array[:, None] - centroid_array, axis=-1)
|
325
|
+
|
326
|
+
# Step 3: Generate positions in the colormap, with a focus on centroids that are close
|
327
|
+
remaining_indices = set(range(num_colors_to_generate))
|
328
|
+
# Assign distant colors to close centroids
|
329
|
+
color_positions = _assign_distant_colors(
|
330
|
+
remaining_indices, dist_matrix, colormap, num_colors_to_generate
|
331
|
+
)
|
332
|
+
|
333
|
+
# Step 4: Randomly shuffle color positions to generate a new color palette
|
334
|
+
# while maintaining the dissimilarity between neighboring colors. This shuffling
|
335
|
+
# preserves the relative distances between centroids, ensuring that close centroids
|
336
|
+
# remain visually distinct while introducing randomness into the overall color arrangement.
|
337
|
+
random.shuffle(color_positions)
|
338
|
+
# Ensure that all positions remain between 0 and 1
|
339
|
+
color_positions = np.clip(color_positions, 0, 1)
|
340
|
+
|
341
|
+
# Step 5: Generate colors based on positions
|
342
|
+
return [colormap(pos) for pos in color_positions]
|
343
|
+
|
344
|
+
|
345
|
+
def _calculate_centroids(network, domain_id_to_node_ids_map):
|
346
|
+
"""Calculate the centroid for each domain based on node x and y coordinates in the network.
|
347
|
+
|
348
|
+
Args:
|
349
|
+
network (NetworkX graph): The graph representing the network.
|
350
|
+
domain_id_to_node_ids_map (dict): Mapping from domain IDs to lists of node IDs.
|
351
|
+
|
352
|
+
Returns:
|
353
|
+
List[Tuple[float, float]]: List of centroids (x, y) for each domain.
|
354
|
+
"""
|
355
|
+
centroids = []
|
356
|
+
for domain_id, node_ids in domain_id_to_node_ids_map.items():
|
357
|
+
# Extract x and y coordinates from the network nodes
|
358
|
+
node_positions = np.array(
|
359
|
+
[[network.nodes[node_id]["x"], network.nodes[node_id]["y"]] for node_id in node_ids]
|
360
|
+
)
|
361
|
+
# Compute the centroid as the mean of the x and y coordinates
|
362
|
+
centroid = np.mean(node_positions, axis=0)
|
363
|
+
centroids.append(tuple(centroid))
|
364
|
+
|
365
|
+
return centroids
|
366
|
+
|
367
|
+
|
368
|
+
def _assign_distant_colors(remaining_indices, dist_matrix, colormap, num_colors_to_generate):
|
369
|
+
"""Assign colors to centroids that are close in space, ensuring stark color differences.
|
370
|
+
|
371
|
+
Args:
|
372
|
+
remaining_indices (set): Indices of centroids left to color.
|
373
|
+
dist_matrix (ndarray): Matrix of pairwise centroid distances.
|
374
|
+
colormap (Colormap): The colormap used to assign colors.
|
375
|
+
num_colors_to_generate (int): Number of colors to generate.
|
376
|
+
|
377
|
+
Returns:
|
378
|
+
np.array: Array of color positions in the colormap.
|
379
|
+
"""
|
380
|
+
color_positions = np.zeros(num_colors_to_generate)
|
381
|
+
# Convert the set to a list to index over it
|
382
|
+
remaining_indices = list(remaining_indices)
|
383
|
+
# Sort remaining indices by centroid proximity (based on sum of distances to others)
|
384
|
+
proximity_order = sorted(remaining_indices, key=lambda idx: np.sum(dist_matrix[idx]))
|
385
|
+
# Assign colors starting with the most distant points in proximity order
|
386
|
+
for i, idx in enumerate(proximity_order):
|
387
|
+
color_positions[idx] = i / num_colors_to_generate
|
388
|
+
|
389
|
+
# Adjust colors so that centroids close to one another are maximally distant on the color spectrum
|
390
|
+
half_spectrum = int(num_colors_to_generate / 2)
|
391
|
+
for i in range(half_spectrum):
|
392
|
+
# Split the spectrum so that close centroids are assigned distant colors
|
393
|
+
color_positions[proximity_order[i]] = (i * 2) / num_colors_to_generate
|
394
|
+
color_positions[proximity_order[-(i + 1)]] = ((i * 2) + 1) / num_colors_to_generate
|
395
|
+
|
396
|
+
return color_positions
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|