freq_etfe¶
MATLAB equivalent:
sidFreqETFE
freq_etfe ¶
Empirical Transfer Function Estimate (ETFE) for frequency response estimation.
freq_etfe ¶
freq_etfe(y: ndarray | list, u: ndarray | list | None = None, *, smoothing: int = 1, frequencies: ndarray | None = None, sample_time: float = 1.0) -> FreqResult
Estimate the frequency response via the Empirical Transfer Function Estimate.
Computes the frequency response as the ratio of the output and input discrete Fourier transforms. Provides maximum frequency resolution but high variance. Optional smoothing reduces variance at the cost of resolution.
This is an open-source replacement for the System Identification
Toolbox function etfe.
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 |
required |
u
|
ndarray, list of ndarray, or None
|
Input data. Same shape conventions as y. Pass |
None
|
smoothing
|
int
|
Smoothing window length S. Must be a positive integer; when
S > 1 it must be odd. A length-S boxcar (moving average)
filter is applied to the raw ETFE. Default is |
1
|
frequencies
|
(ndarray, shape(nf))
|
Frequency vector in rad/sample. All values must lie in the
interval |
None
|
sample_time
|
float
|
Sample time in seconds. Must be positive. Default is |
1.0
|
Returns:
| Type | Description |
|---|---|
FreqResult
|
Frozen dataclass with fields:
|
Raises:
| Type | Description |
|---|---|
SidError
|
If sample_time is not positive (code: |
SidError
|
If smoothing is not a positive integer, or is even and > 1
(code: |
SidError
|
If any frequency is outside |
SidError
|
If data contains NaN/Inf (code: |
Examples:
Basic SISO system identification:
>>> import numpy as np
>>> import sid
>>> N = 1000; 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_etfe(y, u, smoothing=5)
>>> result.response.shape
(128,)
Time-series periodogram:
>>> y = rng.standard_normal(500)
>>> result = sid.freq_etfe(y)
>>> result.noise_spectrum.shape
(128,)
Custom frequencies:
Multi-trajectory (ensemble-averaged):
>>> L = 5; N = 1000
>>> u3d = rng.standard_normal((N, 1, L))
>>> y3d = np.zeros_like(u3d)
>>> for l in range(L):
... y3d[:, 0, l] = lfilter([1], [1, -0.9], u3d[:, 0, l]) + 0.1 * rng.standard_normal(N)
>>> result = sid.freq_etfe(y3d, u3d)
Notes
Algorithm:
- Validate and orient input data; detect time-series vs. SISO vs. MIMO.
- Compute discrete Fourier transforms Y(w) and U(w) of the data.
- Form the raw ETFE: G(w) = Y(w) / U(w) (SISO) or G(w) = Phi_yu(w) * Phi_u(w)^{-1} (MIMO), using the H1 estimator for multi-trajectory data.
- Optionally smooth G with a length-S boxcar (moving average) window.
- Noise spectrum: Phi_v(w) = (1/N) * |Y(w) - G(w) * U(w)|^2. Time-series mode: periodogram Phi_y(w) = (1/N) * |Y(w)|^2.
- ETFE has no closed-form asymptotic variance; standard deviations are returned as NaN arrays.
Specification: SPEC.md S4 -- Empirical Transfer Function Estimate
References
.. [1] Ljung, L., "System Identification: Theory for the User", 2nd ed., Prentice Hall, 1999. Sections 2.3, 6.3.
See Also
sid.freq_bt : Blackman-Tukey spectral analysis (lower variance). sid.freq_btfdr : Blackman-Tukey with frequency-dependent resolution. sid.bode_plot : Bode magnitude/phase plot of a FreqResult. sid.spectrum_plot : Plot the noise/output spectrum of a FreqResult.
Changelog
2026-04-08 : First version (Python port) by Pedro Lourenco.