From 795af28e7f7a63f31991bb5609bd448fcfc49d8d Mon Sep 17 00:00:00 2001 From: Sean Law Date: Tue, 30 Dec 2025 23:12:07 -0500 Subject: [PATCH 1/5] Fixed #930 Improve `ignore_trivial` Docstring and Warnings --- stumpy/aamp.py | 1 + stumpy/aamped.py | 1 + stumpy/core.py | 21 +++++++++++++++++++++ stumpy/gpu_aamp.py | 1 + stumpy/gpu_stump.py | 8 ++++++-- stumpy/scraamp.py | 1 + stumpy/scrump.py | 8 ++++++-- stumpy/stomp.py | 1 + stumpy/stump.py | 8 ++++++-- stumpy/stumped.py | 8 ++++++-- tests/test_core.py | 6 ++++++ 11 files changed, 56 insertions(+), 8 deletions(-) diff --git a/stumpy/aamp.py b/stumpy/aamp.py index 940a20b2b..b5b0455a3 100644 --- a/stumpy/aamp.py +++ b/stumpy/aamp.py @@ -396,6 +396,7 @@ def aamp(T_A, m, T_B=None, ignore_trivial=True, p=2.0, k=1): """ if T_B is None: T_B = T_A.copy() + core.check_self_join(ignore_trivial) ignore_trivial = True T_A, T_A_subseq_isfinite = core.preprocess_non_normalized(T_A, m) diff --git a/stumpy/aamped.py b/stumpy/aamped.py index 14e6d237e..8da759dfa 100644 --- a/stumpy/aamped.py +++ b/stumpy/aamped.py @@ -375,6 +375,7 @@ def aamped(client, T_A, m, T_B=None, ignore_trivial=True, p=2.0, k=1): """ if T_B is None: T_B = T_A.copy() + core.check_self_join(ignore_trivial) ignore_trivial = True T_A, T_A_subseq_isfinite = core.preprocess_non_normalized(T_A, m) diff --git a/stumpy/core.py b/stumpy/core.py index 507a516db..5f6a957e0 100644 --- a/stumpy/core.py +++ b/stumpy/core.py @@ -4509,3 +4509,24 @@ def _update_incremental_PI(D, P, I, excl_zone, n_appended=0): _shift_insert_at_index(I[-1], idx, i + n_appended) return + + +def check_self_join(ignore_trivial): + """ + A simple function to check whether `ignore_trivial` is `True` for a self-join + + Otherwise, warn the user. + + Parameters + ---------- + ignore_trivial : bool + Set to True if this is a self-join. Otherwise, for AB-join, set this to False. + + Returns + ------- + None + """ + if not ignore_trivial: + msg = "`ignore_trivial` cannot be `False` for a self-join and " + msg += "has been automatically overridden and set to `True`." + warnings.warn(msg) diff --git a/stumpy/gpu_aamp.py b/stumpy/gpu_aamp.py index fc0c74068..9797f2252 100644 --- a/stumpy/gpu_aamp.py +++ b/stumpy/gpu_aamp.py @@ -519,6 +519,7 @@ def gpu_aamp(T_A, m, T_B=None, ignore_trivial=True, device_id=0, p=2.0, k=1): """ if T_B is None: # Self join! T_B = T_A + core.check_self_join(ignore_trivial) ignore_trivial = True T_A, T_A_subseq_isfinite = core.preprocess_non_normalized(T_A, m) diff --git a/stumpy/gpu_stump.py b/stumpy/gpu_stump.py index 16166ffb2..8eb54a88c 100644 --- a/stumpy/gpu_stump.py +++ b/stumpy/gpu_stump.py @@ -515,8 +515,11 @@ def gpu_stump( Default is ``None`` which corresponds to a self-join. ignore_trivial : bool, default True - Set to ``True`` if this is a self-join. Otherwise, for AB-join, set this - to ``False``. + Set to ``True`` if this is a self-join (i.e., for a single time series + ``T_A`` without ``T_B``). This ensures that an exclusion zone is applied + to each subsequence in ``T_A`` and all trivial/self-matches are ignored. + Otherwise, for an AB-join (i.e., between two times series, ``T_A`` and + ``T_B``), set this to ``False``. device_id : int or list, default 0 The (GPU) device number to use. The default value is ``0``. A list of @@ -644,6 +647,7 @@ def gpu_stump( """ if T_B is None: # Self join! T_B = T_A + core.check_self_join(ignore_trivial) ignore_trivial = True T_B_subseq_isconstant = T_A_subseq_isconstant diff --git a/stumpy/scraamp.py b/stumpy/scraamp.py index c0d9b5ee1..e4f9417c4 100644 --- a/stumpy/scraamp.py +++ b/stumpy/scraamp.py @@ -621,6 +621,7 @@ def __init__( if T_B is None: T_B = T_A + core.check_self_join(self._ignore_trivial) self._ignore_trivial = True self._m = m diff --git a/stumpy/scrump.py b/stumpy/scrump.py index 55e15ca6d..e837a7268 100644 --- a/stumpy/scrump.py +++ b/stumpy/scrump.py @@ -810,8 +810,11 @@ def __init__( subsequence in T_A, its nearest neighbor in T_B will be recorded. ignore_trivial : bool, default True - Set to `True` if this is a self-join. Otherwise, for AB-join, set this to - `False`. Default is `True`. + Set to ``True`` if this is a self-join (i.e., for a single time series + ``T_A`` without ``T_B``). This ensures that an exclusion zone is applied + to each subsequence in ``T_A`` and all trivial/self-matches are ignored. + Otherwise, for an AB-join (i.e., between two times series, ``T_A`` and + ``T_B``), set this to ``False``. percentage : float, default 0.01 Approximate percentage completed. The value is between 0.0 and 1.0. @@ -867,6 +870,7 @@ def __init__( if T_B is None: T_B = T_A + core.check_self_join(self._ignore_trivial) self._ignore_trivial = True T_B_subseq_isconstant = T_A_subseq_isconstant diff --git a/stumpy/stomp.py b/stumpy/stomp.py index 251d0fdc9..fc81aa03a 100644 --- a/stumpy/stomp.py +++ b/stumpy/stomp.py @@ -70,6 +70,7 @@ def _stomp(T_A, m, T_B=None, ignore_trivial=True): if T_B is None: T_B = T_A + core.check_self_join(ignore_trivial) ignore_trivial = True T_A, μ_Q, σ_Q, Q_subseq_isconstant = core.preprocess(T_A, m) diff --git a/stumpy/stump.py b/stumpy/stump.py index b70a776aa..c5bd435db 100644 --- a/stumpy/stump.py +++ b/stumpy/stump.py @@ -542,8 +542,11 @@ def stump( Default is ``None`` which corresponds to a self-join. ignore_trivial : bool, default True - Set to ``True`` if this is a self-join. Otherwise, for AB-join, set this - to ``False``. + Set to ``True`` if this is a self-join (i.e., for a single time series + ``T_A`` without ``T_B``). This ensures that an exclusion zone is applied + to each subsequence in ``T_A`` and all trivial/self-matches are ignored. + Otherwise, for an AB-join (i.e., between two times series, ``T_A`` and + ``T_B``), set this to ``False``. normalize : bool, default True When set to ``True``, this z-normalizes subsequences prior to computing @@ -677,6 +680,7 @@ def stump( mparray([4, 3, 0, 1, 0]) """ if T_B is None: + core.check_self_join(ignore_trivial) ignore_trivial = True T_B = T_A T_B_subseq_isconstant = T_A_subseq_isconstant diff --git a/stumpy/stumped.py b/stumpy/stumped.py index 0cfa331b2..c097b3719 100644 --- a/stumpy/stumped.py +++ b/stumpy/stumped.py @@ -429,8 +429,11 @@ def stumped( Default is ``None`` which corresponds to a self-join. ignore_trivial : bool, default True - Set to ``True`` if this is a self-join. Otherwise, for AB-join, set this - to ``False``. + Set to ``True`` if this is a self-join (i.e., for a single time series + ``T_A`` without ``T_B``). This ensures that an exclusion zone is applied + to each subsequence in ``T_A`` and all trivial/self-matches are ignored. + Otherwise, for an AB-join (i.e., between two times series, ``T_A`` and + ``T_B``), set this to ``False``. normalize : bool, default True When set to ``True``, this z-normalizes subsequences prior to computing @@ -585,6 +588,7 @@ def stumped( """ if T_B is None: T_B = T_A + core.check_self_join(ignore_trivial) ignore_trivial = True T_B_subseq_isconstant = T_A_subseq_isconstant diff --git a/tests/test_core.py b/tests/test_core.py index 17059d5dc..109754b9b 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1963,3 +1963,9 @@ def test_update_incremental_PI_egressTrue_MemoryCheck(): npt.assert_almost_equal(P_ref, P_comp) npt.assert_almost_equal(I_ref, I_comp) + + +def test_check_self_join(): + with pytest.warns(UserWarning): + ignore_trivial = False + core.check_self_join(ignore_trivial) From 1860cfb87e0f263e9b651ff2c901d47c1a3f936c Mon Sep 17 00:00:00 2001 From: Sean Law Date: Wed, 31 Dec 2025 09:02:14 -0500 Subject: [PATCH 2/5] Added note to docstring --- stumpy/core.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/stumpy/core.py b/stumpy/core.py index 5f6a957e0..e3c8a201b 100644 --- a/stumpy/core.py +++ b/stumpy/core.py @@ -4525,6 +4525,22 @@ def check_self_join(ignore_trivial): Returns ------- None + + Notes + ----- + These warnings may be supressed by using a context manager + ``` + import stumpy + import numpy as np + import warnings + + T = np.random.rand(10_000) + m = 50 + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", message="`ignore_trivial` cannot be `False`") + for _ in range(5): + stumpy.stump(T, m, ignore_trivial=False) + ``` """ if not ignore_trivial: msg = "`ignore_trivial` cannot be `False` for a self-join and " From 3b8bae8940e84882472979ef630464296d394939 Mon Sep 17 00:00:00 2001 From: Sean Law Date: Wed, 31 Dec 2025 09:03:14 -0500 Subject: [PATCH 3/5] Fixed spelling --- stumpy/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stumpy/core.py b/stumpy/core.py index e3c8a201b..80fe50e05 100644 --- a/stumpy/core.py +++ b/stumpy/core.py @@ -3752,7 +3752,7 @@ def check_ignore_trivial(T_A, T_B, ignore_trivial): Notes ----- - These warnings may be supressed by using a context manager + These warnings may be suppressed by using a context manager ``` import stumpy import numpy as np @@ -4528,7 +4528,7 @@ def check_self_join(ignore_trivial): Notes ----- - These warnings may be supressed by using a context manager + These warnings may be suppressed by using a context manager ``` import stumpy import numpy as np From e2c12ba5f05a747d0167f874ab32d5b81313ad8e Mon Sep 17 00:00:00 2001 From: Sean Law Date: Wed, 31 Dec 2025 21:32:20 -0500 Subject: [PATCH 4/5] Removed reference to default value --- stumpy/core.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stumpy/core.py b/stumpy/core.py index 80fe50e05..f3d885579 100644 --- a/stumpy/core.py +++ b/stumpy/core.py @@ -3738,11 +3738,10 @@ def check_ignore_trivial(T_A, T_B, ignore_trivial): T_B : numpy.ndarray The time series or sequence that will be used to annotate T_A. For every - subsequence in T_A, its nearest neighbor in T_B will be recorded. Default is - `None` which corresponds to a self-join. + subsequence in T_A, its nearest neighbor in T_B will be recorded. ignore_trivial : bool - Set to `True` if this is a self-join. Otherwise, for AB-join, set this + Set to `True` if this is a self-join. Otherwise, for an AB-join, set this to `False`. Returns From b4822a03e040a4833754b4bdf53e0ee843732c36 Mon Sep 17 00:00:00 2001 From: Sean Law Date: Wed, 31 Dec 2025 21:36:23 -0500 Subject: [PATCH 5/5] Switched if condition to check `is False` --- stumpy/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stumpy/core.py b/stumpy/core.py index f3d885579..4f286f706 100644 --- a/stumpy/core.py +++ b/stumpy/core.py @@ -4541,7 +4541,7 @@ def check_self_join(ignore_trivial): stumpy.stump(T, m, ignore_trivial=False) ``` """ - if not ignore_trivial: + if ignore_trivial is False: msg = "`ignore_trivial` cannot be `False` for a self-join and " msg += "has been automatically overridden and set to `True`." warnings.warn(msg)