risk-network 0.0.8b18__py3-none-any.whl → 0.0.9b26__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.
Files changed (50) hide show
  1. risk/__init__.py +2 -2
  2. risk/annotations/__init__.py +2 -2
  3. risk/annotations/annotations.py +133 -72
  4. risk/annotations/io.py +50 -34
  5. risk/log/__init__.py +4 -2
  6. risk/log/{config.py → console.py} +5 -3
  7. risk/log/{params.py → parameters.py} +21 -46
  8. risk/neighborhoods/__init__.py +3 -5
  9. risk/neighborhoods/api.py +446 -0
  10. risk/neighborhoods/community.py +281 -96
  11. risk/neighborhoods/domains.py +92 -38
  12. risk/neighborhoods/neighborhoods.py +210 -149
  13. risk/network/__init__.py +1 -3
  14. risk/network/geometry.py +69 -58
  15. risk/network/graph/__init__.py +6 -0
  16. risk/network/graph/api.py +194 -0
  17. risk/network/graph/network.py +269 -0
  18. risk/network/graph/summary.py +254 -0
  19. risk/network/io.py +58 -48
  20. risk/network/plotter/__init__.py +6 -0
  21. risk/network/plotter/api.py +54 -0
  22. risk/network/{plot → plotter}/canvas.py +80 -26
  23. risk/network/{plot → plotter}/contour.py +43 -34
  24. risk/network/{plot → plotter}/labels.py +123 -113
  25. risk/network/plotter/network.py +424 -0
  26. risk/network/plotter/utils/colors.py +416 -0
  27. risk/network/plotter/utils/layout.py +94 -0
  28. risk/risk.py +11 -469
  29. risk/stats/__init__.py +8 -4
  30. risk/stats/binom.py +51 -0
  31. risk/stats/chi2.py +69 -0
  32. risk/stats/hypergeom.py +28 -18
  33. risk/stats/permutation/__init__.py +1 -1
  34. risk/stats/permutation/permutation.py +45 -39
  35. risk/stats/permutation/test_functions.py +25 -17
  36. risk/stats/poisson.py +17 -11
  37. risk/stats/stats.py +20 -16
  38. risk/stats/zscore.py +68 -0
  39. {risk_network-0.0.8b18.dist-info → risk_network-0.0.9b26.dist-info}/METADATA +9 -5
  40. risk_network-0.0.9b26.dist-info/RECORD +44 -0
  41. {risk_network-0.0.8b18.dist-info → risk_network-0.0.9b26.dist-info}/WHEEL +1 -1
  42. risk/network/graph.py +0 -159
  43. risk/network/plot/__init__.py +0 -6
  44. risk/network/plot/network.py +0 -282
  45. risk/network/plot/plotter.py +0 -137
  46. risk/network/plot/utils/color.py +0 -353
  47. risk/network/plot/utils/layout.py +0 -53
  48. risk_network-0.0.8b18.dist-info/RECORD +0 -37
  49. {risk_network-0.0.8b18.dist-info → risk_network-0.0.9b26.dist-info}/LICENSE +0 -0
  50. {risk_network-0.0.8b18.dist-info → risk_network-0.0.9b26.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,7 @@ risk/network/plot/labels
3
3
  ~~~~~~~~~~~~~~~~~~~~~~~~
4
4
  """
5
5
 
6
+ import copy
6
7
  from typing import Any, Dict, List, Tuple, Union
7
8
 
8
9
  import matplotlib.pyplot as plt
@@ -10,9 +11,9 @@ import numpy as np
10
11
  import pandas as pd
11
12
 
12
13
  from risk.log import params
13
- from risk.network.graph import NetworkGraph
14
- from risk.network.plot.utils.color import get_annotated_domain_colors, to_rgba
15
- from risk.network.plot.utils.layout import calculate_bounding_box
14
+ from risk.network.graph.network import NetworkGraph
15
+ from risk.network.plotter.utils.colors import get_annotated_domain_colors, to_rgba
16
+ from risk.network.plotter.utils.layout import calculate_bounding_box
16
17
 
17
18
  TERM_DELIMITER = "::::" # String used to separate multiple domain terms when constructing composite domain labels
18
19
 
@@ -53,7 +54,7 @@ class Labels:
53
54
  words_to_omit: Union[List, None] = None,
54
55
  overlay_ids: bool = False,
55
56
  ids_to_keep: Union[List, Tuple, np.ndarray, None] = None,
56
- ids_to_replace: Union[Dict, None] = None,
57
+ ids_to_labels: Union[Dict[int, str], None] = None,
57
58
  ) -> None:
58
59
  """Annotate the network graph with labels for different domains, positioned around the network for clarity.
59
60
 
@@ -61,18 +62,18 @@ class Labels:
61
62
  scale (float, optional): Scale factor for positioning labels around the perimeter. Defaults to 1.05.
62
63
  offset (float, optional): Offset distance for labels from the perimeter. Defaults to 0.10.
63
64
  font (str, optional): Font name for the labels. Defaults to "Arial".
64
- fontcase (Union[str, Dict[str, str], None]): Defines how to transform the case of words.
65
+ fontcase (str, Dict[str, str], or None, optional): Defines how to transform the case of words.
65
66
  - If a string (e.g., 'upper', 'lower', 'title'), applies the transformation to all words.
66
67
  - If a dictionary, maps specific cases ('lower', 'upper', 'title') to transformations (e.g., 'lower'='upper').
67
68
  - If None, no transformation is applied.
68
69
  fontsize (int, optional): Font size for the labels. Defaults to 10.
69
- fontcolor (str, list, tuple, or np.ndarray, optional): Color of the label text. Can be a string or RGBA array.
70
+ fontcolor (str, List, Tuple, or np.ndarray, optional): Color of the label text. Can be a string or RGBA array.
70
71
  Defaults to "black".
71
72
  fontalpha (float, None, optional): Transparency level for the font color. If provided, it overrides any existing alpha
72
73
  values found in fontcolor. Defaults to 1.0.
73
74
  arrow_linewidth (float, optional): Line width of the arrows pointing to centroids. Defaults to 1.
74
75
  arrow_style (str, optional): Style of the arrows pointing to centroids. Defaults to "->".
75
- arrow_color (str, list, tuple, or np.ndarray, optional): Color of the arrows. Defaults to "black".
76
+ arrow_color (str, List, Tuple, or np.ndarray, optional): Color of the arrows. Defaults to "black".
76
77
  arrow_alpha (float, None, optional): Transparency level for the arrow color. If provided, it overrides any existing alpha
77
78
  values found in arrow_color. Defaults to 1.0.
78
79
  arrow_base_shrink (float, optional): Distance between the text and the base of the arrow. Defaults to 0.0.
@@ -82,11 +83,11 @@ class Labels:
82
83
  max_label_lines (int, optional): Maximum number of lines in a label. Defaults to None (no limit).
83
84
  min_chars_per_line (int, optional): Minimum number of characters in a line to display. Defaults to 1.
84
85
  max_chars_per_line (int, optional): Maximum number of characters in a line to display. Defaults to None (no limit).
85
- words_to_omit (list, optional): List of words to omit from the labels. Defaults to None.
86
+ words_to_omit (List, optional): List of words to omit from the labels. Defaults to None.
86
87
  overlay_ids (bool, optional): Whether to overlay domain IDs in the center of the centroids. Defaults to False.
87
- ids_to_keep (list, tuple, np.ndarray, or None, optional): IDs of domains that must be labeled. To discover domain IDs,
88
+ ids_to_keep (List, Tuple, np.ndarray, or None, optional): IDs of domains that must be labeled. To discover domain IDs,
88
89
  you can set `overlay_ids=True`. Defaults to None.
89
- ids_to_replace (dict, optional): A dictionary mapping domain IDs to custom labels (strings). The labels should be
90
+ ids_to_labels (Dict[int, str], optional): A dictionary mapping domain IDs to custom labels (strings). The labels should be
90
91
  space-separated words. If provided, the custom labels will replace the default domain terms. To discover domain IDs, you
91
92
  can set `overlay_ids=True`. Defaults to None.
92
93
 
@@ -118,7 +119,7 @@ class Labels:
118
119
  label_words_to_omit=words_to_omit,
119
120
  label_overlay_ids=overlay_ids,
120
121
  label_ids_to_keep=ids_to_keep,
121
- label_ids_to_replace=ids_to_replace,
122
+ label_ids_to_labels=ids_to_labels,
122
123
  )
