mayutils 1.2.25__tar.gz → 1.2.28__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.
- {mayutils-1.2.25 → mayutils-1.2.28}/PKG-INFO +11 -1
- {mayutils-1.2.25 → mayutils-1.2.28}/pyproject.toml +29 -1
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/data/live.py +15 -4
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/data/queries/__init__.py +7 -2
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/data/read.py +6 -2
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/environment/logging.py +3 -1
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/environment/memoisation.py +4 -1
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/export/slides.py +8 -2
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/dataframes.py +30 -10
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/datetime.py +6 -2
- mayutils-1.2.28/src/mayutils/objects/strings.py +61 -0
- mayutils-1.2.28/src/mayutils/visualisation/graphs/plotly/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/graphs/plotly/charts.py +3 -3
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/graphs/plotly/traces.py +67 -21
- mayutils-1.2.25/src/mayutils/objects/strings.py +0 -7
- {mayutils-1.2.25 → mayutils-1.2.28}/LICENSE +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/README.md +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/core/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/core/constants.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/data/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/data/analysis/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/data/cache/.gitkeep +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/data/local.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/data/queries/.gitkeep +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/data/queries/examples/.gitkeep +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/environment/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/environment/benchmarking.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/environment/databases.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/environment/filesystem.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/environment/oauth.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/environment/secrets.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/environment/webdrivers.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/export/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/export/images.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/export/pdf.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/interfaces/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/interfaces/google.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/interfaces/microsoft.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/interfaces/streamlit.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/mathematics/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/mathematics/numba.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/mathematics/numpy.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/classes.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/colours.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/decorators.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/dictionaries.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/functions.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/hashing.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/numbers.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/objects/types.py +0 -0
- /mayutils-1.2.25/src/mayutils/scripts/__init__.py → /mayutils-1.2.28/src/mayutils/py.typed +0 -0
- {mayutils-1.2.25/src/mayutils/testing → mayutils-1.2.28/src/mayutils/scripts}/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/scripts/clear_cache.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/scripts/versioning.py +0 -0
- {mayutils-1.2.25/src/mayutils/visualisation → mayutils-1.2.28/src/mayutils/testing}/__init__.py +0 -0
- {mayutils-1.2.25/src/mayutils/visualisation/graphs/matplotlib → mayutils-1.2.28/src/mayutils/visualisation}/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/console.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/graphs/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/graphs/combine.py +0 -0
- {mayutils-1.2.25/src/mayutils/visualisation/graphs/plotly → mayutils-1.2.28/src/mayutils/visualisation/graphs/matplotlib}/__init__.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/graphs/matplotlib/template.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/graphs/plotly/templates.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/graphs/plotly/utilities.py +0 -0
- {mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/notebook.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: mayutils
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.28
|
|
4
4
|
Summary: Utilities for Python from Mayuran Visakan
|
|
5
5
|
Author: Mayuran Visakan
|
|
6
6
|
Author-email: Mayuran Visakan <mayuran.k.v@gmail.com>
|
|
@@ -70,13 +70,23 @@ Requires-Dist: requests>=2.32.5
|
|
|
70
70
|
Requires-Dist: rich>=14.1.0
|
|
71
71
|
Requires-Dist: scikit-learn>=1.7.1
|
|
72
72
|
Requires-Dist: scipy>=1.16.1
|
|
73
|
+
Requires-Dist: scipy-stubs>=1.16.2.4
|
|
73
74
|
Requires-Dist: selenium>=4.35.0
|
|
74
75
|
Requires-Dist: snowflake-connector-python[secure-local-storage]>=3.17.2
|
|
75
76
|
Requires-Dist: snowflake-sqlalchemy>=1.7.6
|
|
76
77
|
Requires-Dist: sqlalchemy>=2.0.43
|
|
77
78
|
Requires-Dist: streamlit>=1.49.0
|
|
78
79
|
Requires-Dist: typer
|
|
80
|
+
Requires-Dist: types-cachetools>=6.2.0.20251022
|
|
81
|
+
Requires-Dist: types-decorator>=5.2.0.20250324
|
|
82
|
+
Requires-Dist: types-openpyxl>=3.1.5.20250919
|
|
83
|
+
Requires-Dist: types-pycurl>=7.45.7.20250926
|
|
84
|
+
Requires-Dist: types-python-dateutil>=2.9.0.20251008
|
|
85
|
+
Requires-Dist: types-pyyaml>=6.0.12.20250915
|
|
86
|
+
Requires-Dist: types-requests>=2.32.4.20250913
|
|
87
|
+
Requires-Dist: types-simplejson>=3.20.0.20250822
|
|
79
88
|
Requires-Dist: types-six>=1.17.0.20250515
|
|
89
|
+
Requires-Dist: types-toml>=0.10.8.20240310
|
|
80
90
|
Requires-Dist: unicodeit>=0.7.5
|
|
81
91
|
Requires-Dist: watchdog>=6.0.0
|
|
82
92
|
Requires-Dist: coverage ; extra == 'dev'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mayutils"
|
|
3
|
-
version = "1.2.
|
|
3
|
+
version = "1.2.28"
|
|
4
4
|
description = "Utilities for Python from Mayuran Visakan"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Mayuran Visakan", email = "mayuran.k.v@gmail.com" }
|
|
@@ -57,13 +57,23 @@ dependencies = [
|
|
|
57
57
|
"rich>=14.1.0",
|
|
58
58
|
"scikit-learn>=1.7.1",
|
|
59
59
|
"scipy>=1.16.1",
|
|
60
|
+
"scipy-stubs>=1.16.2.4",
|
|
60
61
|
"selenium>=4.35.0",
|
|
61
62
|
"snowflake-connector-python[secure-local-storage]>=3.17.2",
|
|
62
63
|
"snowflake-sqlalchemy>=1.7.6",
|
|
63
64
|
"sqlalchemy>=2.0.43",
|
|
64
65
|
"streamlit>=1.49.0",
|
|
65
66
|
"typer",
|
|
67
|
+
"types-cachetools>=6.2.0.20251022",
|
|
68
|
+
"types-decorator>=5.2.0.20250324",
|
|
69
|
+
"types-openpyxl>=3.1.5.20250919",
|
|
70
|
+
"types-pycurl>=7.45.7.20250926",
|
|
71
|
+
"types-python-dateutil>=2.9.0.20251008",
|
|
72
|
+
"types-pyyaml>=6.0.12.20250915",
|
|
73
|
+
"types-requests>=2.32.4.20250913",
|
|
74
|
+
"types-simplejson>=3.20.0.20250822",
|
|
66
75
|
"types-six>=1.17.0.20250515",
|
|
76
|
+
"types-toml>=0.10.8.20240310",
|
|
67
77
|
"unicodeit>=0.7.5",
|
|
68
78
|
"watchdog>=6.0.0",
|
|
69
79
|
]
|
|
@@ -85,10 +95,28 @@ generate_encryption_key = "mayutils.environment.oauth:generate_fernet_key"
|
|
|
85
95
|
[tool.uv]
|
|
86
96
|
prerelease = "if-necessary-or-explicit"
|
|
87
97
|
|
|
98
|
+
[tool.uv.sources]
|
|
99
|
+
mayutils = { workspace = true }
|
|
100
|
+
|
|
88
101
|
[tool.pyright]
|
|
89
102
|
venvPath = "."
|
|
90
103
|
venv = ".venv"
|
|
91
104
|
|
|
105
|
+
[tool.mypy]
|
|
106
|
+
explicit_package_bases = true
|
|
107
|
+
|
|
108
|
+
|
|
92
109
|
[build-system]
|
|
93
110
|
requires = ["uv_build>=0.8.14,<0.9.0"]
|
|
94
111
|
build-backend = "uv_build"
|
|
112
|
+
|
|
113
|
+
[dependency-groups]
|
|
114
|
+
dev = [
|
|
115
|
+
"coverage>=7.11.0",
|
|
116
|
+
"ipdb>=0.13.13",
|
|
117
|
+
"mayutils",
|
|
118
|
+
"mypy>=1.18.2",
|
|
119
|
+
"pytest>=8.4.2",
|
|
120
|
+
"ruff>=0.14.2",
|
|
121
|
+
"ty>=0.0.1a24",
|
|
122
|
+
]
|
|
@@ -92,13 +92,17 @@ class LiveData(object):
|
|
|
92
92
|
engine: EngineWrapper,
|
|
93
93
|
) -> None:
|
|
94
94
|
new_interval = Interval(
|
|
95
|
-
start=(now - self.interval.as_duration())
|
|
95
|
+
start=(now - self.interval.as_duration())
|
|
96
|
+
if self.rolling
|
|
97
|
+
else self.interval.start,
|
|
96
98
|
end=now,
|
|
97
99
|
)
|
|
98
100
|
|
|
99
101
|
if self.rolling:
|
|
100
102
|
# elapsed_period = (previous_period[0], self.period[0])
|
|
101
|
-
self.data = self.data.loc[
|
|
103
|
+
self.data = self.data.loc[
|
|
104
|
+
self.data[self.index_column] >= new_interval.start.naive()
|
|
105
|
+
]
|
|
102
106
|
|
|
103
107
|
# new_period = (previous_period[1], self.period[1])»
|
|
104
108
|
additional_data = engine.read_pandas(
|
|
@@ -132,7 +136,11 @@ class LiveData(object):
|
|
|
132
136
|
if engine is None:
|
|
133
137
|
engine = self.engine
|
|
134
138
|
|
|
135
|
-
if
|
|
139
|
+
if (
|
|
140
|
+
force
|
|
141
|
+
or self.update_frequency is None
|
|
142
|
+
or ((now - self.interval.end) > self.update_frequency)
|
|
143
|
+
):
|
|
136
144
|
self._update(
|
|
137
145
|
now=now,
|
|
138
146
|
engine=engine,
|
|
@@ -143,7 +151,10 @@ class LiveData(object):
|
|
|
143
151
|
def _get_aggregated_data(
|
|
144
152
|
self,
|
|
145
153
|
) -> dict[str, DataFrame]:
|
|
146
|
-
self.aggregated_data = {
|
|
154
|
+
self.aggregated_data = {
|
|
155
|
+
aggregation_name: aggregation(self.data)
|
|
156
|
+
for aggregation_name, aggregation in self.aggregations.items()
|
|
157
|
+
}
|
|
147
158
|
|
|
148
159
|
return self.aggregated_data
|
|
149
160
|
|
|
@@ -11,7 +11,10 @@ def get_queries_folders() -> tuple[Path, ...]:
|
|
|
11
11
|
ROOT = get_root()
|
|
12
12
|
return (
|
|
13
13
|
ROOT / "queries",
|
|
14
|
-
*[
|
|
14
|
+
*[
|
|
15
|
+
ROOT / "src" / module / "data" / "queries"
|
|
16
|
+
for module in os.listdir(path=ROOT / "src")
|
|
17
|
+
],
|
|
15
18
|
Path(__file__).parent,
|
|
16
19
|
)
|
|
17
20
|
|
|
@@ -44,7 +47,9 @@ def get_query(
|
|
|
44
47
|
return read_file(path=path)
|
|
45
48
|
|
|
46
49
|
except ValueError:
|
|
47
|
-
raise ValueError(
|
|
50
|
+
raise ValueError(
|
|
51
|
+
f"No such query {query_name} found in the query folders {', '.join(list(map(str, queries_folders)))} or at the path {path}"
|
|
52
|
+
)
|
|
48
53
|
|
|
49
54
|
|
|
50
55
|
def get_formatted_query(
|
|
@@ -10,8 +10,8 @@ from mayutils.data import CACHE_FOLDER
|
|
|
10
10
|
from mayutils.data.queries import QUERIES_FOLDERS, get_formatted_query
|
|
11
11
|
from mayutils.environment.filesystem import encode_path
|
|
12
12
|
from mayutils.environment.memoisation import DataframeBackends
|
|
13
|
-
from mayutils.objects.dataframes import DataFrames, read_parquet, to_parquet
|
|
14
13
|
from mayutils.objects.hashing import hash_inputs
|
|
14
|
+
from mayutils.objects.dataframes import read_parquet, to_parquet, DataFrames
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
17
|
from functools import _lru_cache_wrapper as LRUCacheWrapper
|
|
@@ -58,7 +58,11 @@ def get_query_data(
|
|
|
58
58
|
cache: bool | Literal["persistent"] = True,
|
|
59
59
|
**format_kwargs,
|
|
60
60
|
) -> DataFrames:
|
|
61
|
-
if
|
|
61
|
+
if (
|
|
62
|
+
cache is False
|
|
63
|
+
and hasattr(read_query, "cache_clear")
|
|
64
|
+
and callable(getattr(read_query, "cache_clear"))
|
|
65
|
+
):
|
|
62
66
|
read_query.cache_clear()
|
|
63
67
|
|
|
64
68
|
cache_name = f"{encode_path(path=query_name)}_data_{
|
|
@@ -146,7 +146,9 @@ class Logger(logging.Logger):
|
|
|
146
146
|
level: Optional[Level] = None,
|
|
147
147
|
**kwargs,
|
|
148
148
|
) -> str:
|
|
149
|
-
level_int =
|
|
149
|
+
level_int = (
|
|
150
|
+
logging._nameToLevel.get(level, None) if isinstance(level, str) else level
|
|
151
|
+
)
|
|
150
152
|
if level_int is None:
|
|
151
153
|
level_int = self.getEffectiveLevel()
|
|
152
154
|
|
|
@@ -107,7 +107,10 @@ class cache(object):
|
|
|
107
107
|
**kwargs,
|
|
108
108
|
)
|
|
109
109
|
|
|
110
|
-
if
|
|
110
|
+
if (
|
|
111
|
+
self.maxsize is not None
|
|
112
|
+
and len(self.persistent_cache) >= self.maxsize
|
|
113
|
+
):
|
|
111
114
|
self.persistent_cache.popitem(last=False)
|
|
112
115
|
|
|
113
116
|
self.misses += 1
|
|
@@ -64,9 +64,15 @@ def export_slides(
|
|
|
64
64
|
format="%Y_%m_%d",
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
-
filepath =
|
|
67
|
+
filepath = (
|
|
68
|
+
os.path.dirname(p=os.path.realpath(filename="__file__")) + "/" + file_name
|
|
69
|
+
)
|
|
68
70
|
|
|
69
|
-
file_title =
|
|
71
|
+
file_title = (
|
|
72
|
+
f"{title}_{today}"
|
|
73
|
+
if title is not None
|
|
74
|
+
else f"{file_name.split(sep='.')[0]}_{today}"
|
|
75
|
+
)
|
|
70
76
|
output_filepath = SLIDES_FOLDER / file_title
|
|
71
77
|
|
|
72
78
|
with Progress(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
|
-
from typing import Callable, Literal, Optional, Self,
|
|
2
|
+
from typing import Callable, Literal, Optional, Self, get_args
|
|
3
3
|
|
|
4
4
|
from itables import show
|
|
5
5
|
from great_tables import GT
|
|
@@ -31,7 +31,7 @@ from mayutils.objects.colours import Colour
|
|
|
31
31
|
from mayutils.export import OUTPUT_FOLDER
|
|
32
32
|
|
|
33
33
|
DataframeBackends = Literal["pandas", "polars"]
|
|
34
|
-
DataFrames
|
|
34
|
+
DataFrames = pd.DataFrame | pl.DataFrame
|
|
35
35
|
|
|
36
36
|
DATA_FOLDER = OUTPUT_FOLDER / "Data"
|
|
37
37
|
|
|
@@ -59,7 +59,12 @@ class Styler(Style):
|
|
|
59
59
|
self,
|
|
60
60
|
) -> Self:
|
|
61
61
|
def style_map(value):
|
|
62
|
-
return
|
|
62
|
+
return (
|
|
63
|
+
"color: rgba(0,0,0,0); background-color: rgba(0, 0, 0, 0);"
|
|
64
|
+
if isinstance(value, (float, int, np.floating, np.integer))
|
|
65
|
+
and np.isnan(value)
|
|
66
|
+
else ""
|
|
67
|
+
)
|
|
63
68
|
|
|
64
69
|
return self.map(style_map=style_map)
|
|
65
70
|
|
|
@@ -97,7 +102,9 @@ class Styler(Style):
|
|
|
97
102
|
|
|
98
103
|
for col_num in range(len(self.columns)):
|
|
99
104
|
self._display_funcs[(row_num, col_num)] = ( # type: ignore
|
|
100
|
-
row_formatter
|
|
105
|
+
row_formatter
|
|
106
|
+
if not isinstance(row_formatter, str)
|
|
107
|
+
else lambda x: format(x, row_formatter) # type: ignore
|
|
101
108
|
)
|
|
102
109
|
|
|
103
110
|
return self
|
|
@@ -324,9 +331,13 @@ class DataframeUtilsAccessor(object):
|
|
|
324
331
|
) -> DataFrame:
|
|
325
332
|
df_cut = self.df.loc[self.df.index < cutoff].copy()
|
|
326
333
|
if aggregation is not None:
|
|
327
|
-
df_cut.loc[f"{cutoff}+", :] = aggregation(
|
|
334
|
+
df_cut.loc[f"{cutoff}+", :] = aggregation(
|
|
335
|
+
self.df.loc[self.df.index >= cutoff]
|
|
336
|
+
)
|
|
328
337
|
df_cut.index = df_cut.index.astype(dtype=str)
|
|
329
|
-
df_cut = df_cut.sort_index(
|
|
338
|
+
df_cut = df_cut.sort_index(
|
|
339
|
+
key=lambda x: x.str.split(pat="+").str[0].astype(dtype=int)
|
|
340
|
+
)
|
|
330
341
|
|
|
331
342
|
return df_cut
|
|
332
343
|
|
|
@@ -413,7 +424,9 @@ class SeriesUtilsAccessor(object):
|
|
|
413
424
|
path: Path | str,
|
|
414
425
|
) -> Path:
|
|
415
426
|
# TODO: Finish
|
|
416
|
-
raise NotImplementedError(
|
|
427
|
+
raise NotImplementedError(
|
|
428
|
+
"Not implemented for series yet: leverage existing df methods"
|
|
429
|
+
)
|
|
417
430
|
|
|
418
431
|
|
|
419
432
|
class IndexUtilsAccessor(object):
|
|
@@ -430,7 +443,14 @@ class IndexUtilsAccessor(object):
|
|
|
430
443
|
if not isinstance(self.index, MultiIndex):
|
|
431
444
|
raise TypeError("Index is not of type MultiIndex")
|
|
432
445
|
|
|
433
|
-
return
|
|
446
|
+
return (
|
|
447
|
+
list(map(list, self.index))
|
|
448
|
+
if not transpose
|
|
449
|
+
else list(
|
|
450
|
+
list(self.index.get_level_values(level=level))
|
|
451
|
+
for level in range(len(self.index.names))
|
|
452
|
+
)
|
|
453
|
+
)
|
|
434
454
|
|
|
435
455
|
|
|
436
456
|
# def save_dataframe(
|
|
@@ -510,7 +530,7 @@ class IndexUtilsAccessor(object):
|
|
|
510
530
|
|
|
511
531
|
|
|
512
532
|
def to_parquet(
|
|
513
|
-
df: DataFrames,
|
|
533
|
+
df: DataFrames, # type: ignore
|
|
514
534
|
path: Path | str,
|
|
515
535
|
dataframe_backend: Optional[DataframeBackends] = None,
|
|
516
536
|
**kwargs,
|
|
@@ -552,7 +572,7 @@ def read_parquet(
|
|
|
552
572
|
path: Path | str,
|
|
553
573
|
dataframe_backend: DataframeBackends = "pandas",
|
|
554
574
|
**kwargs,
|
|
555
|
-
) -> DataFrames:
|
|
575
|
+
) -> DataFrames: # type: ignore
|
|
556
576
|
path = Path(path)
|
|
557
577
|
|
|
558
578
|
if dataframe_backend == "pandas":
|
|
@@ -227,7 +227,9 @@ class Time(BaseTime):
|
|
|
227
227
|
def fractional_completion(
|
|
228
228
|
self,
|
|
229
229
|
) -> float:
|
|
230
|
-
return (
|
|
230
|
+
return (
|
|
231
|
+
self.hour * 3600 + self.minute * 60 + self.second + self.microsecond * 1e-6
|
|
232
|
+
) / DAY_SECONDS
|
|
231
233
|
|
|
232
234
|
|
|
233
235
|
class DateTime(BaseDateTime):
|
|
@@ -580,7 +582,9 @@ class Intervals(object):
|
|
|
580
582
|
def sort(
|
|
581
583
|
self,
|
|
582
584
|
) -> Self:
|
|
583
|
-
self.intervals = tuple(
|
|
585
|
+
self.intervals = tuple(
|
|
586
|
+
sorted(self.intervals, key=lambda interval: (interval.start, interval.end))
|
|
587
|
+
)
|
|
584
588
|
|
|
585
589
|
return self
|
|
586
590
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from re import sub
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def noneish_string(
|
|
6
|
+
string: Optional[str],
|
|
7
|
+
) -> Optional[str]:
|
|
8
|
+
return None if string == "" else string
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def snakify(
|
|
12
|
+
string: str,
|
|
13
|
+
) -> str:
|
|
14
|
+
return "_".join(
|
|
15
|
+
sub(
|
|
16
|
+
pattern="([A-Z][a-z]+)",
|
|
17
|
+
repl=r" \1",
|
|
18
|
+
string=sub(
|
|
19
|
+
pattern="([A-Z]+)",
|
|
20
|
+
repl=r" \1",
|
|
21
|
+
string=string.replace("-", " "),
|
|
22
|
+
),
|
|
23
|
+
).split()
|
|
24
|
+
).lower()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def unsnakify(
|
|
28
|
+
string: str,
|
|
29
|
+
) -> str:
|
|
30
|
+
return string.replace("_", " ").title()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def kebabify(
|
|
34
|
+
string: str,
|
|
35
|
+
) -> str:
|
|
36
|
+
return "-".join(
|
|
37
|
+
sub(
|
|
38
|
+
pattern=r"(\s|_|-)+",
|
|
39
|
+
repl=" ",
|
|
40
|
+
string=sub(
|
|
41
|
+
pattern=r"[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+",
|
|
42
|
+
repl=r" \1",
|
|
43
|
+
string=string,
|
|
44
|
+
).lower(),
|
|
45
|
+
).split()
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def camel(
|
|
50
|
+
string: str,
|
|
51
|
+
) -> str:
|
|
52
|
+
string = (
|
|
53
|
+
sub(
|
|
54
|
+
pattern=r"(_|-)+",
|
|
55
|
+
repl=" ",
|
|
56
|
+
string=string,
|
|
57
|
+
)
|
|
58
|
+
.title()
|
|
59
|
+
.replace(" ", "")
|
|
60
|
+
)
|
|
61
|
+
return "".join([string[0].lower(), string[1:]])
|
|
File without changes
|
|
@@ -5,7 +5,7 @@ from typing import Any, Literal, Optional, Self, final
|
|
|
5
5
|
from dataclasses import dataclass, field
|
|
6
6
|
from mayutils.export.images import IMAGES_FOLDER
|
|
7
7
|
import numpy as np
|
|
8
|
-
from scipy.stats import gaussian_kde, norm
|
|
8
|
+
from scipy.stats import gaussian_kde, norm
|
|
9
9
|
|
|
10
10
|
import plotly.graph_objects as go
|
|
11
11
|
import plotly.io as pio
|
|
@@ -21,13 +21,13 @@ from mayutils.visualisation.graphs.plotly.templates import (
|
|
|
21
21
|
axis_dict,
|
|
22
22
|
shuffled_colourscale,
|
|
23
23
|
)
|
|
24
|
+
from plotly.basedatatypes import BaseTraceType as Trace
|
|
24
25
|
from mayutils.visualisation.graphs.plotly.traces import (
|
|
25
26
|
Null,
|
|
26
27
|
Line,
|
|
27
28
|
Scatter,
|
|
28
29
|
Ecdf,
|
|
29
30
|
Bar3d,
|
|
30
|
-
Trace,
|
|
31
31
|
is_trace_3d,
|
|
32
32
|
)
|
|
33
33
|
|
|
@@ -586,7 +586,7 @@ class Plot(go.Figure):
|
|
|
586
586
|
*args,
|
|
587
587
|
**kwargs,
|
|
588
588
|
) -> Self:
|
|
589
|
-
self.data:
|
|
589
|
+
self.data: Any = [] # pyright: ignore[reportIncompatibleMethodOverride]
|
|
590
590
|
|
|
591
591
|
return self
|
|
592
592
|
|
|
@@ -10,7 +10,7 @@ import plotly.graph_objects as go
|
|
|
10
10
|
from numpy.typing import ArrayLike
|
|
11
11
|
from pandas import DataFrame, Series
|
|
12
12
|
from plotly.basedatatypes import BaseTraceType as Trace
|
|
13
|
-
from scipy.stats import gaussian_kde
|
|
13
|
+
from scipy.stats import gaussian_kde
|
|
14
14
|
|
|
15
15
|
from mayutils.objects.colours import Colour
|
|
16
16
|
from mayutils.objects.datetime import DateTime
|
|
@@ -41,19 +41,24 @@ class Line(go.Scatter):
|
|
|
41
41
|
self,
|
|
42
42
|
label_name: bool | str = False,
|
|
43
43
|
textposition: str = "middle right",
|
|
44
|
+
meta: str = "line",
|
|
44
45
|
*args,
|
|
45
46
|
**kwargs,
|
|
46
47
|
) -> None:
|
|
47
48
|
mode: str = kwargs.pop("mode", "lines")
|
|
48
|
-
mode +=
|
|
49
|
+
mode += (
|
|
50
|
+
"+text" if label_name is not False and not mode.endswith("+text") else ""
|
|
51
|
+
)
|
|
49
52
|
kwargs["mode"] = mode
|
|
50
53
|
kwargs["textposition"] = textposition
|
|
51
54
|
|
|
52
|
-
label_name = (
|
|
55
|
+
label_name = (
|
|
56
|
+
kwargs.get("name", None) if label_name is True else label_name
|
|
57
|
+
) or ""
|
|
53
58
|
kwargs["text"] = [""] * (len(kwargs.get("x", [])) - 1) + [label_name]
|
|
54
59
|
|
|
55
60
|
super().__init__(
|
|
56
|
-
meta=
|
|
61
|
+
meta=meta,
|
|
57
62
|
*args,
|
|
58
63
|
**kwargs,
|
|
59
64
|
)
|
|
@@ -93,7 +98,9 @@ class Line(go.Scatter):
|
|
|
93
98
|
for lower, upper in zip(y_lower, y_upper):
|
|
94
99
|
if len(lower) != len(y) or len(upper) != len(y): # type: ignore
|
|
95
100
|
raise ValueError("Y Values of different length provided")
|
|
96
|
-
elif np.any(np.asarray(lower) > last_lower) or np.any(
|
|
101
|
+
elif np.any(np.asarray(lower) > last_lower) or np.any(
|
|
102
|
+
np.asarray(upper) < last_upper
|
|
103
|
+
):
|
|
97
104
|
raise ValueError("Monotonic bounds not passed")
|
|
98
105
|
|
|
99
106
|
last_lower = lower
|
|
@@ -124,7 +131,11 @@ class Line(go.Scatter):
|
|
|
124
131
|
legendgroup=legendgroup,
|
|
125
132
|
hoverinfo="skip",
|
|
126
133
|
*[*args],
|
|
127
|
-
**{
|
|
134
|
+
**{
|
|
135
|
+
key: value
|
|
136
|
+
for key, value in kwargs.items()
|
|
137
|
+
if key != "line_color"
|
|
138
|
+
},
|
|
128
139
|
)
|
|
129
140
|
for lower, upper in zip(y_lower, y_upper)
|
|
130
141
|
],
|
|
@@ -184,8 +195,11 @@ class Ecdf(Line):
|
|
|
184
195
|
|
|
185
196
|
_y += y_shift
|
|
186
197
|
|
|
187
|
-
kwargs["line_shape"] =
|
|
198
|
+
kwargs["line_shape"] = (
|
|
199
|
+
"hv" if ((mode != "reversed") ^ (not left_inclusive)) else "vh"
|
|
200
|
+
)
|
|
188
201
|
kwargs["fill"] = fill
|
|
202
|
+
kwargs["meta"] = kwargs.pop("meta", "ecdf")
|
|
189
203
|
|
|
190
204
|
if fill == "toself":
|
|
191
205
|
_x = np.insert(_x, 0, _x[-1])
|
|
@@ -202,8 +216,6 @@ class Ecdf(Line):
|
|
|
202
216
|
**kwargs,
|
|
203
217
|
)
|
|
204
218
|
|
|
205
|
-
self.meta = "ecdf"
|
|
206
|
-
|
|
207
219
|
|
|
208
220
|
class Kde(Line):
|
|
209
221
|
def __init__(
|
|
@@ -219,6 +231,8 @@ class Kde(Line):
|
|
|
219
231
|
_x_grid = np.linspace(np.min(_x), np.max(_x), 1000)
|
|
220
232
|
_y = kde(_x_grid)
|
|
221
233
|
|
|
234
|
+
kwargs["meta"] = kwargs.pop("meta", "kde")
|
|
235
|
+
|
|
222
236
|
super().__init__(
|
|
223
237
|
x=_x_grid,
|
|
224
238
|
y=_y,
|
|
@@ -228,8 +242,6 @@ class Kde(Line):
|
|
|
228
242
|
**kwargs,
|
|
229
243
|
)
|
|
230
244
|
|
|
231
|
-
self.meta = "kde"
|
|
232
|
-
|
|
233
245
|
|
|
234
246
|
class Scatter(go.Scatter):
|
|
235
247
|
def __init__(
|
|
@@ -372,7 +384,11 @@ class Bar3d(go.Mesh3d):
|
|
|
372
384
|
x_arr = np.asarray(x)
|
|
373
385
|
y_arr = np.asarray(y)
|
|
374
386
|
z_arr = np.asarray(z, dtype=np.float64)
|
|
375
|
-
w_arr =
|
|
387
|
+
w_arr = (
|
|
388
|
+
np.asarray(w, dtype=np.float64)
|
|
389
|
+
if w is not None
|
|
390
|
+
else np.ones(z_arr.shape, dtype=np.float64)
|
|
391
|
+
)
|
|
376
392
|
|
|
377
393
|
if any(len(arr) != len(w_arr) for arr in [x_arr, y_arr, z_arr]):
|
|
378
394
|
raise ValueError("Input arrays are not same length")
|
|
@@ -390,7 +406,12 @@ class Bar3d(go.Mesh3d):
|
|
|
390
406
|
)
|
|
391
407
|
* dx
|
|
392
408
|
)
|
|
393
|
-
self._x =
|
|
409
|
+
self._x = (
|
|
410
|
+
np.stack([x_arr_numerical - dx / 2, x_arr_numerical + dx / 2], axis=1)[
|
|
411
|
+
np.arange(x_arr_numerical.size)[:, None], [0, 0, 1, 1, 0, 0, 1, 1]
|
|
412
|
+
].reshape(-1)
|
|
413
|
+
+ x_start
|
|
414
|
+
)
|
|
394
415
|
y_arr_numerical = (
|
|
395
416
|
map_categorical_array(
|
|
396
417
|
arr=self._y_arr,
|
|
@@ -398,18 +419,34 @@ class Bar3d(go.Mesh3d):
|
|
|
398
419
|
)
|
|
399
420
|
* dy
|
|
400
421
|
)
|
|
401
|
-
self._y =
|
|
422
|
+
self._y = (
|
|
423
|
+
np.stack([y_arr_numerical - dy / 2, y_arr_numerical + dy / 2], axis=1)[
|
|
424
|
+
np.arange(y_arr_numerical.size)[:, None], [0, 1, 1, 0, 0, 1, 1, 0]
|
|
425
|
+
].reshape(-1)
|
|
426
|
+
+ y_start
|
|
427
|
+
)
|
|
402
428
|
self._z = np.ones(self._z_arr.size * 8, dtype=self._z_arr.dtype) * z0
|
|
403
|
-
self._z[(np.arange(self._z_arr.size) * 8)[:, None] + np.array([4, 5, 6, 7])] =
|
|
429
|
+
self._z[(np.arange(self._z_arr.size) * 8)[:, None] + np.array([4, 5, 6, 7])] = (
|
|
430
|
+
self._z_arr[:, None]
|
|
431
|
+
)
|
|
404
432
|
self._z += z_start
|
|
405
433
|
self._w = np.repeat(
|
|
406
434
|
self._w_arr,
|
|
407
435
|
repeats=8,
|
|
408
436
|
)
|
|
409
437
|
|
|
410
|
-
i = (
|
|
411
|
-
|
|
412
|
-
|
|
438
|
+
i = (
|
|
439
|
+
np.tile([7, 0, 0, 0, 4, 4, 6, 6, 4, 0, 3, 2], (len(self._x_arr), 1))
|
|
440
|
+
+ np.arange(len(self._x_arr))[:, np.newaxis] * 8
|
|
441
|
+
).flatten()
|
|
442
|
+
j = (
|
|
443
|
+
np.tile([3, 4, 1, 2, 5, 6, 5, 2, 0, 1, 6, 3], (len(self._x_arr), 1))
|
|
444
|
+
+ np.arange(len(self._x_arr))[:, np.newaxis] * 8
|
|
445
|
+
).flatten()
|
|
446
|
+
k = (
|
|
447
|
+
np.tile([0, 7, 2, 3, 6, 7, 1, 1, 5, 5, 7, 6], (len(self._x_arr), 1))
|
|
448
|
+
+ np.arange(len(self._x_arr))[:, np.newaxis] * 8
|
|
449
|
+
).flatten()
|
|
413
450
|
|
|
414
451
|
return super().__init__(
|
|
415
452
|
x=self._x,
|
|
@@ -474,9 +511,18 @@ def merge_cuboids(
|
|
|
474
511
|
y = np.zeros(len(cuboids) * 8)
|
|
475
512
|
z = np.zeros(len(cuboids) * 8)
|
|
476
513
|
intensity = np.zeros(len(cuboids) * 8)
|
|
477
|
-
i = (
|
|
478
|
-
|
|
479
|
-
|
|
514
|
+
i = (
|
|
515
|
+
np.tile([7, 0, 0, 0, 4, 4, 6, 6, 4, 0, 3, 2], (len(cuboids), 1))
|
|
516
|
+
+ np.arange(len(cuboids))[:, np.newaxis] * 8
|
|
517
|
+
).flatten()
|
|
518
|
+
j = (
|
|
519
|
+
np.tile([3, 4, 1, 2, 5, 6, 5, 2, 0, 1, 6, 3], (len(cuboids), 1))
|
|
520
|
+
+ np.arange(len(cuboids))[:, np.newaxis] * 8
|
|
521
|
+
).flatten()
|
|
522
|
+
k = (
|
|
523
|
+
np.tile([0, 7, 2, 3, 6, 7, 1, 1, 5, 5, 7, 6], (len(cuboids), 1))
|
|
524
|
+
+ np.arange(len(cuboids))[:, np.newaxis] * 8
|
|
525
|
+
).flatten()
|
|
480
526
|
|
|
481
527
|
for idx, cuboid in enumerate(cuboids):
|
|
482
528
|
x[idx * 8 : (idx + 1) * 8] = cuboid.x # type: ignore
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mayutils-1.2.25/src/mayutils/visualisation → mayutils-1.2.28/src/mayutils/testing}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mayutils-1.2.25 → mayutils-1.2.28}/src/mayutils/visualisation/graphs/matplotlib/template.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|