chaotic_pfc.dynamics.spectral

spectral.py

Power-spectral-density estimation utilities used by the plotting layer.

The single public function, psd_normalised(), wraps scipy.signal.welch() with the conventions adopted throughout the project: peak-normalised magnitude, and the frequency axis expressed as ω/π [0, 1] rather than cycles or hertz.

Functions

psd_normalised(x[, nfft, window_length, fs, ...])

Estimate the normalised power-spectral density of x via Welch.

chaotic_pfc.dynamics.spectral.psd_normalised(x, nfft=4096, window_length=1024, fs=1.0, remove_dc=True, *, window='hamming', kaiser_beta=5.0)[source]

Estimate the normalised power-spectral density of x via Welch.

The PSD is one-sided, peak-normalised to 1.0, and the frequency axis is returned as ω/π for consistency with the notation used in the project figures (x-axis of every PSD panel).

Parameters:
  • x (ndarray[tuple[Any, ...], dtype[_ScalarT]]) – Input signal, shape (N,). Can be any dtype coercible to float.

  • nfft (int) – Length of the FFT. Larger values give smoother spectra at the cost of more computation. Must be >= window_length.

  • window_length (int) – Length of the Welch segment (aka nperseg). Controls the frequency resolution.

  • fs (float) – Sampling frequency. Leave at the default 1.0 to work in normalised units — the output axis becomes ω/π directly.

  • remove_dc (bool) – If True (default), the DC component of x is subtracted before the FFT to avoid a spurious spike at ω = 0. Set to False only if you explicitly want to see the DC bin.

  • window (str) – Welch window. Supported values: "hamming" (default), "hann", "blackman", "kaiser", "blackmanharris", "boxcar", "bartlett".

  • kaiser_beta (float) – Shape parameter of the Kaiser window. Must be >= 0; ignored when window != "kaiser".

Returns:

  • omega_norm (ndarray, shape (nfft // 2 + 1,)) – Normalised frequency axis, ω/π [0, 1].

  • psd (ndarray, shape (nfft // 2 + 1,)) – Peak-normalised PSD. psd.max() == 1.0. Raises ValueError when the input is identically zero.

Return type:

tuple[ndarray[tuple[Any, …], dtype[_ScalarT]], ndarray[tuple[Any, …], dtype[_ScalarT]]]

Notes

Welch’s method divides x into overlapping segments, applies the window, takes the periodogram of each, and averages the result. This trades frequency resolution (controlled by window_length) for variance reduction, which is the right trade-off for visualising the smooth broadband spectrum of a chaotic carrier.

Segment overlap is left at the scipy default of 50 % (noverlap = nperseg // 2).