FerroWave · guides

Conventions

Sign, indexing, length, and padding conventions shared across ferro-wave transforms.

Wavelet bugs hide in boundary handling and normalization. ferro-wave names those choices on the surface so a reader of the call site can reproduce the math without reading the source.

Boundary modes are explicit

Every transform that extends a signal at its edges takes a BoundaryMode at the call site. There is no implicit edge extension hidden inside a transform.

BoundaryModeDescription
PeriodicWrap-around extension. Matches PyWavelets periodization; the canonical choice for tight round-trips.
SymmetricMirror the signal at the boundary (half-sample symmetry).
ZeroPadExtend with zeros beyond the support.
ReflectWhole-sample reflection at the boundary.

PyWavelets-canonical output lengths

DWT output lengths match PyWavelets exactly across odd and even N. MODWT, SWT, and SST are shift-invariant — no downsampling — so every decomposition level keeps the input length. That length invariance is what makes per-level coefficients line up sample-for-sample with the input for streaming and attribution.

Energy identities hold

Each transform documents its normalization and the Parseval identity it satisfies, so band variances attribute cleanly:

  • MODWTV2+W2=x2\lVert V \rVert^2 + \lVert W \rVert^2 = \lVert x \rVert^2 across scaling and detail coefficients per level (Percival & Walden).
  • SWT — the two-channel frame identity A2+D2=2x2\lVert A \rVert^2 + \lVert D \rVert^2 = 2\lVert x \rVert^2.
  • DWT (multilevel) — band variances sum to the signal variance (Parseval), so a multi-scale variance decomposition is a clean attribution by frequency octave.

Numerical equivalence is the reference

Every DWT, MODWT, SWT, WPT, and CWT coefficient is pinned to PyWavelets and scipy at 1e-10 in the test suite. Orthogonal-wavelet round-trips pin to 1e-10; ICWT round-trip correlation runs ≥ 0.987 across every wavelet × signal pair. A feature pipeline prototyped against PyWavelets ports to ferro-wave with the same numbers — no retraining for numerical drift.

API shape

  • Every *Config is a #[non_exhaustive] struct with a Default impl and with_* builders, so new knobs land without breaking call sites.
  • One Wavelet trait, one Signal<T> type, one BoundaryMode enum, and one ferro_wave::Result<_> across the library.
  • Forward and inverse are paired wherever a transform is invertible — dwt/idwt, modwt/imodwt, cwt/icwt.