ShortTimeFFT#
- class scipy.signal.ShortTimeFFT(win, hop, fs, *, fft_mode='onesided', mfft=None, dual_win=None, scale_to=None, phase_shift=0)[source]#
Provide a parametrized discrete Short-time Fourier transform (stft) and its inverse (istft).
The stft calculates sequential FFTs by sliding a window (
win) over an input signal byhopincrements. It can be used to quantify the change of the spectrum over time.The stft is represented by a complex-valued matrix S[q,p] where the p-th column represents an FFT with the window centered at the time t[p] = p *
delta_t= p *hop*TwhereTis the sampling interval of the input signal. The q-th row represents the values at the frequency f[q] = q *delta_fwithdelta_f= 1 / (mfft*T) being the bin width of the FFT.The inverse STFT istft is calculated by reversing the steps of the STFT: Take the IFFT of the p-th slice of S[q,p] and multiply the result with the so-called dual window (see
dual_win). Shift the result by p *delta_tand add the result to previous shifted results to reconstruct the signal. If only the dual window is known and the STFT is invertible,from_dualcan be used to instantiate this class.Due to the convention of time t = 0 being at the first sample of the input signal, the STFT values typically have negative time slots. Hence, negative indexes like
p_minork_mindo not indicate counting backwards from an array’s end like in standard Python indexing but being left of t = 0.More detailed information can be found in the Short-Time Fourier Transform section of the SciPy User Guide.
Note that all parameters of the initializer, except
scale_to(which usesscaling) have identical named attributes.- Parameters:
- winnp.ndarray
The window must be a real- or complex-valued 1d array.
- hopint
The increment in samples, by which the window is shifted in each step.
- fsfloat
Sampling frequency of input signal and window. Its relation to the sampling interval
TisT = 1 / fs.- fft_mode‘twosided’, ‘centered’, ‘onesided’, ‘onesided2X’
Mode of FFT to be used (default ‘onesided’). See property
fft_modefor details.- mfft: int | None
Length of the FFT used, if a zero padded FFT is desired. If
None(default), the length of the windowwinis used.- dual_winnp.ndarray | None
The dual window of
win. If set toNone, it is calculated if needed.- scale_to‘magnitude’, ‘psd’ | None
If not
None(default) the window function is scaled, so each STFT column represents either a ‘magnitude’ or a power spectral density (‘psd’) spectrum. This parameter sets the propertyscalingto the same value. See methodscale_tofor details.- phase_shiftint | None
If set, add a linear phase
phase_shift/mfft*fto each frequencyf. The default value 0 ensures that there is no phase shift on the zeroth slice (in which t=0 is centered). See propertyphase_shiftfor more details.
Examples
The following example shows the magnitude of the STFT of a sine with varying frequency \(f_i(t)\) (marked by a red dashed line in the plot):
>>> import numpy as np >>> import matplotlib.pyplot as plt >>> from scipy.signal import ShortTimeFFT >>> from scipy.signal.windows import gaussian ... >>> T_x, N = 1 / 20, 1000 # 20 Hz sampling rate for 50 s signal >>> t_x = np.arange(N) * T_x # time indexes for signal >>> f_i = 1 * np.arctan((t_x - t_x[N // 2]) / 2) + 5 # varying frequency >>> x = np.sin(2*np.pi*np.cumsum(f_i)*T_x) # the signal
The utilized Gaussian window is 50 samples or 2.5 s long. The parameter
mfft=200in ShortTimeFFT causes the spectrum to be oversampled by a factor of 4:>>> g_std = 8 # standard deviation for Gaussian window in samples >>> w = gaussian(50, std=g_std, sym=True) # symmetric Gaussian window >>> SFT = ShortTimeFFT(w, hop=10, fs=1/T_x, mfft=200, scale_to='magnitude') >>> Sx = SFT.stft(x) # perform the STFT
In the plot, the time extent of the signal x is marked by vertical dashed lines. Note that the SFT produces values outside the time range of x. The shaded areas on the left and the right indicate border effects caused by the window slices in that area not fully being inside time range of x:
>>> fig1, ax1 = plt.subplots(figsize=(6., 4.)) # enlarge plot a bit >>> t_lo, t_hi = SFT.extent(N)[:2] # time range of plot >>> ax1.set_title(rf"STFT ({SFT.m_num*SFT.T:g}$\,s$ Gaussian window, " + ... rf"$\sigma_t={g_std*SFT.T}\,$s)") >>> ax1.set(xlabel=f"Time $t$ in seconds ({SFT.p_num(N)} slices, " + ... rf"$\Delta t = {SFT.delta_t:g}\,$s)", ... ylabel=f"Freq. $f$ in Hz ({SFT.f_pts} bins, " + ... rf"$\Delta f = {SFT.delta_f:g}\,$Hz)", ... xlim=(t_lo, t_hi)) ... >>> im1 = ax1.imshow(abs(Sx), origin='lower', aspect='auto', ... extent=SFT.extent(N), cmap='viridis') >>> ax1.plot(t_x, f_i, 'r--', alpha=.5, label='$f_i(t)$') >>> fig1.colorbar(im1, label="Magnitude $|S_x(t, f)|$") ... >>> # Shade areas where window slices stick out to the side: >>> for t0_, t1_ in [(t_lo, SFT.lower_border_end[0] * SFT.T), ... (SFT.upper_border_begin(N)[0] * SFT.T, t_hi)]: ... ax1.axvspan(t0_, t1_, color='w', linewidth=0, alpha=.2) >>> for t_ in [0, N * SFT.T]: # mark signal borders with vertical line: ... ax1.axvline(t_, color='y', linestyle='--', alpha=0.5) >>> ax1.legend() >>> fig1.tight_layout() >>> plt.show()
Reconstructing the signal with the istft is straightforward, but note that the length of x1 should be specified, since the SFT length increases in
hopsteps:>>> SFT.invertible # check if invertible True >>> x1 = SFT.istft(Sx, k1=N) >>> np.allclose(x, x1) True
It is possible to calculate the SFT of signal parts:
>>> p_q = SFT.nearest_k_p(N // 2) >>> Sx0 = SFT.stft(x[:p_q]) >>> Sx1 = SFT.stft(x[p_q:])
When assembling sequential STFT parts together, the overlap needs to be considered:
>>> p0_ub = SFT.upper_border_begin(p_q)[1] - SFT.p_min >>> p1_le = SFT.lower_border_end[1] - SFT.p_min >>> Sx01 = np.hstack((Sx0[:, :p0_ub], ... Sx0[:, p0_ub:] + Sx1[:, :p1_le], ... Sx1[:, p1_le:])) >>> np.allclose(Sx01, Sx) # Compare with SFT of complete signal True
It is also possible to calculate the itsft for signal parts:
>>> y_p = SFT.istft(Sx, N//3, N//2) >>> np.allclose(y_p, x[N//3:N//2]) True
- Attributes:
TSampling interval of input signal and of the window.
delta_fWidth of the frequency bins of the STFT.
delta_tTime increment of STFT.
dual_winCanonical dual window.
fFrequencies values of the STFT.
f_ptsNumber of points along the frequency axis.
fac_magnitudeFactor to multiply the STFT values by to scale each frequency slice to a magnitude spectrum.
fac_psdFactor to multiply the STFT values by to scale each frequency slice to a power spectral density (PSD).
fft_modeMode of utilized FFT (‘twosided’, ‘centered’, ‘onesided’ or ‘onesided2X’).
fsSampling frequency of input signal and of the window.
hopTime increment in signal samples for sliding window.
invertibleCheck if STFT is invertible.
k_minThe smallest possible signal index of the STFT.
lower_border_endFirst signal index and first slice index unaffected by pre-padding.
m_numNumber of samples in window
win.m_num_midCenter index of window
win.mfftLength of input for the FFT used - may be larger than window length
m_num.onesided_fftReturn True if a one-sided FFT is used.
p_minThe smallest possible slice index.
phase_shiftIf set, add linear phase
phase_shift/mfft*fto each FFT slice of frequencyf.scalingNormalization applied to the window function (‘magnitude’, ‘psd’ or
None).winWindow function as real- or complex-valued 1d array.
Methods
extent(n[, axes_seq, center_bins])Return minimum and maximum values time-frequency values.
from_dual(dual_win, hop, fs, *[, fft_mode, ...])Instantiate a ShortTimeFFT by only providing a dual window.
from_window(win_param, fs, nperseg, noverlap, *)Instantiate ShortTimeFFT by using get_window.
istft(S[, k0, k1, f_axis, t_axis])Inverse short-time Fourier transform.
k_max(n)First sample index after signal end not touched by a time slice.
nearest_k_p(k[, left])Return nearest sample index k_p for which t[k_p] == t[p] holds.
p_max(n)Index of first non-overlapping upper time slice for n sample input.
p_num(n)Number of time slices for an input signal with n samples.
p_range(n[, p0, p1])Determine and validate slice index range.
scale_to(scaling)Scale window to obtain 'magnitude' or 'psd' scaling for the STFT.
spectrogram(x[, y, detr, p0, p1, k_offset, ...])Calculate spectrogram or cross-spectrogram.
stft(x[, p0, p1, k_offset, padding, axis])Perform the short-time Fourier transform.
stft_detrend(x, detr[, p0, p1, k_offset, ...])Short-time Fourier transform with a trend being subtracted from each segment beforehand.
t(n[, p0, p1, k_offset])Times of STFT for an input signal with n samples.
First signal index and first slice index affected by post-padding.