Skip to content

Commit 0fdd090

Browse files
committed
Fixed #342 Refactored Non-normalized Functions
1 parent 655eabd commit 0fdd090

17 files changed

Lines changed: 407 additions & 123 deletions

docs/api.rst

Lines changed: 3 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,16 @@ STUMPY API
1515
stumpy.mstump
1616
stumpy.mstumped
1717
stumpy.subspace
18-
stumpy.aamp
19-
stumpy.aamped
20-
stumpy.gpu_aamp
21-
stumpy.aampi
22-
stumpy.maamp
23-
stumpy.maamped
2418
stumpy.atsc
2519
stumpy.allc
2620
stumpy.fluss
2721
stumpy.floss
2822
stumpy.ostinato
2923
stumpy.ostinatoed
3024
stumpy.gpu_ostinato
31-
stumpy.aamp_ostinato
32-
stumpy.aamp_ostinatoed
33-
stumpy.gpu_aamp_ostinato
3425
stumpy.mpdist
3526
stumpy.mpdisted
3627
stumpy.gpu_mpdist
37-
stumpy.aampdist
38-
stumpy.aampdisted
39-
stumpy.gpu_aampdist
4028

4129
stump
4230
=====
@@ -51,7 +39,7 @@ stumped
5139
gpu-stump
5240
=========
5341

54-
.. autofunction:: stumpy.gpu_stump(T_A, m, T_B=None, ignore_trivial=True, device_id=0)
42+
.. autofunction:: stumpy.gpu_stump(T_A, m, T_B=None, ignore_trivial=True, device_id=0, normalize=True)
5543

5644
scrump
5745
======
@@ -77,36 +65,6 @@ subspace
7765
========
7866
.. autofunction:: stumpy.subspace
7967

80-
aamp
81-
====
82-
83-
.. autofunction:: stumpy.aamp
84-
85-
aamped
86-
======
87-
88-
.. autofunction:: stumpy.aamped
89-
90-
gpu_aamp
91-
========
92-
93-
.. autofunction:: stumpy.gpu_aamp(T_A, m, T_B=None, ignore_trivial=True, device_id=0)
94-
95-
aampi
96-
=====
97-
98-
.. autofunction:: stumpy.aampi
99-
100-
maamp
101-
=====
102-
103-
.. autofunction:: stumpy.maamp
104-
105-
maamped
106-
=======
107-
108-
.. autofunction:: stumpy.maamped
109-
11068
atsc
11169
====
11270

@@ -140,22 +98,7 @@ ostinatoed
14098
gpu_ostinato
14199
============
142100

143-
.. autofunction:: gpu_ostinato(Ts, m, device_id=0)
144-
145-
aamp_ostinato
146-
=============
147-
148-
.. autofunction:: stumpy.aamp_ostinato
149-
150-
aamp_ostinatoed
151-
===============
152-
153-
.. autofunction:: stumpy.aamp_ostinatoed
154-
155-
gpu_aamp_ostinato
156-
=================
157-
158-
.. autofunction:: stumpy.gpu_aamp_ostinato(Ts, m, device_id=0)
101+
.. autofunction:: gpu_ostinato(Ts, m, device_id=0, normalize=True)
159102

160103
mpdist
161104
======
@@ -170,19 +113,4 @@ mpdisted
170113
gpu_mpdist
171114
==========
172115

173-
.. autofunction:: stumpy.gpu_mpdist(T_A, T_B, m, percentage=0.05, k=None, device_id=0)
174-
175-
aampdist
176-
========
177-
178-
.. autofunction:: stumpy.aampdist
179-
180-
aampdisted
181-
==========
182-
183-
.. autofunction:: stumpy.aampdisted
184-
185-
gpu_aampdist
186-
============
187-
188-
.. autofunction:: stumpy.gpu_aampdist(T_A, T_B, m, percentage=0.05, k=None, device_id=0)
116+
.. autofunction:: stumpy.gpu_mpdist(T_A, T_B, m, percentage=0.05, k=None, device_id=0, normalize=True)

stumpy/aampdist.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22
# Copyright 2019 TD Ameritrade. Released under the terms of the 3-Clause BSD license.
33
# STUMPY is a trademark of TD Ameritrade IP Company, Inc. All rights reserved.
44

5-
from . import aamp, aamped
5+
from . import aamp, aamped, mpdist
66
from .core import _mass_absolute_distance_matrix
7-
from .mpdist import _mpdist, _mpdist_vect
87

98

