WaveletCoherence#

class cultivars.spectral.wavelets.WaveletCoherence(*, omega0=_MORLET_OMEGA0, per_octave=_SCALES_PER_OCTAVE, smallest=2.0, surrogates=_COHERENCE_SURROGATES, alpha=_DEFAULT_ALPHA, seed=None)[source]

Bases: object

Morlet wavelet coherence of two series, with cone of influence and surrogate significance.

The continuous transform of a series against the Morlet wavelet \(\psi(\eta) = \pi^{-1/4} e^{i\omega_0\eta} e^{-\eta^2/2}\) at scale \(s\),

\[W_x(s, t) = \sum_{u} x_u \sqrt{\frac{\delta}{s}}\; \overline{\psi}\Bigl(\frac{u - t}{s}\Bigr),\]

is evaluated on a dyadic grid \(s_k = s_0 2^{k / v}\) with \(v\) voices per octave from smallest up to the sample length, for both series; the coherence and phase of the pair, the cone of influence, and (unless surrogates=0) the per-scale significance level are assembled into a WaveletCoherenceResult. The significance level is empirical: each series is replaced surrogates times by a Gaussian AR(1) with its own lag-one autocorrelation and variance, the two independent surrogates’ coherence is pooled over dates outside the cone at every scale, and its \(1 - \alpha\) quantile is the level a real coherence has to beat.

Variables:
  • _omega0 – The Morlet centre frequency.

  • _per_octave – Voices per octave.

  • _smallest – The smallest scale.

  • _surrogates – Surrogate pairs for the significance level.

  • _alpha – The significance level.

  • _seed – The seed for the surrogate draws, or None.

Parameters:
  • omega0 (float) – Morlet centre frequency, above 4; 6 makes scale and Fourier period nearly equal (ratio 1.03) and satisfies admissibility.

  • per_octave (int) – Voices per octave on the dyadic scale grid, at least 1; 8 by default.

  • smallest (float) – Smallest scale, in observations, above 1; 2 is the Nyquist limit.

  • surrogates (int) – AR(1) surrogate pairs behind the significance level, 300 by default; 0 skips it and leaves significance as None.

  • alpha (float) – Level of the significance threshold, inside (0, 1).

  • seed (int | None) – Seed for the surrogate draws; None draws fresh each call.

Raises:

SpecificationError – If a setting is out of range.

Note

The surrogate step dominates the cost – it runs the full bivariate transform surrogates times – so the default 300 pairs on a few hundred observations takes seconds, and the example below uses surrogates=0 where only the point estimate is needed. The AR(1) null tests comovement beyond what two independent persistent series would show; it is not a test against a richer null, and a pair of series sharing a common deterministic seasonal will be “significantly” coherent at that period for the uninteresting reason.

Warning

With seed=None the significance level differs between runs by surrogate sampling noise. Pass a seed for any result that will be reported.

See also

References

Torrence, C., & Compo, G. P. (1998). A practical guide to wavelet analysis. Bulletin of the American Meteorological Society, 79(1), 61-78.

Grinsted, A., Moore, J. C., & Jevrejeva, S. (2004). Application of the cross wavelet transform and wavelet coherence to geophysical time series. Nonlinear Processes in Geophysics, 11, 561-566.

Example

>>> t = np.arange(256.0)
>>> x = np.sin(2 * np.pi * t / 16)
>>> y = np.sin(2 * np.pi * (t - 2) / 16)
>>> res = WaveletCoherence(per_octave=4, surrogates=0).compute(x, y)
>>> bool(res.coherence[np.argmin(np.abs(res.periods - 16)), 128] > 0.95)
True
>>> bool(1.5 < res.lead((14.0, 18.0)) < 2.5)
True

The phase at the signal’s period is the delay in radians, \(2\pi \cdot 2 / 16\):

>>> row = int(np.argmin(np.abs(res.periods - 16)))
>>> round(float(res.phase[row, 128]), 3), round(2 * np.pi * 2 / 16, 3)
(0.785, 0.785)

Private attributes#