Skip to content

freq_map

MATLAB equivalent: sidFreqMap

freq_map

Time-varying frequency response map via segmented spectral analysis.

freq_map

freq_map(y: ndarray | list, u: ndarray | list | None = None, *, segment_length: int | None = None, overlap: int | None = None, algorithm: str = 'bt', sample_time: float = 1.0, window_size: int | None = None, frequencies: ndarray | None = None, sub_segment_length: int | None = None, sub_overlap: int | None = None, window: str | ndarray = 'hann', nfft: int | None = None) -> FreqMapResult

Estimate a time-varying frequency response map.

Estimates G(omega, t) by applying spectral analysis to overlapping segments of input-output data. For a linear time-invariant (LTI) system the map is constant along time; for a linear time-varying (LTV) system it reveals how the transfer function, noise spectrum, and coherence evolve.

Two inner estimation algorithms are supported:

  • 'bt' (default) -- Blackman-Tukey correlogram via :func:sid.freq_bt.
  • 'welch' -- Welch averaged periodogram.

Parameters:

Name Type Description Default
y ndarray or list of ndarray, shape (N, ny) or (N, ny, L)

Output data. A 1-D array is treated as a single-channel signal. For multiple trajectories pass a 3-D array (N, ny, L) or a list of 1-D / 2-D arrays. Spectral estimates within each segment are ensemble-averaged.

required
u ndarray, list of ndarray, or None

Input data. Same shape conventions as y. Pass None for time-series mode (output spectrum only). Default is None.

None
segment_length int

Number of samples per outer segment L. Must be >= 4. Default: min(N // 4, 256).

None
overlap int

Overlap P between segments, 0 <= P < L. Default: L // 2.

None
algorithm str

'bt' (default) or 'welch'.

'bt'
sample_time float

Sample time in seconds. Must be positive. Default is 1.0.

1.0
window_size int

(BT only) Hann lag window size M. Default: min(L // 10, 30).

None
frequencies (ndarray, shape(nf))

(BT only) Frequency vector in rad/sample, in (0, pi]. Default: 128-point linear grid.

None
sub_segment_length int

(Welch only) Sub-segment length within each outer segment. Default: floor(L / 4.5).

None
sub_overlap int

(Welch only) Sub-segment overlap. Default: sub_segment_length // 2.

None
window str or ndarray

(Welch only) 'hann' (default), 'hamming', 'rect', or a numeric window vector of length sub_segment_length.

'hann'
nfft int

(Welch only) FFT length. Default: max(256, 2**ceil(log2(sub_segment_length))).

None

Returns:

Type Description
FreqMapResult

Frozen dataclass with fields:

  • time (ndarray, shape (K,)) -- Centre time of each segment in seconds.
  • frequency (ndarray, shape (nf,)) -- Frequency vector, rad/sample.
  • frequency_hz (ndarray, shape (nf,)) -- Frequency vector, Hz.
  • response (ndarray or None) -- Complex time-varying frequency response. Shape (nf, K) for SISO, (nf, K, ny, nu) for MIMO, or None in time-series mode.
  • response_std (ndarray or None) -- Standard deviation of response, same shape.
  • noise_spectrum (ndarray) -- Time-varying noise spectrum. Shape (nf, K) for SISO / time-series, (nf, K, ny, ny) for MIMO.
  • noise_spectrum_std (ndarray) -- Standard deviation of noise_spectrum, same shape.
  • coherence (ndarray or None) -- Squared coherence, shape (nf, K). SISO only; None for MIMO or time-series.
  • sample_time (float) -- Sample time in seconds.
  • segment_length (int) -- Segment length L.
  • overlap (int) -- Overlap P between segments.
  • window_size (int or None) -- BT lag window size M, or None for Welch.
  • algorithm (str) -- 'bt' or 'welch'.
  • num_trajectories (int) -- Number of trajectories.
  • method (str) -- Always 'freq_map'.

Raises:

Type Description
SidError

If segment_length < 4 (code: 'invalid_segment_length').

SidError

If segment_length > N (code: 'segment_too_long').

SidError

If sample_time <= 0 (code: 'invalid_sample_time').

SidError

If algorithm is not 'bt' or 'welch' (code: 'invalid_algorithm').

SidError

If overlap is not in [0, L-1] (code: 'invalid_overlap').

SidError

If data is too short for even one segment (code: 'too_few_segments').

Examples:

Time-varying frequency map (Blackman-Tukey):

>>> import numpy as np
>>> import sid
>>> N = 4000; rng = np.random.default_rng(0)
>>> u = rng.standard_normal(N)
>>> from scipy.signal import lfilter
>>> y = lfilter([1], [1, -0.9], u) + 0.1 * rng.standard_normal(N)
>>> result = sid.freq_map(y, u, segment_length=512)

Time-varying spectrum (time-series, Welch):

>>> result = sid.freq_map(y, algorithm='welch', segment_length=256)
Notes

Algorithm (outer segmentation + inner estimator):

  1. Validate and orient data; detect time-series / SISO / MIMO.
  2. Divide the data into K overlapping segments of length L with stride L - P.
  3. For each segment, apply either the Blackman-Tukey or Welch inner estimator.
  4. Stack the per-segment results into 2-D / 4-D arrays indexed by (frequency, segment).

Specification: SPEC.md S6 -- Time-Varying Frequency Response Map

See Also

sid.freq_bt : Blackman-Tukey spectral analysis (inner estimator). sid.map_plot : Surface / image plot of a FreqMapResult. sid.spectrogram : Short-time FFT spectrogram.

Changelog

2026-04-08 : First version (Python port) by Pedro Lourenco.