MODWT#

class cultivars.spectral.wavelets.MODWT(*, wavelet='la8', levels=None)[source]#

Maximal-overlap discrete wavelet transform and multiresolution analysis.

The pyramid filters the level-\((j-1)\) scaling coefficients with the wavelet and scaling filters upsampled by \(2^{j-1}\),

\[W_{j,t} = \sum_{l=0}^{L-1} \tilde h_l\, V_{j-1,\,t - 2^{j-1} l \bmod T}, \qquad V_{j,t} = \sum_{l=0}^{L-1} \tilde g_l\, V_{j-1,\,t - 2^{j-1} l \bmod T},\]

starting from \(V_0 = y\), with the DWT filters rescaled by \(1/\sqrt 2\) so that energy is preserved without decimation. Because nothing is decimated the transform is shift-invariant, every level has \(T\) coefficients aligned with the data, and the multiresolution details are zero-phase – the properties that make it the wavelet transform for time series rather than for compression. The cost is redundancy (\(J + 1\) series of length \(T\)) and the circular boundary, which touches \((2^j - 1)(L - 1)\) coefficients at level \(j\); the default depth is the largest \(J\) at which that count still leaves a boundary-free coefficient, \(\lfloor \log_2(T/(L-1)) \rfloor\).

Variables:
  • _wavelet – The validated filter name.

  • _levels – The requested depth, or None for the default.

Parameters:
  • wavelet (str) – "haar" (2 taps, the first difference at level 1), "d4" (Daubechies extremal phase, 4 taps) or "la8" (least asymmetric, 8 taps; the default – near-zero phase and a sharper band split than Haar).

  • levels (int | None) – Detail levels J, at least 1. By default the largest J for which every level keeps a boundary-free coefficient, floor(log2(T / (L - 1))).

Raises:

SpecificationError – If the wavelet is unknown or levels is not an integer of at least 1.

Note

Shorter filters have less boundary contamination and a blurrier band split; haar at level 1 is exactly half the first difference, so its “band” leaks across the whole spectrum, while la8 confines a period-12 sinusoid to level 3 with 98% of its energy. Deeper levels have fewer degrees of freedom by a factor of two each, so the default depth is an upper bound on what is estimable, not a recommendation.

See also

  • MODWTResult – the result.

  • WaveletCoherence – the continuous Morlet transform for time-frequency comovement of two series.

  • BaxterKingFilter – a band-pass on any stated band, when octaves are the wrong partition.

References

Percival, D. B., & Walden, A. T. (2000). Wavelet Methods for Time Series Analysis, chapter 5. Cambridge University Press.

Gencay, R., Selcuk, F., & Whitcher, B. (2002). An Introduction to Wavelets and Other Filtering Methods in Finance and Economics. Academic Press.

Example

>>> rng = np.random.default_rng(0)
>>> y = rng.standard_normal(256)
>>> res = MODWT(wavelet="haar", levels=3).transform(y)
>>> res.levels, bool(np.allclose(res.details.sum(axis=0) + res.smooth, y))
(3, True)

The default depth depends on the filter length: 256 observations support 8 Haar levels, 6 of d4 and 5 of la8:

>>> [MODWT(wavelet=w).transform(y).levels for w in ("haar", "d4", "la8")]
[8, 6, 5]

Methods#

transform(endog)

Decompose a series.