109
def _aampdist_vect(
@@ -47,7 +46,7 @@ def _aampdist_vect(
4746
`MPdist` value. The `percentage` and `k` parameters are ignored when
4847
`custom_func` is not None.
4948
"""
50-
return _mpdist_vect(
49+
return mpdist._mpdist_vect(
5150
Q,
5251
T,
5352
m,
@@ -97,7 +96,7 @@ def aampdist(T_A, T_B, m, percentage=0.05, k=None):
9796
9897
See Section III
9998
"""
100-
return _mpdist(T_A, T_B, m, percentage, k, mp_func=aamp)
99+
return mpdist._mpdist(T_A, T_B, m, percentage, k, mp_func=aamp)
101100

102101

103102
def aampdisted(dask_client, T_A, T_B, m, percentage=0.05, k=None):
@@ -150,4 +149,6 @@ def aampdisted(dask_client, T_A, T_B, m, percentage=0.05, k=None):
150149
151150
See Section III
152151
"""
153-
return _mpdist(T_A, T_B, m, percentage, k, dask_client=dask_client, mp_func=aamped)
152+
return mpdist._mpdist(
153+
T_A, T_B, m, percentage, k, dask_client=dask_client, mp_func=aamped
154+
)

stumpy/core.py

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
# Copyright 2019 TD Ameritrade. Released under the terms of the 3-Clause BSD license. # noqa: E501
33
# STUMPY is a trademark of TD Ameritrade IP Company, Inc. All rights reserved.
44

5-
from functools import partial
5+
import logging
6+
import functools
7+
import inspect
8+
69
import numpy as np
710
from numba import njit, prange
811
from scipy.signal import convolve
@@ -17,6 +20,8 @@
1720
except ImportError:
1821
pass
1922

23+
logger = logging.getLogger(__name__)
24+
2025

2126
def driver_not_found(*args, **kwargs): # pragma: no cover
2227
"""
@@ -1583,10 +1588,88 @@ def _get_partial_mp_func(mp_func, dask_client=None, device_id=None):
15831588
`device_id` into `functools.partial` function where possible
15841589
"""
15851590
if dask_client is not None:
1586-
partial_mp_func = partial(mp_func, dask_client)
1591+
partial_mp_func = functools.partial(mp_func, dask_client)
15871592
elif device_id is not None:
1588-
partial_mp_func = partial(mp_func, device_id=device_id)
1593+
partial_mp_func = functools.partial(mp_func, device_id=device_id)
15891594
else:
15901595
partial_mp_func = mp_func
15911596

15921597
return partial_mp_func
1598+
1599+
1600+
def compare_parameters(norm, non_norm, exclude=None):
1601+
"""
1602+
Compare if the parameters in `norm` and `non_norm` are the same
1603+
1604+
Parameters
1605+
----------
1606+
norm : object
1607+
The normalized function (or class) that is complementary to the
1608+
non-normalized function (or class)
1609+
1610+
non_norm : object
1611+
The non-normalized function (or class) that is complementary to the
1612+
z-normalized function (or class)
1613+
1614+
exclude : list
1615+
A list of parameters to exclude
1616+
1617+
Returns
1618+
-------
1619+
is_same_params : bool
1620+
`True` if parameters from both `norm` and `non-norm` are the same. `False`
1621+
otherwise.
1622+
"""
1623+
norm_params = list(inspect.signature(norm).parameters.keys())
1624+
non_norm_params = list(inspect.signature(non_norm).parameters.keys())
1625+
1626+
if exclude is not None:
1627+
for param in exclude:
1628+
norm_params.remove(param)
1629+
1630+
is_same_params = set(norm_params) == set(non_norm_params)
1631+
if not is_same_params:
1632+
if exclude is not None:
1633+
logger.warning(f"Excluding `{exclude}` parameters, ")
1634+
logger.warning(f"`{norm}` and `{non_norm}` have different parameters.")
1635+
1636+
return is_same_params
1637+
1638+
1639+
def non_normalized(non_norm):
1640+
"""
1641+
Decorator for swapping a z-normalized function (or class) for its complementary
1642+
non-normalized function (or class) as defined by `non_norm`. This requires that
1643+
the z-normalized function (or class) has a `normalize` parameter.
1644+
1645+
With the exception of `normalize` parameter, the `non_norm` function (or class)
1646+
must have the same siganture as the `norm` function (or class) signature in order
1647+
to be compatible.
1648+
1649+
Parameters
1650+
----------
1651+
non_norm : object
1652+
The non-normalized function (or class) that is complementary to the
1653+
z-normalized function (or class)
1654+
1655+
Returns
1656+
-------
1657+
outer_wrapper : object
1658+
The desired z-normalized/non-normalized function (or class)
1659+
"""
1660+
1661+
@functools.wraps(non_norm)
1662+
def outer_wrapper(norm):
1663+
@functools.wraps(norm)
1664+
def inner_wrapper(*args, **kwargs):
1665+
is_same_params = compare_parameters(norm, non_norm, exclude=["normalize"])
1666+
1667+
if not is_same_params or kwargs.get("normalize", True):
1668+
return norm(*args, **kwargs)
1669+
else:
1670+
kwargs = {k: v for k, v in kwargs.items() if k != "normalize"}
1671+
return non_norm(*args, **kwargs)
1672+
1673+
return inner_wrapper
1674+
1675+
return outer_wrapper

stumpy/gpu_mpdist.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
# import numpy as np
66
# import math
77

8-
from . import gpu_stump
8+
from . import core, gpu_stump
99
from .mpdist import _mpdist
10+
from .gpu_aampdist import gpu_aampdist
1011

1112

12-
def gpu_mpdist(T_A, T_B, m, percentage=0.05, k=None, device_id=0):
13+
@core.non_normalized(gpu_aampdist)
14+
def gpu_mpdist(T_A, T_B, m, percentage=0.05, k=None, device_id=0, normalize=True):
1315
"""
1416
Compute the z-normalized matrix profile distance (MPdist) measure between any two
1517
time series with one or more GPU devices
@@ -46,6 +48,11 @@ def gpu_mpdist(T_A, T_B, m, percentage=0.05, k=None, device_id=0):
4648
computation. A list of all valid device ids can be obtained by
4749
executing `[device.id for device in numba.cuda.list_devices()]`.
4850
51+
normalize : bool, default True
52+
When set to `True`, this z-normalizes subsequences prior to computing distances.
53+
Otherwise, this function gets re-routed to its complementary non-normalized
54+
equivalent set in the `@core.non_normalized` function decorator.
55+
4956
Returns
5057
-------
5158
MPdist : float

stumpy/gpu_ostinato.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
from . import core, gpu_stump
66
from .ostinato import _ostinato, _get_central_motif
7+
from .gpu_aamp_ostinato import gpu_aamp_ostinato
78

89

9-
def gpu_ostinato(Ts, m, device_id=0):
10+
@core.non_normalized(gpu_aamp_ostinato)
11+
def gpu_ostinato(Ts, m, device_id=0, normalize=True):
1012
"""
1113
Find the z-normalized consensus motif of multiple time series with one or more GPU
1214
devices
@@ -29,6 +31,11 @@ def gpu_ostinato(Ts, m, device_id=0):
2931
computation. A list of all valid device ids can be obtained by
3032
executing `[device.id for device in numba.cuda.list_devices()]`.
3133
34+
normalize : bool, default True
35+
When set to `True`, this z-normalizes subsequences prior to computing distances.
36+
Otherwise, this function gets re-routed to its complementary non-normalized
37+
equivalent set in the `@core.non_normalized` function decorator.
38+
3239
Returns
3340
-------
3441
central_radius : float

stumpy/gpu_stump.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from numba import cuda
1111

1212
from . import core, config
13+
from .gpu_aamp import gpu_aamp
1314

1415
logger = logging.getLogger(__name__)
1516

@@ -371,7 +372,8 @@ def _gpu_stump(
371372
return profile_fname, indices_fname
372373

373374

374-
def gpu_stump(T_A, m, T_B=None, ignore_trivial=True, device_id=0):
375+
@core.non_normalized(gpu_aamp)
376+
def gpu_stump(T_A, m, T_B=None, ignore_trivial=True, device_id=0, normalize=True):
375377
"""
376378
Compute the z-normalized matrix profile with one or more GPU devices
377379
@@ -401,6 +403,11 @@ def gpu_stump(T_A, m, T_B=None, ignore_trivial=True, device_id=0):
401403
computation. A list of all valid device ids can be obtained by
402404
executing `[device.id for device in numba.cuda.list_devices()]`.
403405
406+
normalize : bool, default True
407+
When set to `True`, this z-normalizes subsequences prior to computing distances.
408+
Otherwise, this function gets re-routed to its complementary non-normalized
409+
equivalent set in the `@core.non_normalized` function decorator.
410+
404411
Returns
405412
-------
406413
out : ndarray

0 commit comments

Comments
 (0)