Skip to content

Commit 73208b2

Browse files
committed
🚧 WiP include minmaxlttb tests
1 parent 73aea16 commit 73208b2

File tree

2 files changed

+92
-4
lines changed

2 files changed

+92
-4
lines changed

tests/test_algos_python_compliance.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,26 @@
22
import pytest
33

44
from tsdownsample import (
5-
FPCSDownsampler, # TODO -> include MinMaxLTTB?
5+
FPCSDownsampler,
66
LTTBDownsampler,
77
M4Downsampler,
88
MinMaxDownsampler,
9+
# MinMaxLTTBDownsampler,
10+
NaNFPCSDownsampler,
911
NaNM4Downsampler,
1012
NaNMinMaxDownsampler,
13+
# NaNMinMaxLTTBDownsampler,
1114
)
1215
from tsdownsample._python.downsamplers import (
1316
FPCS_py,
1417
LTTB_py,
1518
M4_py,
1619
MinMax_py,
20+
# MinMaxLTTB_py,
21+
NaNFPCS_py,
1722
NaNM4_py,
1823
NaNMinMax_py,
24+
# NaNMinMaxLTTB_py,
1925
)
2026

2127

@@ -25,10 +31,13 @@
2531
(MinMaxDownsampler(), MinMax_py()),
2632
(M4Downsampler(), M4_py()),
2733
(LTTBDownsampler(), LTTB_py()),
34+
# (MinMaxLTTBDownsampler(), MinMaxLTTB_py()),
2835
(FPCSDownsampler(), FPCS_py()),
2936
# Include NaN downsamplers
3037
(NaNMinMaxDownsampler(), NaNMinMax_py()),
3138
(NaNM4Downsampler(), NaNM4_py()),
39+
# (NaNMinMaxLTTBDownsampler(), NaNMinMaxLTTB_py()),
40+
(NaNFPCSDownsampler(), NaNFPCS_py()),
3241
],
3342
)
3443
@pytest.mark.parametrize("n", [10_000, 10_032, 20_321, 23_489])
@@ -51,7 +60,12 @@ def test_resampler_accordance(rust_python_pair, n, n_out):
5160

5261
@pytest.mark.parametrize(
5362
"rust_python_pair",
54-
[(NaNMinMaxDownsampler(), NaNMinMax_py()), (NaNM4Downsampler(), NaNM4_py())],
63+
[
64+
(NaNMinMaxDownsampler(), NaNMinMax_py()),
65+
(NaNM4Downsampler(), NaNM4_py()),
66+
# (NaNMinMaxLTTBDownsampler(), NaNMinMaxLTTB_py()),
67+
(NaNFPCSDownsampler(), NaNFPCS_py()),
68+
],
5569
)
5670
@pytest.mark.parametrize("n", [10_000, 10_032, 20_321, 23_489])
5771
@pytest.mark.parametrize("n_random_nans", [100, 200, 500, 2000, 5000])

tsdownsample/_python/downsamplers.py

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import numpy as np
55

66
from ..downsampling_interface import AbstractDownsampler
7+
from abc import ABC
78

89

