td-ts-compressor 0.1.9__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.
- td_ts_compressor/__init__.py +19 -0
- td_ts_compressor/core.py +433 -0
- td_ts_compressor/recipes.py +50 -0
- td_ts_compressor/resources/__init__.py +1 -0
- td_ts_compressor/resources/ts_compress_to.c +2414 -0
- td_ts_compressor/sql.py +501 -0
- td_ts_compressor/tdfs4ds.py +455 -0
- td_ts_compressor-0.1.9.dist-info/METADATA +149 -0
- td_ts_compressor-0.1.9.dist-info/RECORD +11 -0
- td_ts_compressor-0.1.9.dist-info/WHEEL +5 -0
- td_ts_compressor-0.1.9.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""Python interface for the Teradata ``ts_compress_to`` table operator."""
|
|
2
|
+
|
|
3
|
+
from .core import TeradataTimeSeriesCompressor
|
|
4
|
+
from .recipes import analytical_points, fixed_budget, visual_fidelity
|
|
5
|
+
from .sql import CompressionParameters, CompressorSpec
|
|
6
|
+
from .tdfs4ds import ProcessFeatureEngineeringArtifact
|
|
7
|
+
|
|
8
|
+
__version__ = "0.1.9"
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"CompressionParameters",
|
|
12
|
+
"CompressorSpec",
|
|
13
|
+
"ProcessFeatureEngineeringArtifact",
|
|
14
|
+
"TeradataTimeSeriesCompressor",
|
|
15
|
+
"__version__",
|
|
16
|
+
"analytical_points",
|
|
17
|
+
"fixed_budget",
|
|
18
|
+
"visual_fidelity",
|
|
19
|
+
]
|
td_ts_compressor/core.py
ADDED
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
"""High-level Python facade for teradataml workflows."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from importlib import resources
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Mapping, Sequence
|
|
8
|
+
|
|
9
|
+
from .recipes import visual_fidelity
|
|
10
|
+
from .sql import (
|
|
11
|
+
CompressionParameters,
|
|
12
|
+
CompressorSpec,
|
|
13
|
+
compression_sql,
|
|
14
|
+
create_table_as_sql,
|
|
15
|
+
feature_sql,
|
|
16
|
+
features_by_mode_sql,
|
|
17
|
+
register_sql,
|
|
18
|
+
td_plot_sql,
|
|
19
|
+
)
|
|
20
|
+
from .tdfs4ds import ProcessFeatureEngineeringArtifact, build_process_feature_engineering_artifact
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TeradataTimeSeriesCompressor:
|
|
24
|
+
"""Pythonic wrapper for the ``ts_compress_to`` function mapping.
|
|
25
|
+
|
|
26
|
+
Methods return SQL by default. When ``as_dataframe=True`` they lazily import
|
|
27
|
+
``teradataml`` and return ``teradataml.DataFrame.from_query(...)``.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
spec: CompressorSpec,
|
|
33
|
+
compressor_database: str | None = None,
|
|
34
|
+
operator_database: str | None = None,
|
|
35
|
+
):
|
|
36
|
+
self.spec = spec
|
|
37
|
+
self.operator_database = operator_database or compressor_database
|
|
38
|
+
self.compressor_database = self.operator_database
|
|
39
|
+
|
|
40
|
+
def sql(
|
|
41
|
+
self,
|
|
42
|
+
*,
|
|
43
|
+
table_name: str | None = None,
|
|
44
|
+
schema_name: str | None = None,
|
|
45
|
+
data_database: str | None = None,
|
|
46
|
+
input_query: str | None = None,
|
|
47
|
+
dataframe: object | None = None,
|
|
48
|
+
parameters: CompressionParameters | None = None,
|
|
49
|
+
columns: Sequence[str] | None = None,
|
|
50
|
+
) -> str:
|
|
51
|
+
input_query = _resolve_input_query(input_query, dataframe)
|
|
52
|
+
source_database = _resolve_data_database(schema_name, data_database)
|
|
53
|
+
return compression_sql(
|
|
54
|
+
table_name=table_name,
|
|
55
|
+
schema_name=source_database,
|
|
56
|
+
compressor_database=self.compressor_database,
|
|
57
|
+
input_query=input_query,
|
|
58
|
+
spec=self.spec,
|
|
59
|
+
parameters=parameters,
|
|
60
|
+
columns=columns,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def compress(
|
|
64
|
+
self,
|
|
65
|
+
*,
|
|
66
|
+
table_name: str | None = None,
|
|
67
|
+
schema_name: str | None = None,
|
|
68
|
+
data_database: str | None = None,
|
|
69
|
+
input_query: str | None = None,
|
|
70
|
+
dataframe: object | None = None,
|
|
71
|
+
parameters: CompressionParameters | None = None,
|
|
72
|
+
columns: Sequence[str] | None = None,
|
|
73
|
+
as_dataframe: bool = True,
|
|
74
|
+
):
|
|
75
|
+
query = self.sql(
|
|
76
|
+
table_name=table_name,
|
|
77
|
+
schema_name=schema_name,
|
|
78
|
+
data_database=data_database,
|
|
79
|
+
input_query=input_query,
|
|
80
|
+
dataframe=dataframe,
|
|
81
|
+
parameters=parameters,
|
|
82
|
+
columns=columns,
|
|
83
|
+
)
|
|
84
|
+
if not as_dataframe:
|
|
85
|
+
return query
|
|
86
|
+
return _teradataml_dataframe(query)
|
|
87
|
+
|
|
88
|
+
def features_sql(
|
|
89
|
+
self,
|
|
90
|
+
*,
|
|
91
|
+
table_name: str | None = None,
|
|
92
|
+
schema_name: str | None = None,
|
|
93
|
+
data_database: str | None = None,
|
|
94
|
+
input_query: str | None = None,
|
|
95
|
+
dataframe: object | None = None,
|
|
96
|
+
parameters: CompressionParameters | None = None,
|
|
97
|
+
columns: Sequence[str] | None = None,
|
|
98
|
+
top_k_distances: int = 0,
|
|
99
|
+
label_column: str | None = None,
|
|
100
|
+
label_value: object | None = None,
|
|
101
|
+
) -> str:
|
|
102
|
+
input_query = _resolve_input_query(input_query, dataframe)
|
|
103
|
+
source_database = _resolve_data_database(schema_name, data_database)
|
|
104
|
+
return feature_sql(
|
|
105
|
+
table_name=table_name,
|
|
106
|
+
schema_name=source_database,
|
|
107
|
+
input_query=input_query,
|
|
108
|
+
compressor_database=self.compressor_database,
|
|
109
|
+
spec=self.spec,
|
|
110
|
+
parameters=parameters,
|
|
111
|
+
columns=columns,
|
|
112
|
+
top_k_distances=top_k_distances,
|
|
113
|
+
label_column=label_column,
|
|
114
|
+
label_value=label_value,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
def features(
|
|
118
|
+
self,
|
|
119
|
+
*,
|
|
120
|
+
table_name: str | None = None,
|
|
121
|
+
schema_name: str | None = None,
|
|
122
|
+
data_database: str | None = None,
|
|
123
|
+
input_query: str | None = None,
|
|
124
|
+
dataframe: object | None = None,
|
|
125
|
+
parameters: CompressionParameters | None = None,
|
|
126
|
+
columns: Sequence[str] | None = None,
|
|
127
|
+
top_k_distances: int = 0,
|
|
128
|
+
label_column: str | None = None,
|
|
129
|
+
label_value: object | None = None,
|
|
130
|
+
as_dataframe: bool = True,
|
|
131
|
+
):
|
|
132
|
+
query = self.features_sql(
|
|
133
|
+
table_name=table_name,
|
|
134
|
+
schema_name=schema_name,
|
|
135
|
+
data_database=data_database,
|
|
136
|
+
input_query=input_query,
|
|
137
|
+
dataframe=dataframe,
|
|
138
|
+
parameters=parameters,
|
|
139
|
+
columns=columns,
|
|
140
|
+
top_k_distances=top_k_distances,
|
|
141
|
+
label_column=label_column,
|
|
142
|
+
label_value=label_value,
|
|
143
|
+
)
|
|
144
|
+
if not as_dataframe:
|
|
145
|
+
return query
|
|
146
|
+
return _teradataml_dataframe(query)
|
|
147
|
+
|
|
148
|
+
def process_feature_engineering(
|
|
149
|
+
self,
|
|
150
|
+
*,
|
|
151
|
+
process_database: str,
|
|
152
|
+
process_name: str,
|
|
153
|
+
source_object: str | None = None,
|
|
154
|
+
source_database: str | None = None,
|
|
155
|
+
input_query: str | None = None,
|
|
156
|
+
dataframe: object | None = None,
|
|
157
|
+
parameters: CompressionParameters | None = None,
|
|
158
|
+
columns: Sequence[str] | None = None,
|
|
159
|
+
top_k_distances: int = 0,
|
|
160
|
+
mode_name: str | None = None,
|
|
161
|
+
feature_prefix: str = "",
|
|
162
|
+
feature_suffix: str = "",
|
|
163
|
+
series_description: str | None = None,
|
|
164
|
+
source_object_description: str | None = None,
|
|
165
|
+
source_column_descriptions: Mapping[str, str] | None = None,
|
|
166
|
+
use_tdfs4ds_dictionary: bool = True,
|
|
167
|
+
) -> ProcessFeatureEngineeringArtifact:
|
|
168
|
+
"""Build a tdfs4ds process view and deterministic dictionary dataframes."""
|
|
169
|
+
|
|
170
|
+
feature_query = self.features_sql(
|
|
171
|
+
table_name=source_object,
|
|
172
|
+
schema_name=source_database,
|
|
173
|
+
input_query=input_query,
|
|
174
|
+
dataframe=dataframe,
|
|
175
|
+
parameters=parameters,
|
|
176
|
+
columns=columns,
|
|
177
|
+
top_k_distances=top_k_distances,
|
|
178
|
+
)
|
|
179
|
+
return build_process_feature_engineering_artifact(
|
|
180
|
+
process_database=process_database,
|
|
181
|
+
process_name=process_name,
|
|
182
|
+
source_database=source_database,
|
|
183
|
+
source_object=source_object,
|
|
184
|
+
spec=self.spec,
|
|
185
|
+
feature_query=feature_query,
|
|
186
|
+
parameters=parameters or CompressionParameters(),
|
|
187
|
+
top_k_distances=top_k_distances,
|
|
188
|
+
mode_name=mode_name,
|
|
189
|
+
feature_prefix=feature_prefix,
|
|
190
|
+
feature_suffix=feature_suffix,
|
|
191
|
+
series_description=series_description,
|
|
192
|
+
source_object_description=source_object_description,
|
|
193
|
+
source_column_descriptions=source_column_descriptions,
|
|
194
|
+
use_tdfs4ds_dictionary=use_tdfs4ds_dictionary,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
def features_by_mode_sql(
|
|
198
|
+
self,
|
|
199
|
+
*,
|
|
200
|
+
modes: Mapping[str, CompressionParameters],
|
|
201
|
+
table_name: str | None = None,
|
|
202
|
+
schema_name: str | None = None,
|
|
203
|
+
data_database: str | None = None,
|
|
204
|
+
input_query: str | None = None,
|
|
205
|
+
dataframe: object | None = None,
|
|
206
|
+
columns: Sequence[str] | None = None,
|
|
207
|
+
top_k_distances: int = 0,
|
|
208
|
+
mode_column: str = "mode",
|
|
209
|
+
order_by: str | Sequence[str | int] | None = None,
|
|
210
|
+
) -> str:
|
|
211
|
+
input_query = _resolve_input_query(input_query, dataframe)
|
|
212
|
+
source_database = _resolve_data_database(schema_name, data_database)
|
|
213
|
+
return features_by_mode_sql(
|
|
214
|
+
modes=modes,
|
|
215
|
+
table_name=table_name,
|
|
216
|
+
schema_name=source_database,
|
|
217
|
+
input_query=input_query,
|
|
218
|
+
compressor_database=self.compressor_database,
|
|
219
|
+
spec=self.spec,
|
|
220
|
+
columns=columns,
|
|
221
|
+
top_k_distances=top_k_distances,
|
|
222
|
+
mode_column=mode_column,
|
|
223
|
+
order_by=order_by,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
def features_by_mode(
|
|
227
|
+
self,
|
|
228
|
+
*,
|
|
229
|
+
modes: Mapping[str, CompressionParameters],
|
|
230
|
+
table_name: str | None = None,
|
|
231
|
+
schema_name: str | None = None,
|
|
232
|
+
data_database: str | None = None,
|
|
233
|
+
input_query: str | None = None,
|
|
234
|
+
dataframe: object | None = None,
|
|
235
|
+
columns: Sequence[str] | None = None,
|
|
236
|
+
top_k_distances: int = 0,
|
|
237
|
+
mode_column: str = "mode",
|
|
238
|
+
order_by: str | Sequence[str | int] | None = None,
|
|
239
|
+
as_dataframe: bool = True,
|
|
240
|
+
):
|
|
241
|
+
query = self.features_by_mode_sql(
|
|
242
|
+
modes=modes,
|
|
243
|
+
table_name=table_name,
|
|
244
|
+
schema_name=schema_name,
|
|
245
|
+
data_database=data_database,
|
|
246
|
+
input_query=input_query,
|
|
247
|
+
dataframe=dataframe,
|
|
248
|
+
columns=columns,
|
|
249
|
+
top_k_distances=top_k_distances,
|
|
250
|
+
mode_column=mode_column,
|
|
251
|
+
order_by=order_by,
|
|
252
|
+
)
|
|
253
|
+
if not as_dataframe:
|
|
254
|
+
return query
|
|
255
|
+
return _teradataml_dataframe(query)
|
|
256
|
+
|
|
257
|
+
def materialize_for_td_plot_sql(
|
|
258
|
+
self,
|
|
259
|
+
*,
|
|
260
|
+
table_name: str | None = None,
|
|
261
|
+
schema_name: str | None = None,
|
|
262
|
+
data_database: str | None = None,
|
|
263
|
+
input_query: str | None = None,
|
|
264
|
+
dataframe: object | None = None,
|
|
265
|
+
output_table: str,
|
|
266
|
+
output_schema_name: str | None = None,
|
|
267
|
+
parameters: CompressionParameters | None = None,
|
|
268
|
+
columns: Sequence[str] | None = None,
|
|
269
|
+
) -> str:
|
|
270
|
+
query = self.sql(
|
|
271
|
+
table_name=table_name,
|
|
272
|
+
schema_name=schema_name,
|
|
273
|
+
data_database=data_database,
|
|
274
|
+
input_query=input_query,
|
|
275
|
+
dataframe=dataframe,
|
|
276
|
+
parameters=parameters or visual_fidelity(),
|
|
277
|
+
columns=columns,
|
|
278
|
+
)
|
|
279
|
+
return create_table_as_sql(
|
|
280
|
+
table_name=output_table,
|
|
281
|
+
schema_name=output_schema_name,
|
|
282
|
+
query=query,
|
|
283
|
+
primary_index=self.spec.id_columns,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
def td_plot_sql(
|
|
287
|
+
self,
|
|
288
|
+
*,
|
|
289
|
+
table_name: str,
|
|
290
|
+
schema_name: str | None = None,
|
|
291
|
+
title: str | None = None,
|
|
292
|
+
width: int = 1024,
|
|
293
|
+
height: int = 768,
|
|
294
|
+
plot_type: str = "line",
|
|
295
|
+
) -> str:
|
|
296
|
+
return td_plot_sql(
|
|
297
|
+
table_name=table_name,
|
|
298
|
+
schema_name=schema_name,
|
|
299
|
+
spec=self.spec,
|
|
300
|
+
title=title,
|
|
301
|
+
width=width,
|
|
302
|
+
height=height,
|
|
303
|
+
plot_type=plot_type,
|
|
304
|
+
)
|
|
305
|
+
|
|
306
|
+
def install_table_operator_sql(
|
|
307
|
+
self,
|
|
308
|
+
*,
|
|
309
|
+
target_database: str,
|
|
310
|
+
c_source_path: str | Path | None = None,
|
|
311
|
+
) -> list[str]:
|
|
312
|
+
"""Return SQL statements to install the operator in a database."""
|
|
313
|
+
|
|
314
|
+
return register_sql(
|
|
315
|
+
c_source_path=c_source_path or bundled_c_source_path(),
|
|
316
|
+
target_database=target_database,
|
|
317
|
+
spec=self.spec,
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
def install_table_operator(
|
|
321
|
+
self,
|
|
322
|
+
*,
|
|
323
|
+
target_database: str,
|
|
324
|
+
c_source_path: str | Path | None = None,
|
|
325
|
+
) -> None:
|
|
326
|
+
"""Install the function and mapping through ``teradataml.execute_sql``."""
|
|
327
|
+
|
|
328
|
+
execute_sql = _teradataml_execute_sql()
|
|
329
|
+
for statement in self.install_table_operator_sql(
|
|
330
|
+
target_database=target_database,
|
|
331
|
+
c_source_path=c_source_path,
|
|
332
|
+
):
|
|
333
|
+
execute_sql(statement)
|
|
334
|
+
|
|
335
|
+
def register_sql(
|
|
336
|
+
self,
|
|
337
|
+
c_source_path: str | Path | None = None,
|
|
338
|
+
target_database: str | None = None,
|
|
339
|
+
) -> list[str]:
|
|
340
|
+
return register_sql(
|
|
341
|
+
c_source_path=c_source_path or bundled_c_source_path(),
|
|
342
|
+
target_database=target_database,
|
|
343
|
+
spec=self.spec,
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
def register(
|
|
347
|
+
self,
|
|
348
|
+
c_source_path: str | Path | None = None,
|
|
349
|
+
target_database: str | None = None,
|
|
350
|
+
) -> None:
|
|
351
|
+
execute_sql = _teradataml_execute_sql()
|
|
352
|
+
for statement in self.register_sql(c_source_path, target_database):
|
|
353
|
+
execute_sql(statement)
|
|
354
|
+
|
|
355
|
+
def execute(self, statement: str) -> None:
|
|
356
|
+
_teradataml_execute_sql()(statement)
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def _teradataml_dataframe(query: str):
|
|
360
|
+
try:
|
|
361
|
+
from teradataml import DataFrame
|
|
362
|
+
except ImportError as exc:
|
|
363
|
+
raise ImportError(
|
|
364
|
+
"Install the teradataml extra or pass as_dataframe=False to receive SQL."
|
|
365
|
+
) from exc
|
|
366
|
+
return DataFrame.from_query(query)
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _resolve_input_query(
|
|
370
|
+
input_query: str | None,
|
|
371
|
+
dataframe: object | None,
|
|
372
|
+
) -> str | None:
|
|
373
|
+
if input_query is not None and dataframe is not None:
|
|
374
|
+
raise ValueError("provide only one of input_query or dataframe")
|
|
375
|
+
if dataframe is None:
|
|
376
|
+
return input_query
|
|
377
|
+
return _dataframe_query(dataframe)
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
def _resolve_data_database(
|
|
381
|
+
schema_name: str | None,
|
|
382
|
+
data_database: str | None,
|
|
383
|
+
) -> str | None:
|
|
384
|
+
if schema_name and data_database and schema_name != data_database:
|
|
385
|
+
raise ValueError("schema_name and data_database must match when both are provided")
|
|
386
|
+
return data_database or schema_name
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def _dataframe_query(dataframe: object) -> str:
|
|
390
|
+
"""Return SQL backing a teradataml DataFrame-like object."""
|
|
391
|
+
|
|
392
|
+
for method_name in ("to_sql", "show_query"):
|
|
393
|
+
method = getattr(dataframe, method_name, None)
|
|
394
|
+
if method is None:
|
|
395
|
+
continue
|
|
396
|
+
try:
|
|
397
|
+
value = method()
|
|
398
|
+
except TypeError:
|
|
399
|
+
continue
|
|
400
|
+
if isinstance(value, str) and value.strip():
|
|
401
|
+
return value.strip().rstrip(";")
|
|
402
|
+
|
|
403
|
+
for attr_name in ("query", "_query"):
|
|
404
|
+
value = getattr(dataframe, attr_name, None)
|
|
405
|
+
if isinstance(value, str) and value.strip():
|
|
406
|
+
return value.strip().rstrip(";")
|
|
407
|
+
|
|
408
|
+
for attr_name in ("table_name", "_table_name"):
|
|
409
|
+
value = getattr(dataframe, attr_name, None)
|
|
410
|
+
if isinstance(value, str) and value.strip():
|
|
411
|
+
return f"SELECT * FROM {value.strip()}"
|
|
412
|
+
|
|
413
|
+
raise TypeError(
|
|
414
|
+
"dataframe must expose SQL through to_sql(), show_query(), query, "
|
|
415
|
+
"_query, table_name, or _table_name"
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
def bundled_c_source_path() -> Path:
|
|
420
|
+
"""Return the installed path to the bundled ``ts_compress_to.c`` source."""
|
|
421
|
+
|
|
422
|
+
source = resources.files("td_ts_compressor.resources").joinpath(
|
|
423
|
+
"ts_compress_to.c"
|
|
424
|
+
)
|
|
425
|
+
return Path(str(source))
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def _teradataml_execute_sql():
|
|
429
|
+
try:
|
|
430
|
+
from teradataml import execute_sql
|
|
431
|
+
except ImportError as exc:
|
|
432
|
+
raise ImportError("Install the teradataml extra before executing SQL.") from exc
|
|
433
|
+
return execute_sql
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Parameter recipes for common compression workflows."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .sql import CompressionParameters
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def visual_fidelity(
|
|
9
|
+
*,
|
|
10
|
+
width_px: int = 1024,
|
|
11
|
+
height_px: int = 768,
|
|
12
|
+
distance_max: float = 1.0,
|
|
13
|
+
plot_x_fraction: float = 0.95,
|
|
14
|
+
) -> CompressionParameters:
|
|
15
|
+
"""Keep enough points for a line plot at the requested display size."""
|
|
16
|
+
|
|
17
|
+
return CompressionParameters(
|
|
18
|
+
distance_max=distance_max,
|
|
19
|
+
n_max="-1",
|
|
20
|
+
tol_x="auto",
|
|
21
|
+
tol_y="auto",
|
|
22
|
+
plot_width_px=width_px,
|
|
23
|
+
plot_height_px=height_px,
|
|
24
|
+
plot_x_fraction=plot_x_fraction,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def analytical_points(*, auto_log_drop: float = 1.5) -> CompressionParameters:
|
|
29
|
+
"""Extract important points using the operator's adaptive elbow rule."""
|
|
30
|
+
|
|
31
|
+
return CompressionParameters(
|
|
32
|
+
distance_max="-1",
|
|
33
|
+
n_max="auto",
|
|
34
|
+
auto_log_drop=auto_log_drop,
|
|
35
|
+
tol_x="auto",
|
|
36
|
+
tol_y="auto",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def fixed_budget(*, n_max: int) -> CompressionParameters:
|
|
41
|
+
"""Keep a fixed maximum number of important points per series."""
|
|
42
|
+
|
|
43
|
+
if n_max < 2:
|
|
44
|
+
raise ValueError("n_max must be at least 2 because endpoints are always kept")
|
|
45
|
+
return CompressionParameters(
|
|
46
|
+
distance_max="-1",
|
|
47
|
+
n_max=str(n_max),
|
|
48
|
+
tol_x="auto",
|
|
49
|
+
tol_y="auto",
|
|
50
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Bundled source files used by td-ts-compressor installation helpers."""
|