MatplotLibAPI 3.2.13__py3-none-any.whl → 3.2.14__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.
- MatplotLibAPI/Bubble.py +413 -136
- MatplotLibAPI/Composite.py +139 -140
- MatplotLibAPI/Network.py +755 -339
- MatplotLibAPI/Pivot.py +115 -194
- MatplotLibAPI/StyleTemplate.py +237 -296
- MatplotLibAPI/Table.py +185 -56
- MatplotLibAPI/Timeserie.py +292 -78
- MatplotLibAPI/Treemap.py +133 -75
- MatplotLibAPI/Wordcloud.py +314 -0
- MatplotLibAPI/__init__.py +838 -313
- {matplotlibapi-3.2.13.dist-info → matplotlibapi-3.2.14.dist-info}/METADATA +16 -9
- matplotlibapi-3.2.14.dist-info/RECORD +14 -0
- {matplotlibapi-3.2.13.dist-info → matplotlibapi-3.2.14.dist-info}/WHEEL +1 -2
- matplotlibapi-3.2.13.dist-info/RECORD +0 -14
- matplotlibapi-3.2.13.dist-info/top_level.txt +0 -1
- {matplotlibapi-3.2.13.dist-info → matplotlibapi-3.2.14.dist-info}/licenses/LICENSE +0 -0
MatplotLibAPI/StyleTemplate.py
CHANGED
|
@@ -1,117 +1,114 @@
|
|
|
1
|
+
"""Common style utilities and formatters for plotting."""
|
|
1
2
|
|
|
2
|
-
|
|
3
|
-
from typing import List, Optional, Dict, Callable, Union
|
|
4
3
|
from dataclasses import dataclass
|
|
5
|
-
import
|
|
6
|
-
import numpy as np
|
|
4
|
+
from typing import Callable, Dict, List, Optional, Union, cast
|
|
7
5
|
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pandas as pd
|
|
8
8
|
from matplotlib.dates import num2date
|
|
9
9
|
from matplotlib.ticker import FuncFormatter
|
|
10
10
|
|
|
11
|
-
#
|
|
11
|
+
# Type alias for formatter functions compatible with matplotlib tick formatters
|
|
12
|
+
FormatterFunc = Callable[[Union[int, float, str], Optional[int]], str]
|
|
12
13
|
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
>>> validate_dataframe(df, ['A'], sort_by='C') # Raises AttributeError
|
|
15
|
+
# region Validation
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def validate_dataframe(
|
|
19
|
+
pd_df: pd.DataFrame, cols: List[str], sort_by: Optional[str] = None
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Ensure required columns and optional sort column exist in a DataFrame.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
pd_df : pd.DataFrame
|
|
26
|
+
The DataFrame to validate.
|
|
27
|
+
cols : list[str]
|
|
28
|
+
Required column names.
|
|
29
|
+
sort_by : str, optional
|
|
30
|
+
Optional column used for sorting.
|
|
31
|
+
|
|
32
|
+
Raises
|
|
33
|
+
------
|
|
34
|
+
AttributeError
|
|
35
|
+
If any column is missing.
|
|
36
36
|
"""
|
|
37
|
-
|
|
38
|
-
if sort_by
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
required_cols = set(cols)
|
|
38
|
+
if sort_by:
|
|
39
|
+
required_cols.add(sort_by)
|
|
40
|
+
missing = required_cols - set(pd_df.columns)
|
|
41
|
+
if missing:
|
|
42
|
+
raise AttributeError(f"Missing columns in DataFrame: {missing}")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# endregion
|
|
46
|
+
|
|
47
|
+
# region Format Dispatcher
|
|
43
48
|
|
|
44
49
|
|
|
45
50
|
def format_func(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Parameters
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
>>> format_funcs = {
|
|
72
|
-
... "label": lambda x: f"Label: {x}",
|
|
73
|
-
... "x": lambda x: f"X-axis: {x}",
|
|
74
|
-
... "y": lambda y: f"Y-axis: {y}",
|
|
75
|
-
... }
|
|
76
|
-
>>> updated_funcs = format_func(format_funcs, label="new_label", x="new_x")
|
|
77
|
-
>>> print(updated_funcs)
|
|
78
|
-
{
|
|
79
|
-
"label": lambda x: f"Label: {x}",
|
|
80
|
-
"x": lambda x: f"X-axis: {x}",
|
|
81
|
-
"y": lambda y: f"Y-axis: {y}",
|
|
82
|
-
"new_label": lambda x: f"Label: {x}",
|
|
83
|
-
"new_x": lambda x: f"X-axis: {x}",
|
|
84
|
-
}
|
|
51
|
+
format_funcs: Optional[Dict[str, Optional[FormatterFunc]]],
|
|
52
|
+
label: Optional[str] = None,
|
|
53
|
+
x: Optional[str] = None,
|
|
54
|
+
y: Optional[str] = None,
|
|
55
|
+
z: Optional[str] = None,
|
|
56
|
+
) -> Optional[Dict[str, Optional[FormatterFunc]]]:
|
|
57
|
+
"""Map shared formatters to specific keys if provided.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
format_funcs : dict[str, FormatterFunc], optional
|
|
62
|
+
Dictionary of formatting functions.
|
|
63
|
+
label : str, optional
|
|
64
|
+
Label column name.
|
|
65
|
+
x : str, optional
|
|
66
|
+
X-axis column name.
|
|
67
|
+
y : str, optional
|
|
68
|
+
Y-axis column name.
|
|
69
|
+
z : str, optional
|
|
70
|
+
Z-axis column name.
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
dict[str, FormatterFunc], optional
|
|
75
|
+
Updated format function dictionary.
|
|
85
76
|
"""
|
|
77
|
+
if not format_funcs:
|
|
78
|
+
return None
|
|
86
79
|
|
|
87
|
-
|
|
88
|
-
format_funcs[label] = format_funcs["label"]
|
|
89
|
-
if x and "x" in format_funcs:
|
|
90
|
-
format_funcs[x] = format_funcs["x"]
|
|
91
|
-
if y and "y" in format_funcs:
|
|
92
|
-
format_funcs[y] = format_funcs["y"]
|
|
93
|
-
if z and "z" in format_funcs:
|
|
94
|
-
format_funcs[z] = format_funcs["z"]
|
|
95
|
-
return format_funcs
|
|
80
|
+
new_format_funcs = format_funcs.copy()
|
|
96
81
|
|
|
97
|
-
|
|
82
|
+
for generic, specific in {"label": label, "x": x, "y": y, "z": z}.items():
|
|
83
|
+
if specific and generic in new_format_funcs:
|
|
84
|
+
new_format_funcs[specific] = new_format_funcs[generic]
|
|
85
|
+
return new_format_funcs
|
|
98
86
|
|
|
99
|
-
# region Style
|
|
100
87
|
|
|
88
|
+
# endregion
|
|
101
89
|
|
|
90
|
+
# region Style Constants
|
|
102
91
|
|
|
103
92
|
FIG_SIZE = (19.2, 10.8)
|
|
104
|
-
BACKGROUND_COLOR =
|
|
105
|
-
TEXT_COLOR =
|
|
93
|
+
BACKGROUND_COLOR = "black"
|
|
94
|
+
TEXT_COLOR = "white"
|
|
106
95
|
PALETTE = "Greys_r"
|
|
107
96
|
FONT_SIZE = 14
|
|
97
|
+
MAX_RESULTS = 50
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# endregion
|
|
101
|
+
|
|
102
|
+
# region Style Template
|
|
108
103
|
|
|
109
104
|
|
|
110
105
|
@dataclass
|
|
111
106
|
class StyleTemplate:
|
|
107
|
+
"""Configuration container for plot styling options."""
|
|
108
|
+
|
|
112
109
|
background_color: str = BACKGROUND_COLOR
|
|
113
110
|
fig_border: str = BACKGROUND_COLOR
|
|
114
|
-
font_name: str =
|
|
111
|
+
font_name: str = "Arial"
|
|
115
112
|
font_size: int = FONT_SIZE
|
|
116
113
|
font_color: str = TEXT_COLOR
|
|
117
114
|
palette: str = PALETTE
|
|
@@ -120,249 +117,193 @@ class StyleTemplate:
|
|
|
120
117
|
x_ticks: int = 5
|
|
121
118
|
yscale: Optional[str] = None
|
|
122
119
|
y_ticks: int = 5
|
|
123
|
-
format_funcs: Optional[Dict[str, Optional[
|
|
124
|
-
Union[int, float, str]], str]]]] = None
|
|
120
|
+
format_funcs: Optional[Dict[str, Optional[FormatterFunc]]] = None
|
|
125
121
|
col_widths: Optional[List[float]] = None
|
|
126
|
-
"""
|
|
127
|
-
A class to define style templates for data visualization with customizable attributes.
|
|
128
|
-
|
|
129
|
-
Attributes:
|
|
130
|
-
background_color (str):
|
|
131
|
-
The background color for the visualizations. Default is BACKGROUND_COLOR.
|
|
132
|
-
fig_border (str):
|
|
133
|
-
The border color for the figures. Default is BACKGROUND_COLOR.
|
|
134
|
-
font_name (str):
|
|
135
|
-
The name of the font to use. Default is 'Arial'.
|
|
136
|
-
font_size (int):
|
|
137
|
-
The base size of the font. Default is FONT_SIZE.
|
|
138
|
-
font_color (str):
|
|
139
|
-
The color of the font. Default is TEXT_COLOR.
|
|
140
|
-
palette (str):
|
|
141
|
-
The color palette to use. Default is PALETTE.
|
|
142
|
-
legend (bool):
|
|
143
|
-
A flag to determine if the legend should be displayed. Default is True.
|
|
144
|
-
xscale (Optional[str]):
|
|
145
|
-
The scale type for the x-axis. Default is None.
|
|
146
|
-
x_ticks (int):
|
|
147
|
-
The number of ticks on the x-axis. Default is 10.
|
|
148
|
-
yscale (Optional[str]):
|
|
149
|
-
The scale type for the y-axis. Default is None.
|
|
150
|
-
y_ticks (int):
|
|
151
|
-
The number of ticks on the y-axis. Default is 5.
|
|
152
|
-
format_funcs (Optional[Dict[str, Optional[Callable[[Union[int, float, str]], str]]]]):
|
|
153
|
-
A dictionary mapping data keys to formatting functions. Default is None.
|
|
154
|
-
col_widths (Optional[List[float]]):
|
|
155
|
-
A list of column widths. Default is None.
|
|
156
|
-
|
|
157
|
-
Properties:
|
|
158
|
-
font_mapping (dict):
|
|
159
|
-
A dictionary mapping font size levels to specific font sizes.
|
|
160
|
-
|
|
161
|
-
Example:
|
|
162
|
-
>>> template = StyleTemplate()
|
|
163
|
-
>>> template.font_mapping
|
|
164
|
-
{0: FONT_SIZE-3, 1: FONT_SIZE-1, 2: FONT_SIZE, 3: FONT_SIZE+1, 4: FONT_SIZE+3}
|
|
165
|
-
"""
|
|
166
|
-
@property
|
|
167
|
-
def font_mapping(self):
|
|
168
|
-
return {0: self.font_size-3,
|
|
169
|
-
1: self.font_size-1,
|
|
170
|
-
2: self.font_size,
|
|
171
|
-
3: self.font_size+1,
|
|
172
|
-
4: self.font_size+3}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
class DynamicFuncFormatter(FuncFormatter):
|
|
176
|
-
"""
|
|
177
|
-
A class to create a dynamic function formatter for matplotlib plots.
|
|
178
122
|
|
|
179
|
-
|
|
180
|
-
|
|
123
|
+
@property
|
|
124
|
+
def font_mapping(self) -> Dict[int, int]:
|
|
125
|
+
"""Map font levels to adjusted font sizes.
|
|
126
|
+
|
|
127
|
+
Returns
|
|
128
|
+
-------
|
|
129
|
+
dict[int, int]
|
|
130
|
+
Level to font size mapping.
|
|
131
|
+
"""
|
|
132
|
+
return {
|
|
133
|
+
0: self.font_size - 3,
|
|
134
|
+
1: self.font_size - 1,
|
|
135
|
+
2: self.font_size,
|
|
136
|
+
3: self.font_size + 1,
|
|
137
|
+
4: self.font_size + 3,
|
|
138
|
+
}
|
|
181
139
|
|
|
182
|
-
Parameters:
|
|
183
|
-
func_name (Callable): The function to be used for formatting.
|
|
184
140
|
|
|
185
|
-
|
|
186
|
-
>>> formatter = DynamicFuncFormatter(percent_formatter)
|
|
187
|
-
"""
|
|
188
|
-
def __init__(self, func_name):
|
|
189
|
-
super().__init__(func_name)
|
|
141
|
+
# endregion
|
|
190
142
|
|
|
143
|
+
# region Custom Formatters
|
|
191
144
|
|
|
192
|
-
def percent_formatter(val, pos: Optional[int] = None):
|
|
193
|
-
"""
|
|
194
|
-
Format a value as a percentage.
|
|
195
145
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
pos (Optional[int]): The position (not used).
|
|
199
|
-
|
|
200
|
-
Returns:
|
|
201
|
-
str: The formatted percentage string.
|
|
146
|
+
class DynamicFuncFormatter(FuncFormatter):
|
|
147
|
+
"""A wrapper for dynamic formatting functions."""
|
|
202
148
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
'1%'
|
|
206
|
-
"""
|
|
207
|
-
if val*100 <= 0.1: # For 0.1%
|
|
208
|
-
return f"{val*100:.2f}%"
|
|
209
|
-
elif val*100 <= 1: # For 1%
|
|
210
|
-
return f"{val*100:.1f}%"
|
|
211
|
-
else:
|
|
212
|
-
return f"{val*100:.0f}%"
|
|
149
|
+
def __init__(self, func_name: FormatterFunc):
|
|
150
|
+
"""Initialize the formatter.
|
|
213
151
|
|
|
152
|
+
Parameters
|
|
153
|
+
----------
|
|
154
|
+
func_name : FormatterFunc
|
|
155
|
+
A formatting function.
|
|
156
|
+
"""
|
|
157
|
+
super().__init__(func_name)
|
|
214
158
|
|
|
215
|
-
def bmk_formatter(val, pos: Optional[int] = None):
|
|
216
|
-
"""
|
|
217
|
-
Format a value as billions, millions, or thousands.
|
|
218
159
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
160
|
+
def percent_formatter(val: Union[int, float, str], pos: Optional[int] = None) -> str:
|
|
161
|
+
"""Format a value as a percentage."""
|
|
162
|
+
if isinstance(val, str):
|
|
163
|
+
val = float(val)
|
|
164
|
+
val *= 100
|
|
165
|
+
if val <= 0.1:
|
|
166
|
+
return f"{val:.2f}%"
|
|
167
|
+
elif val <= 1:
|
|
168
|
+
return f"{val:.1f}%"
|
|
169
|
+
return f"{val:.0f}%"
|
|
222
170
|
|
|
223
|
-
Returns:
|
|
224
|
-
str: The formatted string with B, M, or K suffix.
|
|
225
171
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
"""
|
|
230
|
-
if val >= 1_000_000_000: # Billions
|
|
172
|
+
def bmk_formatter(val: float, pos: Optional[int] = None) -> str:
|
|
173
|
+
"""Format large numbers using B, M, or K suffixes."""
|
|
174
|
+
if val >= 1_000_000_000:
|
|
231
175
|
return f"{val / 1_000_000_000:.2f}B"
|
|
232
|
-
elif val >= 1_000_000:
|
|
176
|
+
elif val >= 1_000_000:
|
|
233
177
|
return f"{val / 1_000_000:.1f}M"
|
|
234
|
-
elif val >= 1_000:
|
|
178
|
+
elif val >= 1_000:
|
|
235
179
|
return f"{val / 1_000:.1f}K"
|
|
236
|
-
|
|
237
|
-
return f"{int(val)}"
|
|
238
|
-
|
|
180
|
+
return str(int(val))
|
|
239
181
|
|
|
240
|
-
def integer_formatter(value, pos: Optional[int] = None):
|
|
241
|
-
"""
|
|
242
|
-
Format a value as an integer.
|
|
243
182
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
183
|
+
def integer_formatter(val: float, pos: Optional[int] = None) -> str:
|
|
184
|
+
"""Format a value as an integer."""
|
|
185
|
+
return str(int(val))
|
|
247
186
|
|
|
248
|
-
Returns:
|
|
249
|
-
str: The formatted integer string.
|
|
250
187
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
"""
|
|
255
|
-
return f"{int(value)}"
|
|
188
|
+
def string_formatter(val: Union[int, float, str], pos: Optional[int] = None) -> str:
|
|
189
|
+
"""Format a string to be title-case with spaces."""
|
|
190
|
+
return str(val).replace("-", " ").replace("_", " ").title()
|
|
256
191
|
|
|
257
192
|
|
|
258
|
-
def
|
|
259
|
-
"""
|
|
260
|
-
|
|
193
|
+
def yy_mm_formatter(x: float, pos: Optional[int] = None) -> str:
|
|
194
|
+
"""Format a float date value as YYYY-MM."""
|
|
195
|
+
return num2date(x).strftime("%Y-%m")
|
|
261
196
|
|
|
262
|
-
Parameters:
|
|
263
|
-
value (str): The string to format.
|
|
264
|
-
pos (Optional[int]): The position (not used).
|
|
265
197
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Example:
|
|
270
|
-
>>> string_formatter("example-string_formatter")
|
|
271
|
-
'Example String Formatter'
|
|
272
|
-
"""
|
|
273
|
-
return str(value).replace("-", " ").replace("_", " ").title()
|
|
198
|
+
def yy_mm_dd_formatter(x: float, pos: Optional[int] = None) -> str:
|
|
199
|
+
"""Format a float date value as YYYY-MM-DD."""
|
|
200
|
+
return num2date(x).strftime("%Y-%m-%d")
|
|
274
201
|
|
|
275
202
|
|
|
276
|
-
|
|
277
|
-
"""
|
|
278
|
-
Format a date as 'YYYY-MM'.
|
|
279
|
-
|
|
280
|
-
Parameters:
|
|
281
|
-
x (float): The value to format.
|
|
282
|
-
pos (Optional[int]): The position (not used).
|
|
283
|
-
|
|
284
|
-
Returns:
|
|
285
|
-
str: The formatted date string.
|
|
286
|
-
|
|
287
|
-
Example:
|
|
288
|
-
>>> yy_mm__formatter(737060)
|
|
289
|
-
'2020-01'
|
|
290
|
-
"""
|
|
291
|
-
return num2date(x).strftime('%Y-%m')
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
def yy_mm_dd__formatter(x, pos: Optional[int] = None):
|
|
295
|
-
"""
|
|
296
|
-
Format a date as 'YYYY-MM-DD'.
|
|
297
|
-
|
|
298
|
-
Parameters:
|
|
299
|
-
x (float): The value to format.
|
|
300
|
-
pos (Optional[int]): The position (not used).
|
|
301
|
-
|
|
302
|
-
Returns:
|
|
303
|
-
str: The formatted date string.
|
|
304
|
-
|
|
305
|
-
Example:
|
|
306
|
-
>>> yy_mm_dd__formatter(737060)
|
|
307
|
-
'2020-01-01'
|
|
308
|
-
"""
|
|
309
|
-
return num2date(x).strftime('%Y-%m-%D')
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
def generate_ticks(min_val, max_val, num_ticks:int=5):
|
|
313
|
-
"""
|
|
314
|
-
Generate tick marks for a given range.
|
|
315
|
-
|
|
316
|
-
Parameters:
|
|
317
|
-
min_val (Union[float, str]): The minimum value of the range.
|
|
318
|
-
max_val (Union[float, str]): The maximum value of the range.
|
|
319
|
-
num_ticks (int): The number of ticks to generate. Default is 10.
|
|
320
|
-
|
|
321
|
-
Returns:
|
|
322
|
-
np.ndarray: An array of tick marks.
|
|
203
|
+
# endregion
|
|
323
204
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
205
|
+
# region Tick Generator
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def generate_ticks(
|
|
209
|
+
min_val: Union[float, str, pd.Timestamp],
|
|
210
|
+
max_val: Union[float, str, pd.Timestamp],
|
|
211
|
+
num_ticks: int = 5,
|
|
212
|
+
) -> Union[np.ndarray, pd.DatetimeIndex]:
|
|
213
|
+
"""Generate evenly spaced ticks between min and max.
|
|
214
|
+
|
|
215
|
+
Parameters
|
|
216
|
+
----------
|
|
217
|
+
min_val : float | str | pd.Timestamp
|
|
218
|
+
Minimum value of range.
|
|
219
|
+
max_val : float | str | pd.Timestamp
|
|
220
|
+
Maximum value of range.
|
|
221
|
+
num_ticks : int
|
|
222
|
+
Number of tick marks.
|
|
223
|
+
|
|
224
|
+
Returns
|
|
225
|
+
-------
|
|
226
|
+
np.ndarray | pd.DatetimeIndex
|
|
227
|
+
Tick values.
|
|
327
228
|
"""
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
min_val = pd.Timestamp(min_val).to_datetime64()
|
|
341
|
-
max_val = pd.Timestamp(max_val).to_datetime64()
|
|
342
|
-
data_range = (max_val - min_val).astype('timedelta64[D]').astype(int)
|
|
229
|
+
min_val_f: float = 0.0
|
|
230
|
+
max_val_f: float = 0.0
|
|
231
|
+
|
|
232
|
+
if isinstance(min_val, (int, float, str)) and isinstance(
|
|
233
|
+
max_val, (int, float, str)
|
|
234
|
+
):
|
|
235
|
+
try:
|
|
236
|
+
min_val_f = float(min_val)
|
|
237
|
+
max_val_f = float(max_val)
|
|
238
|
+
is_date = False
|
|
239
|
+
except (ValueError, TypeError):
|
|
240
|
+
is_date = True
|
|
343
241
|
else:
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
# Calculate a nice step size
|
|
347
|
-
step_size = data_range / (num_ticks - 1)
|
|
242
|
+
is_date = True
|
|
348
243
|
|
|
349
|
-
# If date, convert back to datetime
|
|
350
244
|
if is_date:
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
245
|
+
min_ts = pd.Timestamp(min_val)
|
|
246
|
+
max_ts = pd.Timestamp(max_val)
|
|
247
|
+
if pd.isna(min_ts) or pd.isna(max_ts): # type: ignore
|
|
248
|
+
return pd.to_datetime([])
|
|
249
|
+
if min_ts == max_ts:
|
|
250
|
+
return pd.to_datetime([min_ts])
|
|
251
|
+
return pd.date_range(start=min_ts, end=max_ts, periods=num_ticks)
|
|
358
252
|
|
|
359
|
-
|
|
360
|
-
|
|
253
|
+
data_range = max_val_f - min_val_f
|
|
254
|
+
raw_step = data_range / (num_ticks - 1)
|
|
255
|
+
exponent = np.floor(np.log10(raw_step))
|
|
256
|
+
nice_step = round(raw_step / 10**exponent) * 10**exponent
|
|
257
|
+
return np.arange(min_val_f, max_val_f + nice_step, nice_step)
|
|
361
258
|
|
|
362
|
-
# Generate the tick marks based on the nice step size
|
|
363
|
-
ticks = np.arange(min_val, max_val + nice_step, nice_step)
|
|
364
|
-
|
|
365
|
-
return ticks
|
|
366
259
|
|
|
260
|
+
# endregion
|
|
367
261
|
|
|
262
|
+
# region Style Presets
|
|
263
|
+
|
|
264
|
+
BUBBLE_STYLE_TEMPLATE = StyleTemplate(
|
|
265
|
+
format_funcs=cast(
|
|
266
|
+
Dict[str, Optional[FormatterFunc]],
|
|
267
|
+
{
|
|
268
|
+
"label": string_formatter,
|
|
269
|
+
"x": bmk_formatter,
|
|
270
|
+
"y": percent_formatter,
|
|
271
|
+
"z": bmk_formatter,
|
|
272
|
+
},
|
|
273
|
+
),
|
|
274
|
+
yscale="log",
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
TIMESERIE_STYLE_TEMPLATE = StyleTemplate(
|
|
278
|
+
format_funcs=cast(
|
|
279
|
+
Dict[str, Optional[FormatterFunc]],
|
|
280
|
+
{"x": yy_mm_formatter, "y": bmk_formatter},
|
|
281
|
+
)
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
TABLE_STYLE_TEMPLATE = StyleTemplate()
|
|
285
|
+
|
|
286
|
+
TREEMAP_STYLE_TEMPLATE = StyleTemplate()
|
|
287
|
+
|
|
288
|
+
PIVOTBARS_STYLE_TEMPLATE = StyleTemplate(
|
|
289
|
+
background_color="black",
|
|
290
|
+
fig_border="darkgrey",
|
|
291
|
+
font_color="white",
|
|
292
|
+
palette="magma",
|
|
293
|
+
format_funcs=cast(
|
|
294
|
+
Dict[str, Optional[FormatterFunc]],
|
|
295
|
+
{"y": percent_formatter, "label": string_formatter},
|
|
296
|
+
),
|
|
297
|
+
)
|
|
298
|
+
PIVOTLINES_STYLE_TEMPLATE = StyleTemplate(
|
|
299
|
+
background_color="white",
|
|
300
|
+
fig_border="lightgrey",
|
|
301
|
+
palette="viridis",
|
|
302
|
+
format_funcs=cast(
|
|
303
|
+
Dict[str, Optional[FormatterFunc]],
|
|
304
|
+
{"y": percent_formatter, "label": string_formatter},
|
|
305
|
+
),
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
NETWORK_STYLE_TEMPLATE = StyleTemplate()
|
|
368
309
|
# endregion
|