risk-network 0.0.8b2__py3-none-any.whl → 0.0.8b3__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.py +166 -112
- {risk_network-0.0.8b2.dist-info → risk_network-0.0.8b3.dist-info}/METADATA +1 -1
- {risk_network-0.0.8b2.dist-info → risk_network-0.0.8b3.dist-info}/RECORD +7 -7
- {risk_network-0.0.8b2.dist-info → risk_network-0.0.8b3.dist-info}/LICENSE +0 -0
- {risk_network-0.0.8b2.dist-info → risk_network-0.0.8b3.dist-info}/WHEEL +0 -0
- {risk_network-0.0.8b2.dist-info → risk_network-0.0.8b3.dist-info}/top_level.txt +0 -0
risk/__init__.py
CHANGED
risk/network/plot.py
CHANGED
@@ -3,7 +3,6 @@ risk/network/plot
|
|
3
3
|
~~~~~~~~~~~~~~~~~
|
4
4
|
"""
|
5
5
|
|
6
|
-
from functools import lru_cache
|
7
6
|
from typing import Any, Dict, List, Tuple, Union
|
8
7
|
|
9
8
|
import matplotlib.colors as mcolors
|
@@ -18,6 +17,8 @@ from scipy.stats import gaussian_kde
|
|
18
17
|
from risk.log import params, logger
|
19
18
|
from risk.network.graph import NetworkGraph
|
20
19
|
|
20
|
+
TERM_DELIMITER = "::::" # String used to separate multiple domain terms when constructing composite domain labels
|
21
|
+
|
21
22
|
|
22
23
|
class NetworkPlotter:
|
23
24
|
"""A class for visualizing network graphs with customizable options.
|
@@ -679,10 +680,10 @@ class NetworkPlotter:
|
|
679
680
|
arrow_base_shrink: float = 0.0,
|
680
681
|
arrow_tip_shrink: float = 0.0,
|
681
682
|
max_labels: Union[int, None] = None,
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
683
|
+
max_label_lines: Union[int, None] = None,
|
684
|
+
min_label_lines: int = 1,
|
685
|
+
max_chars_per_line: Union[int, None] = None,
|
686
|
+
min_chars_per_line: int = 1,
|
686
687
|
words_to_omit: Union[List, None] = None,
|
687
688
|
overlay_ids: bool = False,
|
688
689
|
ids_to_keep: Union[List, Tuple, np.ndarray, None] = None,
|
@@ -704,10 +705,10 @@ class NetworkPlotter:
|
|
704
705
|
arrow_base_shrink (float, optional): Distance between the text and the base of the arrow. Defaults to 0.0.
|
705
706
|
arrow_tip_shrink (float, optional): Distance between the arrow tip and the centroid. Defaults to 0.0.
|
706
707
|
max_labels (int, optional): Maximum number of labels to plot. Defaults to None (no limit).
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
708
|
+
max_label_lines (int, optional): Maximum number of lines in a label. Defaults to None (no limit).
|
709
|
+
min_label_lines (int, optional): Minimum number of lines in a label. Defaults to 1.
|
710
|
+
max_chars_per_line (int, optional): Maximum number of characters in a line to display. Defaults to None (no limit).
|
711
|
+
min_chars_per_line (int, optional): Minimum number of characters in a line to display. Defaults to 1.
|
711
712
|
words_to_omit (list, optional): List of words to omit from the labels. Defaults to None.
|
712
713
|
overlay_ids (bool, optional): Whether to overlay domain IDs in the center of the centroids. Defaults to False.
|
713
714
|
ids_to_keep (list, tuple, np.ndarray, or None, optional): IDs of domains that must be labeled. To discover domain IDs,
|
@@ -736,19 +737,26 @@ class NetworkPlotter:
|
|
736
737
|
label_arrow_base_shrink=arrow_base_shrink,
|
737
738
|
label_arrow_tip_shrink=arrow_tip_shrink,
|
738
739
|
label_max_labels=max_labels,
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
740
|
+
label_min_label_lines=min_label_lines,
|
741
|
+
label_max_label_lines=max_label_lines,
|
742
|
+
label_max_chars_per_line=max_chars_per_line,
|
743
|
+
label_min_chars_per_line=min_chars_per_line,
|
743
744
|
label_words_to_omit=words_to_omit,
|
744
745
|
label_overlay_ids=overlay_ids,
|
745
746
|
label_ids_to_keep=ids_to_keep,
|
746
747
|
label_ids_to_replace=ids_to_replace,
|
747
748
|
)
|
748
749
|
|
750
|
+
# Convert ids_to_keep to a tuple if it is not None
|
751
|
+
ids_to_keep = tuple(ids_to_keep) if ids_to_keep else tuple()
|
749
752
|
# Set max_labels to the total number of domains if not provided (None)
|
750
753
|
if max_labels is None:
|
751
754
|
max_labels = len(self.graph.domain_id_to_node_ids_map)
|
755
|
+
# Set max_label_lines and max_chars_per_line to large numbers if not provided (None)
|
756
|
+
if max_label_lines is None:
|
757
|
+
max_label_lines = int(1e6)
|
758
|
+
if max_chars_per_line is None:
|
759
|
+
max_chars_per_line = int(1e6)
|
752
760
|
# Normalize words_to_omit to lowercase
|
753
761
|
if words_to_omit:
|
754
762
|
words_to_omit = set(word.lower() for word in words_to_omit)
|
@@ -760,46 +768,46 @@ class NetworkPlotter:
|
|
760
768
|
domain_centroids[domain_id] = self._calculate_domain_centroid(node_ids)
|
761
769
|
|
762
770
|
# Initialize dictionaries and lists for valid indices
|
763
|
-
valid_indices = []
|
764
|
-
filtered_domain_centroids = {}
|
765
|
-
filtered_domain_terms = {}
|
771
|
+
valid_indices = [] # List of valid indices to plot colors and arrows
|
772
|
+
filtered_domain_centroids = {} # Filtered domain centroids to plot
|
773
|
+
filtered_domain_terms = {} # Filtered domain terms to plot
|
766
774
|
# Handle the ids_to_keep logic
|
767
775
|
if ids_to_keep:
|
768
776
|
# Process the ids_to_keep first INPLACE
|
769
777
|
self._process_ids_to_keep(
|
770
|
-
ids_to_keep,
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
filtered_domain_centroids,
|
780
|
-
filtered_domain_terms,
|
781
|
-
valid_indices,
|
778
|
+
ids_to_keep=ids_to_keep,
|
779
|
+
domain_centroids=domain_centroids,
|
780
|
+
ids_to_replace=ids_to_replace,
|
781
|
+
words_to_omit=words_to_omit,
|
782
|
+
max_labels=max_labels,
|
783
|
+
min_label_lines=min_label_lines,
|
784
|
+
max_label_lines=max_label_lines,
|
785
|
+
min_chars_per_line=min_chars_per_line,
|
786
|
+
max_chars_per_line=max_chars_per_line,
|
787
|
+
filtered_domain_centroids=filtered_domain_centroids,
|
788
|
+
filtered_domain_terms=filtered_domain_terms,
|
789
|
+
valid_indices=valid_indices,
|
782
790
|
)
|
783
791
|
|
784
792
|
# Calculate remaining labels to plot after processing ids_to_keep
|
785
793
|
remaining_labels = (
|
786
|
-
max_labels - len(
|
794
|
+
max_labels - len(valid_indices) if valid_indices and max_labels else max_labels
|
787
795
|
)
|
788
796
|
# Process remaining domains INPLACE to fill in additional labels, if there are slots left
|
789
797
|
if remaining_labels and remaining_labels > 0:
|
790
798
|
self._process_remaining_domains(
|
791
|
-
domain_centroids,
|
792
|
-
ids_to_keep,
|
793
|
-
ids_to_replace,
|
794
|
-
words_to_omit,
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
filtered_domain_centroids,
|
801
|
-
filtered_domain_terms,
|
802
|
-
valid_indices,
|
799
|
+
domain_centroids=domain_centroids,
|
800
|
+
ids_to_keep=ids_to_keep,
|
801
|
+
ids_to_replace=ids_to_replace,
|
802
|
+
words_to_omit=words_to_omit,
|
803
|
+
remaining_labels=remaining_labels,
|
804
|
+
min_chars_per_line=min_chars_per_line,
|
805
|
+
max_chars_per_line=max_chars_per_line,
|
806
|
+
max_label_lines=max_label_lines,
|
807
|
+
min_label_lines=min_label_lines,
|
808
|
+
filtered_domain_centroids=filtered_domain_centroids,
|
809
|
+
filtered_domain_terms=filtered_domain_terms,
|
810
|
+
valid_indices=valid_indices,
|
803
811
|
)
|
804
812
|
|
805
813
|
# Calculate the bounding box around the network
|
@@ -819,8 +827,8 @@ class NetworkPlotter:
|
|
819
827
|
# Annotate the network with labels
|
820
828
|
for idx, (domain, pos) in zip(valid_indices, best_label_positions.items()):
|
821
829
|
centroid = filtered_domain_centroids[domain]
|
822
|
-
# Split by special key to split annotation into multiple lines
|
823
|
-
annotations = filtered_domain_terms[domain].split(
|
830
|
+
# Split by special key TERM_DELIMITER to split annotation into multiple lines
|
831
|
+
annotations = filtered_domain_terms[domain].split(TERM_DELIMITER)
|
824
832
|
self.ax.annotate(
|
825
833
|
"\n".join(annotations),
|
826
834
|
xy=centroid,
|
@@ -969,15 +977,15 @@ class NetworkPlotter:
|
|
969
977
|
|
970
978
|
def _process_ids_to_keep(
|
971
979
|
self,
|
972
|
-
ids_to_keep: Union[List[str], Tuple[str], np.ndarray
|
973
|
-
max_labels: Union[int, None],
|
980
|
+
ids_to_keep: Union[List[str], Tuple[str], np.ndarray],
|
974
981
|
domain_centroids: Dict[str, np.ndarray],
|
975
982
|
ids_to_replace: Union[Dict[str, str], None],
|
976
983
|
words_to_omit: Union[List[str], None],
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
984
|
+
max_labels: Union[int, None],
|
985
|
+
min_label_lines: int,
|
986
|
+
max_label_lines: int,
|
987
|
+
min_chars_per_line: int,
|
988
|
+
max_chars_per_line: int,
|
981
989
|
filtered_domain_centroids: Dict[str, np.ndarray],
|
982
990
|
filtered_domain_terms: Dict[str, str],
|
983
991
|
valid_indices: List[int],
|
@@ -985,15 +993,15 @@ class NetworkPlotter:
|
|
985
993
|
"""Process the ids_to_keep, apply filtering, and store valid domain centroids and terms.
|
986
994
|
|
987
995
|
Args:
|
988
|
-
ids_to_keep (list, tuple, np.ndarray,
|
989
|
-
max_labels (int, optional): Maximum number of labels allowed.
|
996
|
+
ids_to_keep (list, tuple, or np.ndarray, optional): IDs of domains that must be labeled.
|
990
997
|
domain_centroids (dict): Mapping of domains to their centroids.
|
991
998
|
ids_to_replace (dict, optional): A dictionary mapping domain IDs to custom labels. Defaults to None.
|
992
999
|
words_to_omit (list, optional): List of words to omit from the labels. Defaults to None.
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
1000
|
+
max_labels (int, optional): Maximum number of labels allowed.
|
1001
|
+
min_label_lines (int): Minimum number of lines in a label.
|
1002
|
+
max_label_lines (int): Maximum number of lines in a label.
|
1003
|
+
min_chars_per_line (int): Minimum number of characters in a line to display.
|
1004
|
+
max_chars_per_line (int): Maximum number of characters in a line to display.
|
997
1005
|
filtered_domain_centroids (dict): Dictionary to store filtered domain centroids (output).
|
998
1006
|
filtered_domain_terms (dict): Dictionary to store filtered domain terms (output).
|
999
1007
|
valid_indices (list): List to store valid indices (output).
|
@@ -1004,8 +1012,6 @@ class NetworkPlotter:
|
|
1004
1012
|
Raises:
|
1005
1013
|
ValueError: If the number of provided `ids_to_keep` exceeds `max_labels`.
|
1006
1014
|
"""
|
1007
|
-
# Convert ids_to_keep to a set for faster, unique lookups
|
1008
|
-
ids_to_keep = set(ids_to_keep) if ids_to_keep else set()
|
1009
1015
|
# Check if the number of provided ids_to_keep exceeds max_labels
|
1010
1016
|
if max_labels is not None and len(ids_to_keep) > max_labels:
|
1011
1017
|
raise ValueError(
|
@@ -1015,77 +1021,125 @@ class NetworkPlotter:
|
|
1015
1021
|
# Process each domain in ids_to_keep
|
1016
1022
|
for domain in ids_to_keep:
|
1017
1023
|
if domain in self.graph.domain_id_to_domain_terms_map and domain in domain_centroids:
|
1018
|
-
|
1024
|
+
domain_terms = self._process_terms(
|
1019
1025
|
domain=domain,
|
1020
1026
|
ids_to_replace=ids_to_replace,
|
1021
1027
|
words_to_omit=words_to_omit,
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1028
|
+
max_label_lines=max_label_lines,
|
1029
|
+
min_chars_per_line=min_chars_per_line,
|
1030
|
+
max_chars_per_line=max_chars_per_line,
|
1025
1031
|
)
|
1026
|
-
|
1027
|
-
|
1032
|
+
num_domain_lines = len(domain_terms.split(TERM_DELIMITER))
|
1033
|
+
# Check if the number of lines in the label is greater than or equal to the minimum
|
1034
|
+
if num_domain_lines >= min_label_lines:
|
1035
|
+
filtered_domain_terms[domain] = domain_terms
|
1036
|
+
filtered_domain_centroids[domain] = domain_centroids[domain]
|
1037
|
+
valid_indices.append(list(domain_centroids.keys()).index(domain))
|
1028
1038
|
|
1029
1039
|
def _process_remaining_domains(
|
1030
1040
|
self,
|
1031
1041
|
domain_centroids: Dict[str, np.ndarray],
|
1032
|
-
ids_to_keep: Union[List[str], Tuple[str], np.ndarray
|
1042
|
+
ids_to_keep: Union[List[str], Tuple[str], np.ndarray],
|
1033
1043
|
ids_to_replace: Union[Dict[str, str], None],
|
1034
1044
|
words_to_omit: Union[List[str], None],
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1045
|
+
remaining_labels: int,
|
1046
|
+
min_label_lines: int,
|
1047
|
+
max_label_lines: int,
|
1048
|
+
min_chars_per_line: int,
|
1049
|
+
max_chars_per_line: int,
|
1040
1050
|
filtered_domain_centroids: Dict[str, np.ndarray],
|
1041
1051
|
filtered_domain_terms: Dict[str, str],
|
1042
1052
|
valid_indices: List[int],
|
1043
1053
|
) -> None:
|
1044
|
-
"""Process remaining domains to fill in additional labels,
|
1054
|
+
"""Process remaining domains to fill in additional labels, respecting the remaining_labels limit.
|
1045
1055
|
|
1046
1056
|
Args:
|
1047
1057
|
domain_centroids (dict): Mapping of domains to their centroids.
|
1048
|
-
ids_to_keep (list, tuple, np.ndarray,
|
1058
|
+
ids_to_keep (list, tuple, or np.ndarray, optional): IDs of domains that must be labeled.
|
1049
1059
|
ids_to_replace (dict, optional): A dictionary mapping domain IDs to custom labels. Defaults to None.
|
1050
1060
|
words_to_omit (list, optional): List of words to omit from the labels. Defaults to None.
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1061
|
+
remaining_labels (int): The remaining number of labels that can be generated.
|
1062
|
+
min_label_lines (int): Minimum number of lines in a label.
|
1063
|
+
max_label_lines (int): Maximum number of lines in a label.
|
1064
|
+
min_chars_per_line (int): Minimum number of characters in a line to display.
|
1065
|
+
max_chars_per_line (int): Maximum number of characters in a line to display.
|
1056
1066
|
filtered_domain_centroids (dict): Dictionary to store filtered domain centroids (output).
|
1057
1067
|
filtered_domain_terms (dict): Dictionary to store filtered domain terms (output).
|
1058
1068
|
valid_indices (list): List to store valid indices (output).
|
1059
|
-
|
1060
|
-
Note:
|
1061
|
-
The `filtered_domain_centroids`, `filtered_domain_terms`, and `valid_indices` are modified in-place.
|
1062
1069
|
"""
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1070
|
+
# Counter to track how many labels have been created
|
1071
|
+
label_count = 0
|
1072
|
+
# Collect domains not in ids_to_keep
|
1073
|
+
remaining_domains = {
|
1074
|
+
domain: centroid
|
1075
|
+
for domain, centroid in domain_centroids.items()
|
1076
|
+
if domain not in ids_to_keep and not pd.isna(domain)
|
1077
|
+
}
|
1078
|
+
|
1079
|
+
# Function to calculate distance between two centroids
|
1080
|
+
def calculate_distance(centroid1, centroid2):
|
1081
|
+
return np.linalg.norm(centroid1 - centroid2)
|
1082
|
+
|
1083
|
+
# Find the farthest apart domains using centroids
|
1084
|
+
if remaining_domains and remaining_labels:
|
1085
|
+
selected_domains = []
|
1086
|
+
first_domain = next(iter(remaining_domains)) # Pick the first domain to start
|
1087
|
+
selected_domains.append(first_domain)
|
1088
|
+
|
1089
|
+
while len(selected_domains) < remaining_labels:
|
1090
|
+
farthest_domain = None
|
1091
|
+
max_distance = -1
|
1092
|
+
# Find the domain farthest from any already selected domain
|
1093
|
+
for candidate_domain, candidate_centroid in remaining_domains.items():
|
1094
|
+
if candidate_domain in selected_domains:
|
1095
|
+
continue
|
1096
|
+
|
1097
|
+
# Calculate the minimum distance to any selected domain
|
1098
|
+
min_distance = min(
|
1099
|
+
calculate_distance(candidate_centroid, remaining_domains[dom])
|
1100
|
+
for dom in selected_domains
|
1101
|
+
)
|
1102
|
+
# Update the farthest domain if the minimum distance is greater
|
1103
|
+
if min_distance > max_distance:
|
1104
|
+
max_distance = min_distance
|
1105
|
+
farthest_domain = candidate_domain
|
1106
|
+
|
1107
|
+
# Add the farthest domain to the selected domains
|
1108
|
+
if farthest_domain:
|
1109
|
+
selected_domains.append(farthest_domain)
|
1110
|
+
else:
|
1111
|
+
break # No more domains to select
|
1112
|
+
|
1113
|
+
# Process the selected domains and add to filtered lists
|
1114
|
+
for domain in selected_domains:
|
1115
|
+
centroid = remaining_domains[domain]
|
1116
|
+
domain_terms = self._process_terms(
|
1071
1117
|
domain=domain,
|
1072
1118
|
ids_to_replace=ids_to_replace,
|
1073
1119
|
words_to_omit=words_to_omit,
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1120
|
+
max_label_lines=max_label_lines,
|
1121
|
+
min_chars_per_line=min_chars_per_line,
|
1122
|
+
max_chars_per_line=max_chars_per_line,
|
1077
1123
|
)
|
1078
|
-
|
1079
|
-
|
1124
|
+
num_domain_lines = len(domain_terms.split(TERM_DELIMITER))
|
1125
|
+
# Check if the number of lines in the label is greater than or equal to the minimum
|
1126
|
+
if num_domain_lines >= min_label_lines:
|
1127
|
+
filtered_domain_centroids[domain] = centroid
|
1128
|
+
filtered_domain_terms[domain] = domain_terms
|
1129
|
+
valid_indices.append(list(domain_centroids.keys()).index(domain))
|
1130
|
+
|
1131
|
+
label_count += 1
|
1132
|
+
if label_count >= remaining_labels:
|
1133
|
+
break
|
1080
1134
|
|
1081
1135
|
def _process_terms(
|
1082
1136
|
self,
|
1083
1137
|
domain: str,
|
1084
1138
|
ids_to_replace: Union[Dict[str, str], None],
|
1085
1139
|
words_to_omit: Union[List[str], None],
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1140
|
+
max_label_lines: int,
|
1141
|
+
min_chars_per_line: int,
|
1142
|
+
max_chars_per_line: int,
|
1089
1143
|
) -> List[str]:
|
1090
1144
|
"""Process terms for a domain, applying word length constraints and combining words where appropriate.
|
1091
1145
|
|
@@ -1093,9 +1147,9 @@ class NetworkPlotter:
|
|
1093
1147
|
domain (str): The domain being processed.
|
1094
1148
|
ids_to_replace (dict, optional): Dictionary mapping domain IDs to custom labels.
|
1095
1149
|
words_to_omit (list, optional): List of words to omit from the labels.
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1150
|
+
max_label_lines (int): Maximum number of lines in a label.
|
1151
|
+
min_chars_per_line (int): Minimum number of characters in a line to display.
|
1152
|
+
max_chars_per_line (int): Maximum number of characters in a line to display.
|
1099
1153
|
|
1100
1154
|
Returns:
|
1101
1155
|
list: Processed terms, with words combined if necessary to fit within constraints.
|
@@ -1111,11 +1165,11 @@ class NetworkPlotter:
|
|
1111
1165
|
terms = [
|
1112
1166
|
term
|
1113
1167
|
for term in terms
|
1114
|
-
if term.lower() not in words_to_omit and len(term) >=
|
1168
|
+
if term.lower() not in words_to_omit and len(term) >= min_chars_per_line
|
1115
1169
|
]
|
1116
1170
|
|
1117
1171
|
# Use the combine_words function directly to handle word combinations and length constraints
|
1118
|
-
compressed_terms = _combine_words(tuple(terms),
|
1172
|
+
compressed_terms = _combine_words(tuple(terms), max_chars_per_line, max_label_lines)
|
1119
1173
|
|
1120
1174
|
return compressed_terms
|
1121
1175
|
|
@@ -1433,14 +1487,14 @@ def _calculate_bounding_box(
|
|
1433
1487
|
return center, radius
|
1434
1488
|
|
1435
1489
|
|
1436
|
-
def _combine_words(words: List[str], max_length: int,
|
1437
|
-
"""Combine words to fit within the max_length and
|
1490
|
+
def _combine_words(words: List[str], max_length: int, max_label_lines: int) -> str:
|
1491
|
+
"""Combine words to fit within the max_length and max_label_lines constraints,
|
1438
1492
|
and separate the final output by ':' for plotting.
|
1439
1493
|
|
1440
1494
|
Args:
|
1441
1495
|
words (List[str]): List of words to combine.
|
1442
1496
|
max_length (int): Maximum allowed length for a combined line.
|
1443
|
-
|
1497
|
+
max_label_lines (int): Maximum number of lines in a label.
|
1444
1498
|
|
1445
1499
|
Returns:
|
1446
1500
|
str: String of combined words separated by ':' for line breaks.
|
@@ -1465,25 +1519,25 @@ def _combine_words(words: List[str], max_length: int, max_words: int) -> str:
|
|
1465
1519
|
combined_lines.append(combined_word) # Add the combined word or single word
|
1466
1520
|
i += 1 # Move to the next word
|
1467
1521
|
|
1468
|
-
# Stop if we've reached the
|
1469
|
-
if len(combined_lines) >=
|
1522
|
+
# Stop if we've reached the max_label_lines limit
|
1523
|
+
if len(combined_lines) >= max_label_lines:
|
1470
1524
|
break
|
1471
1525
|
|
1472
1526
|
return combined_lines
|
1473
1527
|
|
1474
|
-
# Main logic: start with
|
1475
|
-
combined_lines = try_combinations(words[:
|
1476
|
-
remaining_words = words[
|
1528
|
+
# Main logic: start with max_label_lines number of words
|
1529
|
+
combined_lines = try_combinations(words[:max_label_lines])
|
1530
|
+
remaining_words = words[max_label_lines:] # Remaining words after the initial batch
|
1477
1531
|
|
1478
1532
|
# Continue pulling more words until we fill the lines
|
1479
|
-
while remaining_words and len(combined_lines) <
|
1480
|
-
available_slots =
|
1533
|
+
while remaining_words and len(combined_lines) < max_label_lines:
|
1534
|
+
available_slots = max_label_lines - len(combined_lines)
|
1481
1535
|
words_to_add = remaining_words[:available_slots]
|
1482
1536
|
remaining_words = remaining_words[available_slots:]
|
1483
1537
|
combined_lines += try_combinations(words_to_add)
|
1484
1538
|
|
1485
|
-
# Join the final combined lines with
|
1486
|
-
return
|
1539
|
+
# Join the final combined lines with TERM_DELIMITER, a special separator for line breaks
|
1540
|
+
return TERM_DELIMITER.join(combined_lines[:max_label_lines])
|
1487
1541
|
|
1488
1542
|
|
1489
1543
|
def _calculate_best_label_positions(
|
@@ -1,4 +1,4 @@
|
|
1
|
-
risk/__init__.py,sha256=
|
1
|
+
risk/__init__.py,sha256=qjjV3tZUr6CjlV98T9q2oJFgjLB5qxwKFQm6MkwQc2s,112
|
2
2
|
risk/constants.py,sha256=XInRaH78Slnw_sWgAsBFbUHkyA0h0jL0DKGuQNbOvjM,550
|
3
3
|
risk/risk.py,sha256=FaQhDCBZxZSAXJsScH0rSbjjCTNZA5vgf9rJj1GHW44,20924
|
4
4
|
risk/annotations/__init__.py,sha256=vUpVvMRE5if01Ic8QY6M2Ae3EFGJHdugEe9PdEkAW4Y,138
|
@@ -15,7 +15,7 @@ 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.py,sha256=
|
18
|
+
risk/network/plot.py,sha256=uDRQTza5scBJKFTlcayFgA7nzWfz-c075J_V7k8eyBI,78285
|
19
19
|
risk/stats/__init__.py,sha256=WcgoETQ-hS0LQqKRsAMIPtP15xZ-4eul6VUBuUx4Wzc,220
|
20
20
|
risk/stats/hypergeom.py,sha256=o6Qnj31gCAKxr2uQirXrbv7XvdDJGEq69MFW-ubx_hA,2272
|
21
21
|
risk/stats/poisson.py,sha256=8x9hB4DCukq4gNIlIKO-c_jYG1-BTwTX53oLauFyfj8,1793
|
@@ -23,8 +23,8 @@ risk/stats/stats.py,sha256=kvShov-94W6ffgDUTb522vB9hDJQSyTsYif_UIaFfSM,7059
|
|
23
23
|
risk/stats/permutation/__init__.py,sha256=neJp7FENC-zg_CGOXqv-iIvz1r5XUKI9Ruxhmq7kDOI,105
|
24
24
|
risk/stats/permutation/permutation.py,sha256=D84Rcpt6iTQniK0PfQGcw9bLcHbMt9p-ARcurUnIXZQ,10095
|
25
25
|
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.
|
26
|
+
risk_network-0.0.8b3.dist-info/LICENSE,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
27
|
+
risk_network-0.0.8b3.dist-info/METADATA,sha256=cUY2Uidk8Bqhj1sWs25aIACjI2QrMXhL42oZQdHSBMo,47450
|
28
|
+
risk_network-0.0.8b3.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
29
|
+
risk_network-0.0.8b3.dist-info/top_level.txt,sha256=NX7C2PFKTvC1JhVKv14DFlFAIFnKc6Lpsu1ZfxvQwVw,5
|
30
|
+
risk_network-0.0.8b3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|