910
def _get_bin_idxs(x: np.ndarray, nb_bins: int) -> np.ndarray:
@@ -258,7 +259,59 @@ def _downsample(
258259
return np.array(sorted(rel_idxs))
259260

260261

261-
class FPCS_py(AbstractDownsampler):
262+
class _MinMaxLTTB_py(AbstractDownsampler, ABC):
263+
def __init__(
264+
self, check_contiguous=True, x_dtype_regex_list=None, y_dtype_regex_list=None
265+
):
266+
super().__init__(check_contiguous, x_dtype_regex_list, y_dtype_regex_list)
267+
self.minmax_downsampler: AbstractDownsampler = None
268+
self.lttb_downsampler: AbstractDownsampler = None
269+
270+
def _downsample(self, x, y, n_out, **kwargs):
271+
minmax_ratio = kwargs.get("minmax_ratio", 4)
272+
kwargs.pop("minmax_ratio", None) # remove the minmax_ratio from kwargs
273+
274+
# Is fine for this implementation as this is only used for testing
275+
if x is None:
276+
x = np.arange(y.shape[0])
277+
278+
n_1 = len(x) - 1
279+
idxs = self.minmax_downsampler.downsample(
280+
x[1:n_1], y[1:n_1], n_out=n_out * minmax_ratio, **kwargs
281+
)
282+
idxs += 1
283+
idxs = np.concat(([0], idxs, [len(y) - 1])).ravel()
284+
print("idxs", idxs)
285+
return idxs[
286+
self.lttb_downsampler.downsample(x[idxs], y[idxs], n_out=n_out, **kwargs)
287+
]
288+
289+
290+
class MinMaxLTTB_py(_MinMaxLTTB_py):
291+
def __init__(
292+
self, check_contiguous=True, x_dtype_regex_list=None, y_dtype_regex_list=None
293+
):
294+
super().__init__(check_contiguous, x_dtype_regex_list, y_dtype_regex_list)
295+
self.minmax_downsampler = MinMax_py()
296+
self.lttb_downsampler = LTTB_py()
297+
298+
299+
class NaNMinMaxLTTB_py(_MinMaxLTTB_py):
300+
def __init__(
301+
self, check_contiguous=True, x_dtype_regex_list=None, y_dtype_regex_list=None
302+
):
303+
super().__init__(check_contiguous, x_dtype_regex_list, y_dtype_regex_list)
304+
self.minmax_downsampler = NaNMinMax_py()
305+
self.lttb_downsampler = LTTB_py()
306+
307+
308+
class _FPCS_py(AbstractDownsampler, ABC):
309+
def __init__(
310+
self, check_contiguous=True, x_dtype_regex_list=None, y_dtype_regex_list=None
311+
):
312+
super().__init__(check_contiguous, x_dtype_regex_list, y_dtype_regex_list)
313+
self.minmax_downsampler: AbstractDownsampler = None
314+
262315
def _downsample(
263316
self, x: Union[np.ndarray, None], y: np.ndarray, n_out: int, **kwargs
264317
) -> np.ndarray:
@@ -272,11 +325,16 @@ class Flag(Enum):
272325
Point = NamedTuple("point", [("x", int), ("val", y.dtype)])
273326
# ------------------------------------------------------------------------
274327

328+
# NOTE: is fine for this implementation as this is only used for testing
329+
if x is None:
330+
# Is fine for this implementation as this is only used for testing
331+
x = np.arange(y.shape[0])
332+
275333
# 0. Downsample the data using the MinMax algorithm
276334
MINMAX_FACTOR = 2
277335
n_1 = len(x) - 1
278336
# NOTE: as we include the first and last point, we reduce the number of points
279-
downsampled_idxs = MinMax_py().downsample(
337+
downsampled_idxs = self.minmax_downsampler.downsample(
280338
x[1:n_1], y[1:n_1], n_out=(n_out - 2) * MINMAX_FACTOR
281339
)
282340
downsampled_idxs += 1
@@ -329,3 +387,19 @@ class Flag(Enum):
329387
sampled_indices.append(len(y) - 1) # append the last point
330388
# fmt: on
331389
return np.array(sampled_indices, dtype=np.int64)
390+
391+
392+
class FPCS_py(_FPCS_py):
393+
def __init__(
394+
self, check_contiguous=True, x_dtype_regex_list=None, y_dtype_regex_list=None
395+
):
396+
super().__init__(check_contiguous, x_dtype_regex_list, y_dtype_regex_list)
397+
self.minmax_downsampler = MinMax_py()
398+
399+
400+
class NaNFPCS_py(_FPCS_py):
401+
def __init__(
402+
self, check_contiguous=True, x_dtype_regex_list=None, y_dtype_regex_list=None
403+
):
404+
super().__init__(check_contiguous, x_dtype_regex_list, y_dtype_regex_list)
405+
self.minmax_downsampler = NaNMinMax_py()

0 commit comments

Comments
 (0)