123
124
 
124
125
  # Convert ids_to_keep to a tuple if it is not None
@@ -151,7 +152,7 @@ class Labels:
151
152
  self._process_ids_to_keep(
152
153
  domain_id_to_centroid_map=domain_id_to_centroid_map,
153
154
  ids_to_keep=ids_to_keep,
154
- ids_to_replace=ids_to_replace,
155
+ ids_to_labels=ids_to_labels,
155
156
  words_to_omit=words_to_omit,
156
157
  max_labels=max_labels,
157
158
  min_label_lines=min_label_lines,
@@ -172,7 +173,7 @@ class Labels:
172
173
  self._process_remaining_domains(
173
174
  domain_id_to_centroid_map=domain_id_to_centroid_map,
174
175
  ids_to_keep=ids_to_keep,
175
- ids_to_replace=ids_to_replace,
176
+ ids_to_labels=ids_to_labels,
176
177
  words_to_omit=words_to_omit,
177
178
  remaining_labels=remaining_labels,
178
179
  min_chars_per_line=min_chars_per_line,
@@ -191,10 +192,10 @@ class Labels:
191
192
  filtered_domain_centroids, center, radius, offset
192
193
  )
193
194
  # Convert all domain colors to RGBA using the to_rgba helper function
194
- fontcolor = to_rgba(
195
+ fontcolor_rgba = to_rgba(
195
196
  color=fontcolor, alpha=fontalpha, num_repeats=len(self.graph.domain_id_to_node_ids_map)
196
197
  )
197
- arrow_color = to_rgba(
198
+ arrow_color_rgba = to_rgba(
198
199
  color=arrow_color,
199
200
  alpha=arrow_alpha,
200
201
  num_repeats=len(self.graph.domain_id_to_node_ids_map),
@@ -216,14 +217,15 @@ class Labels:
216
217
  va="center",
217
218
  fontsize=fontsize,
218
219
  fontname=font,
219
- color=fontcolor[idx],
220
- arrowprops=dict(
221
- arrowstyle=arrow_style,
222
- color=arrow_color[idx],
223
- linewidth=arrow_linewidth,
224
- shrinkA=arrow_base_shrink,
225
- shrinkB=arrow_tip_shrink,
226
- ),
220
+ color=fontcolor_rgba[idx],
221
+ arrowprops={
222
+ "arrowstyle": arrow_style,
223
+ "linewidth": arrow_linewidth,
224
+ "color": arrow_color_rgba[idx],
225
+ "alpha": arrow_alpha,
226
+ "shrinkA": arrow_base_shrink,
227
+ "shrinkB": arrow_tip_shrink,
228
+ },
227
229
  )
228
230
 
229
231
  # Overlay domain ID at the centroid regardless of max_labels if requested
@@ -238,8 +240,7 @@ class Labels:
238
240
  va="center",
239
241
  fontsize=fontsize,
240
242
  fontname=font,
241
- color=fontcolor[idx],
242
- alpha=fontalpha,
243
+ color=fontcolor_rgba[idx],
243
244
  )
244
245
 
245
246
  def plot_sublabel(
@@ -263,19 +264,19 @@ class Labels:
263
264
  """Annotate the network graph with a label for the given nodes, with one arrow pointing to each centroid of sublists of nodes.
264
265
 
265
266
  Args:
266
- nodes (list, tuple, or np.ndarray): List of node labels or list of lists of node labels.
267
+ nodes (List, Tuple, or np.ndarray): List of node labels or list of lists of node labels.
267
268
  label (str): The label to be annotated on the network.
268
269
  radial_position (float, optional): Radial angle for positioning the label, in degrees (0-360). Defaults to 0.0.
269
270
  scale (float, optional): Scale factor for positioning the label around the perimeter. Defaults to 1.05.
270
271
  offset (float, optional): Offset distance for the label from the perimeter. Defaults to 0.10.
271
272
  font (str, optional): Font name for the label. Defaults to "Arial".
272
273
  fontsize (int, optional): Font size for the label. Defaults to 10.
273
- fontcolor (str, list, tuple, or np.ndarray, optional): Color of the label text. Defaults to "black".
274
+ fontcolor (str, List, Tuple, or np.ndarray, optional): Color of the label text. Defaults to "black".
274
275
  fontalpha (float, None, optional): Transparency level for the font color. If provided, it overrides any existing alpha values found
275
276
  in fontalpha. Defaults to 1.0.
276
277
  arrow_linewidth (float, optional): Line width of the arrow pointing to the centroid. Defaults to 1.
277
278
  arrow_style (str, optional): Style of the arrows pointing to the centroid. Defaults to "->".
278
- arrow_color (str, list, tuple, or np.ndarray, optional): Color of the arrow. Defaults to "black".
279
+ arrow_color (str, List, Tuple, or np.ndarray, optional): Color of the arrow. Defaults to "black".
279
280
  arrow_alpha (float, None, optional): Transparency level for the arrow color. If provided, it overrides any existing alpha values
280
281
  found in arrow_alpha. Defaults to 1.0.
281
282
  arrow_base_shrink (float, optional): Distance between the text and the base of the arrow. Defaults to 0.0.
@@ -334,20 +335,21 @@ class Labels:
334
335
  fontsize=fontsize,
335
336
  fontname=font,
336
337
  color=fontcolor_rgba[idx],
337
- arrowprops=dict(
338
- arrowstyle=arrow_style,
339
- color=arrow_color_rgba[idx],
340
- linewidth=arrow_linewidth,
341
- shrinkA=arrow_base_shrink,
342
- shrinkB=arrow_tip_shrink,
343
- ),
338
+ arrowprops={
339
+ "arrowstyle": arrow_style,
340
+ "linewidth": arrow_linewidth,
341
+ "color": arrow_color_rgba[idx],
342
+ "alpha": arrow_alpha,
343
+ "shrinkA": arrow_base_shrink,
344
+ "shrinkB": arrow_tip_shrink,
345
+ },
344
346
  )
345
347
 
346
348
  def _calculate_domain_centroid(self, nodes: List) -> tuple:
347
349
  """Calculate the most centrally located node in .
348
350
 
349
351
  Args:
350
- nodes (list): List of node labels to include in the subnetwork.
352
+ nodes (List): List of node labels to include in the subnetwork.
351
353
 
352
354
  Returns:
353
355
  tuple: A tuple containing the domain's central node coordinates.
@@ -368,7 +370,7 @@ class Labels:
368
370
  self,
369
371
  domain_id_to_centroid_map: Dict[str, np.ndarray],
370
372
  ids_to_keep: Union[List[str], Tuple[str], np.ndarray],
371
- ids_to_replace: Union[Dict[str, str], None],
373
+ ids_to_labels: Union[Dict[int, str], None],
372
374
  words_to_omit: Union[List[str], None],
373
375
  max_labels: Union[int, None],
374
376
  min_label_lines: int,
@@ -382,18 +384,18 @@ class Labels:
382
384
  """Process the ids_to_keep, apply filtering, and store valid domain centroids and terms.
383
385
 
384
386
  Args:
385
- domain_id_to_centroid_map (dict): Mapping of domain IDs to their centroids.
386
- ids_to_keep (list, tuple, or np.ndarray, optional): IDs of domains that must be labeled.
387
- ids_to_replace (dict, optional): A dictionary mapping domain IDs to custom labels. Defaults to None.
388
- words_to_omit (list, optional): List of words to omit from the labels. Defaults to None.
387
+ domain_id_to_centroid_map (Dict[str, np.ndarray]): Mapping of domain IDs to their centroids.
388
+ ids_to_keep (List, Tuple, or np.ndarray, optional): IDs of domains that must be labeled.
389
+ ids_to_labels (Dict[int, str], None, optional): A dictionary mapping domain IDs to custom labels. Defaults to None.
390
+ words_to_omit (List, optional): List of words to omit from the labels. Defaults to None.
389
391
  max_labels (int, optional): Maximum number of labels allowed.
390
392
  min_label_lines (int): Minimum number of lines in a label.
391
393
  max_label_lines (int): Maximum number of lines in a label.
392
394
  min_chars_per_line (int): Minimum number of characters in a line to display.
393
395
  max_chars_per_line (int): Maximum number of characters in a line to display.
394
- filtered_domain_centroids (dict): Dictionary to store filtered domain centroids (output).
395
- filtered_domain_terms (dict): Dictionary to store filtered domain terms (output).
396
- valid_indices (list): List to store valid indices (output).
396
+ filtered_domain_centroids (Dict[str, np.ndarray]): Dictionary to store filtered domain centroids (output).
397
+ filtered_domain_terms (Dict[str, str]): Dictionary to store filtered domain terms (output).
398
+ valid_indices (List): List to store valid indices (output).
397
399
 
398
400
  Note:
399
401
  The `filtered_domain_centroids`, `filtered_domain_terms`, and `valid_indices` are modified in-place.
@@ -419,7 +421,7 @@ class Labels:
419
421
  domain=domain,
420
422
  domain_centroid=domain_centroid,
421
423
  domain_id_to_centroid_map=domain_id_to_centroid_map,
422
- ids_to_replace=ids_to_replace,
424
+ ids_to_labels=ids_to_labels,
423
425
  words_to_omit=words_to_omit,
424
426
  min_label_lines=min_label_lines,
425
427
  max_label_lines=max_label_lines,
@@ -434,7 +436,7 @@ class Labels:
434
436
  self,
435
437
  domain_id_to_centroid_map: Dict[str, np.ndarray],
436
438
  ids_to_keep: Union[List[str], Tuple[str], np.ndarray],
437
- ids_to_replace: Union[Dict[str, str], None],
439
+ ids_to_labels: Union[Dict[int, str], None],
438
440
  words_to_omit: Union[List[str], None],
439
441
  remaining_labels: int,
440
442
  min_label_lines: int,
@@ -448,18 +450,18 @@ class Labels:
448
450
  """Process remaining domains to fill in additional labels, respecting the remaining_labels limit.
449
451
 
450
452
  Args:
451
- domain_id_to_centroid_map (dict): Mapping of domain IDs to their centroids.
452
- ids_to_keep (list, tuple, or np.ndarray, optional): IDs of domains that must be labeled.
453
- ids_to_replace (dict, optional): A dictionary mapping domain IDs to custom labels. Defaults to None.
454
- words_to_omit (list, optional): List of words to omit from the labels. Defaults to None.
453
+ domain_id_to_centroid_map (Dict[str, np.ndarray]): Mapping of domain IDs to their centroids.
454
+ ids_to_keep (List, Tuple, or np.ndarray, optional): IDs of domains that must be labeled.
455
+ ids_to_labels (Dict[int, str], None, optional): A dictionary mapping domain IDs to custom labels. Defaults to None.
456
+ words_to_omit (List, optional): List of words to omit from the labels. Defaults to None.
455
457
  remaining_labels (int): The remaining number of labels that can be generated.
456
458
  min_label_lines (int): Minimum number of lines in a label.
457
459
  max_label_lines (int): Maximum number of lines in a label.
458
460
  min_chars_per_line (int): Minimum number of characters in a line to display.
459
461
  max_chars_per_line (int): Maximum number of characters in a line to display.
460
- filtered_domain_centroids (dict): Dictionary to store filtered domain centroids (output).
461
- filtered_domain_terms (dict): Dictionary to store filtered domain terms (output).
462
- valid_indices (list): List to store valid indices (output).
462
+ filtered_domain_centroids (Dict[str, np.ndarray]): Dictionary to store filtered domain centroids (output).
463
+ filtered_domain_terms (Dict[str, str]): Dictionary to store filtered domain terms (output).
464
+ valid_indices (List): List to store valid indices (output).
463
465
 
464
466
  Note:
465
467
  The `filtered_domain_centroids`, `filtered_domain_terms`, and `valid_indices` are modified in-place.
@@ -515,7 +517,7 @@ class Labels:
515
517
  domain=domain,
516
518
  domain_centroid=domain_centroid,
517
519
  domain_id_to_centroid_map=domain_id_to_centroid_map,
518
- ids_to_replace=ids_to_replace,
520
+ ids_to_labels=ids_to_labels,
519
521
  words_to_omit=words_to_omit,
520
522
  min_label_lines=min_label_lines,
521
523
  max_label_lines=max_label_lines,
@@ -536,7 +538,7 @@ class Labels:
536
538
  domain: str,
537
539
  domain_centroid: np.ndarray,
538
540
  domain_id_to_centroid_map: Dict[str, np.ndarray],
539
- ids_to_replace: Union[Dict[str, str], None],
541
+ ids_to_labels: Union[Dict[int, str], None],
540
542
  words_to_omit: Union[List[str], None],
541
543
  min_label_lines: int,
542
544
  max_label_lines: int,
@@ -551,9 +553,9 @@ class Labels:
551
553
  Args:
552
554
  domain (str): Domain ID to process.
553
555
  domain_centroid (np.ndarray): Centroid position of the domain.
554
- domain_id_to_centroid_map (dict): Mapping of domain IDs to their centroids.
555
- ids_to_replace (Union[Dict[str, str], None]): A dictionary mapping domain IDs to custom labels.
556
- words_to_omit (Union[List[str], None]): List of words to omit from the labels.
556
+ domain_id_to_centroid_map (Dict[str, np.ndarray]): Mapping of domain IDs to their centroids.
557
+ ids_to_labels (Dict[int, str], None, optional): A dictionary mapping domain IDs to custom labels. Defaults to None.
558
+ words_to_omit (List[str], None, optional): List of words to omit from the labels. Defaults to None.
557
559
  min_label_lines (int): Minimum number of lines required in a label.
558
560
  max_label_lines (int): Maximum number of lines allowed in a label.
559
561
  min_chars_per_line (int): Minimum number of characters allowed per line.
@@ -564,39 +566,39 @@ class Labels:
564
566
 
565
567
  Returns:
566
568
  bool: True if the domain is valid and added to the filtered dictionaries, False otherwise.
567
-
568
- Note:
569
- The `filtered_domain_centroids`, `filtered_domain_terms`, and `valid_indices` are modified in-place.
570
569
  """
571
- # Process the domain terms
572
- domain_terms = self._process_terms(
573
- domain=domain,
574
- ids_to_replace=ids_to_replace,
575
- words_to_omit=words_to_omit,
576
- max_label_lines=max_label_lines,
577
- min_chars_per_line=min_chars_per_line,
578
- max_chars_per_line=max_chars_per_line,
579
- )
580
- # If domain_terms is empty, skip further processing
581
- if not domain_terms:
582
- return False
583
-
584
- # Split the terms by TERM_DELIMITER and count the number of lines
585
- num_domain_lines = len(domain_terms.split(TERM_DELIMITER))
586
- # Check if the number of lines is greater than or equal to the minimum
587
- if num_domain_lines >= min_label_lines:
588
- filtered_domain_centroids[domain] = domain_centroid
589
- filtered_domain_terms[domain] = domain_terms
590
- # Add the index of the domain to the valid indices list
591
- valid_indices.append(list(domain_id_to_centroid_map.keys()).index(domain))
592
- return True
593
-
594
- return False
570
+ if ids_to_labels and domain in ids_to_labels:
571
+ # Directly use custom labels without filtering
572
+ domain_terms = ids_to_labels[domain]
573
+ else:
574
+ # Process the domain terms automatically
575
+ domain_terms = self._process_terms(
576
+ domain=domain,
577
+ words_to_omit=words_to_omit,
578
+ max_label_lines=max_label_lines,
579
+ min_chars_per_line=min_chars_per_line,
580
+ max_chars_per_line=max_chars_per_line,
581
+ )
582
+ # If no valid terms are generated, skip further processing
583
+ if not domain_terms:
584
+ return False
585
+
586
+ # Split the terms by TERM_DELIMITER and count the number of lines
587
+ num_domain_lines = len(domain_terms.split(TERM_DELIMITER))
588
+ # Check if the number of lines meets the minimum requirement
589
+ if num_domain_lines < min_label_lines:
590
+ return False
591
+
592
+ # Store the valid terms and centroids
593
+ filtered_domain_centroids[domain] = domain_centroid
594
+ filtered_domain_terms[domain] = domain_terms
595
+ valid_indices.append(list(domain_id_to_centroid_map.keys()).index(domain))
596
+
597
+ return True
595
598
 
596
599
  def _process_terms(
597
600
  self,
598
601
  domain: str,
599
- ids_to_replace: Union[Dict[str, str], None],
600
602
  words_to_omit: Union[List[str], None],
601
603
  max_label_lines: int,
602
604
  min_chars_per_line: int,
@@ -606,8 +608,7 @@ class Labels:
606
608
 
607
609
  Args:
608
610
  domain (str): The domain being processed.
609
- ids_to_replace (dict, optional): Dictionary mapping domain IDs to custom labels.
610
- words_to_omit (list, optional): List of words to omit from the labels.
611
+ words_to_omit (List[str], None): List of words to omit from the labels.
611
612
  max_label_lines (int): Maximum number of lines in a label.
612
613
  min_chars_per_line (int): Minimum number of characters in a line to display.
613
614
  max_chars_per_line (int): Maximum number of characters in a line to display.
@@ -615,12 +616,8 @@ class Labels:
615
616
  Returns:
616
617
  str: Processed terms separated by TERM_DELIMITER, with words combined if necessary to fit within constraints.
617
618
  """
618
- # Handle ids_to_replace logic
619
- if ids_to_replace and domain in ids_to_replace:
620
- terms = ids_to_replace[domain].split(" ")
621
- else:
622
- terms = self.graph.domain_id_to_domain_terms_map[domain].split(" ")
623
-
619
+ # Set custom labels from significant terms
620
+ terms = self.graph.domain_id_to_domain_terms_map[domain].split(" ")
624
621
  # Apply words_to_omit and word length constraints
625
622
  if words_to_omit:
626
623
  terms = [
@@ -637,24 +634,30 @@ class Labels:
637
634
  def get_annotated_label_colors(
638
635
  self,
639
636
  cmap: str = "gist_rainbow",
640
- color: Union[str, list, tuple, np.ndarray, None] = None,
637
+ color: Union[str, List, Tuple, np.ndarray, None] = None,
638
+ blend_colors: bool = False,
639
+ blend_gamma: float = 2.2,
641
640
  min_scale: float = 0.8,
642
641
  max_scale: float = 1.0,
643
642
  scale_factor: float = 1.0,
643
+ ids_to_colors: Union[Dict[int, Any], None] = None,
644
644
  random_seed: int = 888,
645
645
  ) -> np.ndarray:
646
646
  """Get colors for the labels based on node annotations or a specified colormap.
647
647
 
648
648
  Args:
649
649
  cmap (str, optional): Name of the colormap to use for generating label colors. Defaults to "gist_rainbow".
650
- color (str, list, tuple, np.ndarray, or None, optional): Color to use for the labels. Can be a single color or an array
650
+ color (str, List, Tuple, np.ndarray, or None, optional): Color to use for the labels. Can be a single color or an array
651
651
  of colors. If None, the colormap will be used. Defaults to None.
652
+ blend_colors (bool, optional): Whether to blend colors for nodes with multiple domains. Defaults to False.
653
+ blend_gamma (float, optional): Gamma correction factor for perceptual color blending. Defaults to 2.2.
652
654
  min_scale (float, optional): Minimum intensity scale for the colors generated by the colormap.
653
655
  Controls the dimmest colors. Defaults to 0.8.
654
656
  max_scale (float, optional): Maximum intensity scale for the colors generated by the colormap.
655
657
  Controls the brightest colors. Defaults to 1.0.
656
- scale_factor (float, optional): Exponent for adjusting color scaling based on enrichment scores.
658
+ scale_factor (float, optional): Exponent for adjusting color scaling based on significance scores.
657
659
  A higher value increases contrast by dimming lower scores more. Defaults to 1.0.
660
+ ids_to_colors (Dict[int, Any], None, optional): Mapping of domain IDs to specific colors. Defaults to None.
658
661
  random_seed (int, optional): Seed for random number generation to ensure reproducibility. Defaults to 888.
659
662
 
660
663
  Returns:
@@ -664,9 +667,12 @@ class Labels:
664
667
  graph=self.graph,
665
668
  cmap=cmap,
666
669
  color=color,
670
+ blend_colors=blend_colors,
671
+ blend_gamma=blend_gamma,
667
672
  min_scale=min_scale,
668
673
  max_scale=max_scale,
669
674
  scale_factor=scale_factor,
675
+ ids_to_colors=ids_to_colors,
670
676
  random_seed=random_seed,
671
677
  )
672
678
 
@@ -716,12 +722,19 @@ def _combine_words(words: List[str], max_chars_per_line: int, max_label_lines: i
716
722
  # Main logic: start with max_label_lines number of words
717
723
  combined_lines = try_combinations(words[:max_label_lines])
718
724
  remaining_words = words[max_label_lines:] # Remaining words after the initial batch
725
+ # Track words that have already been added
726
+ existing_words = set(" ".join(combined_lines).split())
719
727
 
720
728
  # Continue pulling more words until we fill the lines
721
729
  while remaining_words and len(combined_lines) < max_label_lines:
722
730
  available_slots = max_label_lines - len(combined_lines)
723
- words_to_add = remaining_words[:available_slots]
731
+ words_to_add = [
732
+ word for word in remaining_words[:available_slots] if word not in existing_words
733
+ ]
724
734
  remaining_words = remaining_words[available_slots:]
735
+ # Update the existing words set
736
+ existing_words.update(words_to_add)
737
+ # Add to combined_lines only unique words
725
738
  combined_lines += try_combinations(words_to_add)
726
739
 
727
740
  # Join the final combined lines with TERM_DELIMITER, a special separator for line breaks
@@ -734,13 +747,13 @@ def _calculate_best_label_positions(
734
747
  """Calculate and optimize label positions for clarity.
735
748
 
736
749
  Args:
737
- filtered_domain_centroids (dict): Centroids of the filtered domains.
750
+ filtered_domain_centroids (Dict[str, Any]): Centroids of the filtered domains.
738
751
  center (np.ndarray): The center coordinates for label positioning.
739
752
  radius (float): The radius for positioning labels around the center.
740
753
  offset (float): The offset distance from the radius for positioning labels.
741
754
 
742
755
  Returns:
743
- dict: Optimized positions for labels.
756
+ Dict[str, Any]: Optimized positions for labels.
744
757
  """
745
758
  num_domains = len(filtered_domain_centroids)
746
759
  # Calculate equidistant positions around the center for initial label placement
@@ -748,10 +761,7 @@ def _calculate_best_label_positions(
748
761
  center, radius, offset, num_domains
749
762
  )
750
763
  # Create a mapping of domains to their initial label positions
751
- label_positions = {
752
- domain: position
753
- for domain, position in zip(filtered_domain_centroids.keys(), equidistant_positions)
754
- }
764
+ label_positions = dict(zip(filtered_domain_centroids.keys(), equidistant_positions))
755
765
  # Optimize the label positions to minimize distance to domain centroids
756
766
  return _optimize_label_positions(label_positions, filtered_domain_centroids)
757
767
 
@@ -768,7 +778,7 @@ def _calculate_equidistant_positions_around_center(
768
778
  num_domains (int): The number of positions (or domains) to calculate.
769
779
 
770
780
  Returns:
771
- list[np.ndarray]: List of positions (as 2D numpy arrays) around the center.
781
+ List[np.ndarray]: List of positions (as 2D numpy arrays) around the center.
772
782
  """
773
783
  # Calculate equidistant angles in radians around the center
774
784
  angles = np.linspace(0, 2 * np.pi, num_domains, endpoint=False)
@@ -785,11 +795,11 @@ def _optimize_label_positions(
785
795
  """Optimize label positions around the perimeter to minimize total distance to centroids.
786
796
 
787
797
  Args:
788
- best_label_positions (dict): Initial positions of labels around the perimeter.
789
- domain_centroids (dict): Centroid positions of the domains.
798
+ best_label_positions (Dict[str, Any]): Initial positions of labels around the perimeter.
799
+ domain_centroids (Dict[str, Any]): Centroid positions of the domains.
790
800
 
791
801
  Returns:
792
- dict: Optimized label positions.
802
+ Dict[str, Any]: Optimized label positions.
793
803
  """
794
804
  while True:
795
805
  improvement = False # Start each iteration assuming no improvement
@@ -821,8 +831,8 @@ def _calculate_total_distance(
821
831
  """Calculate the total distance from label positions to their domain centroids.
822
832
 
823
833
  Args:
824
- label_positions (dict): Positions of labels around the perimeter.
825
- domain_centroids (dict): Centroid positions of the domains.
834
+ label_positions (Dict[str, Any]): Positions of labels around the perimeter.
835
+ domain_centroids (Dict[str, Any]): Centroid positions of the domains.
826
836
 
827
837
  Returns:
828
838
  float: The total distance from labels to centroids.
@@ -845,17 +855,17 @@ def _swap_and_evaluate(
845
855
  """Swap two labels and evaluate the total distance after the swap.
846
856
 
847
857
  Args:
848
- label_positions (dict): Positions of labels around the perimeter.
858
+ label_positions (Dict[str, Any]): Positions of labels around the perimeter.
849
859
  i (int): Index of the first label to swap.
850
860
  j (int): Index of the second label to swap.
851
- domain_centroids (dict): Centroid positions of the domains.
861
+ domain_centroids (Dict[str, Any]): Centroid positions of the domains.
852
862
 
853
863
  Returns:
854
864
  float: The total distance after swapping the two labels.
855
865
  """
856
866
  # Get the list of labels from the dictionary keys
857
867
  labels = list(label_positions.keys())
858
- swapped_positions = label_positions.copy()
868
+ swapped_positions = copy.deepcopy(label_positions)
859
869
  # Swap the positions of the two specified labels
860
870
  swapped_positions[labels[i]], swapped_positions[labels[j]] = (
861
871
  swapped_positions[labels[j]],