ShortTimeFFT#
- class scipy.signal.ShortTimeFFT(win, hop, fs, *, fft_mode='onesided', mfft=None, dual_win=None, scale_to=None, phase_shift=0)[source]#
提供参数化的离散短时傅里叶变换(stft)及其逆变换(istft)。
stft 通过在输入信号上以
hop
增量滑动窗口 (win
) 来计算连续的 FFT。它可用于量化频谱随时间的变化。stft 由复值矩阵 S[q,p] 表示,其中第 p 列表示以时间 t[p] = p *
delta_t
= p *hop
*T
为中心的 FFT,其中T
是输入信号的采样间隔。第 q 行表示频率 f[q] = q *delta_f
处的值,其中delta_f
= 1 / (mfft
*T
) 是 FFT 的箱宽。逆 STFT istft 通过反转 STFT 的步骤来计算:取 S[q,p] 的第 p 片的 IFFT,并将结果乘以所谓的双窗 (见
dual_win
)。将结果移位 p *delta_t
,并将结果添加到以前移位的结果以重建信号。如果只知道双窗,并且 STFT 是可逆的,则可以使用from_dual
来实例化此类。由于时间 t = 0 在输入信号的第一个样本处,因此 STFT 值通常具有负时间槽。因此,像
p_min
或k_min
这样的负索引并不像标准 Python 索引那样表示从数组结尾反向计数,而是表示 t = 0 的左侧。更详细的信息可以在 短时傅里叶变换 部分的 SciPy 用户指南 中找到。
请注意,初始化程序的所有参数,除了
scale_to
(它使用scaling
),都具有相同的命名属性。- 参数:
- winnp.ndarray
窗口必须是实值或复值一维数组。
- hopint
窗口在每一步中移动的样本增量。
- fsfloat
输入信号和窗口的采样频率。它与采样间隔
T
的关系是T = 1 / fs
。- fft_mode‘twosided’, ‘centered’, ‘onesided’, ‘onesided2X’
要使用的 FFT 模式 (默认值为 'onesided')。有关详细信息,请参阅属性
fft_mode
。- mfft: int | None
如果需要零填充 FFT,则使用 FFT 的长度。如果为
None
(默认值),则使用窗口win
的长度。- dual_winnp.ndarray | None
win
的双窗。如果设置为None
,则在需要时计算。- scale_to‘magnitude’, ‘psd’ | None
如果不是
None
(默认值),则对窗函数进行缩放,以便每个 STFT 列表示幅度谱 ('magnitude') 或功率谱密度 ('psd') 谱。此参数将属性scaling
设置为相同的值。有关详细信息,请参阅方法scale_to
。- phase_shiftint | None
如果设置,则为每个频率
f
添加线性相位phase_shift
/mfft
*f
。默认值 0 确保在第零片(其中 t=0 居中)上没有相位移。有关更多详细信息,请参阅属性phase_shift
。
示例
以下示例显示了具有变化频率 \(f_i(t)\) (在图中用红色虚线标记) 的正弦曲线的 STFT 幅度。
>>> 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
使用的 Gaussian 窗口为 50 个样本或 2.5 秒长。参数
mfft=200
在 ShortTimeFFT 中导致频谱被超采样 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
在图中,信号 x 的时间范围由垂直虚线标记。请注意,SFT 会产生超出 x 时间范围的值。左侧和右侧的阴影区域表示由该区域中的窗口片未完全包含在 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()
使用 istft 重建信号非常简单,但请注意,应指定 x1 的长度,因为 SFT 长度会以
hop
步长增加。>>> SFT.invertible # check if invertible True >>> x1 = SFT.istft(Sx, k1=N) >>> np.allclose(x, x1) True
可以计算信号部分的 SFT。
>>> p_q = SFT.nearest_k_p(N // 2) >>> Sx0 = SFT.stft(x[:p_q]) >>> Sx1 = SFT.stft(x[p_q:])
将连续的 STFT 部分组合在一起时,需要考虑重叠。
>>> 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
还可以计算信号部分的 itsft。
>>> y_p = SFT.istft(Sx, N//3, N//2) >>> np.allclose(y_p, x[N//3:N//2]) True
- 属性:
T
输入信号和窗口的采样间隔。
delta_f
STFT 频率箱的宽度。
delta_t
STFT 的时间增量。
dual_win
规范对偶窗口。
f
STFT 的频率值。
f_pts
频率轴上的点数。
fac_magnitude
将 STFT 值乘以该因子以将每个频率切片缩放为幅度谱。
fac_psd
将 STFT 值乘以该因子以将每个频率切片缩放为功率谱密度 (PSD)。
fft_mode
所用 FFT 的模式('twosided'、'centered'、'onesided' 或 'onesided2X')。
fs
输入信号和窗口的采样频率。
hop
滑动窗口的信号样本时间增量。
invertible
检查 STFT 是否可逆。
k_min
STFT 的最小可能信号索引。
lower_border_end
不受预填充影响的第一个信号索引和第一个切片索引。
m_num
窗口
win
中的样本数。m_num_mid
窗口
win
的中心索引。mfft
所用 FFT 的输入长度 - 可能大于窗口长度
m_num
。onesided_fft
如果使用单边 FFT,则返回 True。
p_min
最小可能的切片索引。
phase_shift
如果设置,则将线性相位
phase_shift
/mfft
*f
添加到每个频率为f
的 FFT 切片。scaling
应用于窗口函数的归一化('magnitude'、'psd' 或
None
)。win
窗口函数作为实值或复值一维数组。
方法
extent
(n[, axes_seq, center_bins])返回最小值和最大值时间频率值。
from_dual
(dual_win, hop, fs, *[, fft_mode, ...])仅提供对偶窗口来实例化 ShortTimeFFT。
from_window
(win_param, fs, nperseg, noverlap, *)使用 get_window 来实例化 ShortTimeFFT。
istft
(S[, k0, k1, f_axis, t_axis])逆短时傅里叶变换。
k_max
(n)信号结束后的第一个样本索引,没有被时间切片触及。
nearest_k_p
(k[, left])返回最接近的样本索引 k_p,其中 t[k_p] == t[p] 成立。
p_max
(n)对于 n 个样本输入,第一个非重叠上部时间切片的索引。
p_num
(n)具有 n 个样本的输入信号的时间切片数。
p_range
(n[, p0, p1])确定和验证切片索引范围。
scale_to
(scaling)缩放窗口以获得 STFT 的 'magnitude' 或 'psd' 缩放。
spectrogram
(x[, y, detr, p0, p1, k_offset, ...])计算频谱图或交叉频谱图。
stft
(x[, p0, p1, k_offset, padding, axis])执行短时傅里叶变换。
stft_detrend
(x, detr[, p0, p1, k_offset, ...])短时傅里叶变换,事先从每个段中减去趋势。
t
(n[, p0, p1, k_offset])具有 n 个样本的输入信号的 STFT 时间。
受后填充影响的第一个信号索引和第一个切片索引。