@@ -164,6 +164,7 @@ def detect(
164164 y = RobustPeriod ._preprocess (x , lamb , c )
165165
166166 # TODO Decouple multiple periodicities
167+ RobustPeriod ._decouple_periodicities (y )
167168
168169 # TODO Robust single periodicity detection
169170
@@ -218,6 +219,18 @@ def _preprocess(
218219 mad = np .mean (np .abs (y - mean ))
219220 return RobustPeriod ._huber ((y - mean ) / mad , c )
220221
222+ @staticmethod
223+ def _decouple_periodicities (x : ArrayLike , db_n : int , level : int ):
224+ w_coeffs = RobustPeriod ._modwt (x , db_n , level )
225+ bivar = np .array (
226+ [
227+ # Exclude the first Lj - 1 coefficients
228+ RobustPeriod ._biweight_midvariance (w_coeffs [j ][1 ][j :], 9 )
229+ for j in range (level )
230+ ]
231+ )
232+ pass
233+
221234 @staticmethod
222235 def _hpfilter (x : ArrayLike , lamb : float ):
223236 """
@@ -303,3 +316,23 @@ def _modwt(x: ArrayLike, db_n: int, level: int) -> NDArray:
303316
304317 # Compute the Maximal Overlap Discrete Wavelet Transform
305318 return pywt .swt (y , "db{}" .format (db_n ), level , norm = True )
319+
320+ @staticmethod
321+ def _biweight_midvariance (x : ArrayLike , c : float ) -> float :
322+ # Ensure the correct data type
323+ x = np .asanyarray (x ).astype (np .float64 )
324+
325+ # Compute u
326+ med = np .median (x )
327+ mad = np .mean (np .abs (x - np .mean (x )))
328+ u = (x - med ) / (c * mad )
329+
330+ # Indicator function
331+ indicator = np .abs (u ) < 1
332+
333+ # Return the biweight midvariance estimation result
334+ return (
335+ len (x )
336+ * np .sum ((x [indicator ] - med ) ** 2 * (1 - u [indicator ] ** 2 ) ** 4 )
337+ / np .sum ((1 - u [indicator ] ** 2 ) * (1 - 5 * u [indicator ] ** 2 )) ** 2
338+ )
0 commit comments