scipy.fft.fft 输出行为与 T/f_signal 比率
scipy.fft.fft output behaviour vs T/f_signal ratio
我在探索 scipy.fft.fft
的输出时观察到一个我无法解释的行为
首先描述我在做什么,然后是代码和结果。
我正在设置 10 秒的观察 window,将其分成 N = 1600 个瞬间,因此采样可变频率的正弦波,采样时间 T_s = 10/1600 = 6.25女士
然后我通过scipy.fft
模块提供的函数计算FFT。我按照惯例将结果归一化为样本数 N
,以获得正弦曲线的幅度。
但是,我发现 FFT 输出的最大幅度取决于我输入 scipy.fft.fft
的正弦波的频率。根据我的理解,这不应该是这种情况,因为我正在转换的正弦曲线都是等幅的。
我发现这个效果与 sinc(\pi*t/T) 函数有关,所以我可以根据需要进行更正,但是我不明白 为什么 这正在发生。请注意:
我不认为这是频谱泄漏,因为这会表现为围绕基波的能量而不是渐进缩放。此外,我为正弦曲线选择的频率使得所有信号都符合观察范围内的整数个周期 window,因此我预计不会出现任何截断效应。
代码如下:
import matplotlib.pyplot as plt
import numpy as np
from scipy.fft import fft, ifft
get_ipython().run_line_magic('matplotlib', 'qt')
N = 1600 # FFT n. of points
T = 10 # observation window
Ts = T/N # sampling time
print('Sampling time: {}ms, Nyquist freq: {} Hz'.format(Ts*1e3,1/(2*Ts)))
t = np.linspace(0.0,T,N) # time vector, N points over (0,T)
plt.figure()
for f in np.linspace(5,80,16,dtype=int)[:-1]:
y = np.sin(2*np.pi*f*t)
yf = fft(y)
plt.plot(np.abs(yf)/N)
结果是这样的:
可以注意到,只有接近直流的频率才有正确的 0.5 振幅(因为必须将正负频率相加才能得到完整的振幅,这没关系)。
随着频率上升,但仍在奈奎斯特极限内(示例中为 80Hz)并且对于 f_s = 1/T = 0.1 Hz 的频率整数倍,似乎有一个我无法解释的比例因子,来自理论。
注意 scipy.fft
documentation 示例中也报告了这一点,但似乎并没有打扰他们,所以我认为这是一个已知的效果?
那里,信号如下:
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
据报道具有以下光谱:
其 bin 振幅似乎与时域中的信号不一致(组成它的两个正弦波的振幅为 1 和 0.5,而 FFT returns 第一个为 0.7,第二个为 0.5第二个)。
我根据经验发现 'scaling function' 是一个 sinc(\pi*t/T),就好像原始时域信号是 convolved 一样脉冲功能。然而,这从理论上讲是没有意义的,因为时域信号是乘以一个时间window,而不是卷积,这就是光谱泄漏现象。然而,如前所述,在这种情况下,这种效果不应该是可见的,因为信号在观察中都重复了整数次 window (T)
使用以下代码更正的图:
win_seed = np.append([1],np.sin(np.pi*t[1:int(N/2)]/T)/(np.pi*t[1:int(N/2)]/T))
win_correct = np.append(win_seed,win_seed[-1::-1])
plt.figure()
for f in np.linspace(5,80,16,dtype=int)[:-1]:
y = np.sin(2*np.pi*f*t)
yf = fft(y)
plt.plot(np.abs(yf)/N/win_correct)
为 scipy.fft
:
给出恒定幅度
感谢您的见解!
问题出在以下行:
t = np.linspace(0,T,N)
默认情况下,np.linspace
包含端点,因此您获得的采样率与所需的 1/T
采样间隔略有不同。相应地,在频域中使用 fft
获得的频谱中的采样点仅略微偏离实际峰值,随着正弦波频率接近奈奎斯特速率,偏移量变得更加明显。
要使用 np.linspace
获得所需的 1/T
采样间隔,您应该通过将行更改为:
来删除端点
t = np.linspace(0,T,N,endpoint=False)
具有以下频谱(无同步补偿):
请注意,在上图中您没有看到预期的光谱泄漏效应。这是因为 FFT 的默认点数使得频谱恰好在峰裙的零交叉处被采样。我怀疑这可能是为什么 scipy.fft
's documentation 你已经看到(试图解释频谱泄漏效应)故意选择稍微偏离的频率的原因。然而,查看这种泄漏的另一种方法是简单地增加 FFT 点的数量一些小的因素(例如 4):
yf = fft(y,4*len(y))
使用以下结果频谱(显示预期的峰值幅度 和 频谱泄漏效应):
我在探索 scipy.fft.fft
首先描述我在做什么,然后是代码和结果。
我正在设置 10 秒的观察 window,将其分成 N = 1600 个瞬间,因此采样可变频率的正弦波,采样时间 T_s = 10/1600 = 6.25女士
然后我通过scipy.fft
模块提供的函数计算FFT。我按照惯例将结果归一化为样本数 N
,以获得正弦曲线的幅度。
但是,我发现 FFT 输出的最大幅度取决于我输入 scipy.fft.fft
的正弦波的频率。根据我的理解,这不应该是这种情况,因为我正在转换的正弦曲线都是等幅的。
我发现这个效果与 sinc(\pi*t/T) 函数有关,所以我可以根据需要进行更正,但是我不明白 为什么 这正在发生。请注意:
我不认为这是频谱泄漏,因为这会表现为围绕基波的能量而不是渐进缩放。此外,我为正弦曲线选择的频率使得所有信号都符合观察范围内的整数个周期 window,因此我预计不会出现任何截断效应。
代码如下:
import matplotlib.pyplot as plt
import numpy as np
from scipy.fft import fft, ifft
get_ipython().run_line_magic('matplotlib', 'qt')
N = 1600 # FFT n. of points
T = 10 # observation window
Ts = T/N # sampling time
print('Sampling time: {}ms, Nyquist freq: {} Hz'.format(Ts*1e3,1/(2*Ts)))
t = np.linspace(0.0,T,N) # time vector, N points over (0,T)
plt.figure()
for f in np.linspace(5,80,16,dtype=int)[:-1]:
y = np.sin(2*np.pi*f*t)
yf = fft(y)
plt.plot(np.abs(yf)/N)
结果是这样的:
可以注意到,只有接近直流的频率才有正确的 0.5 振幅(因为必须将正负频率相加才能得到完整的振幅,这没关系)。 随着频率上升,但仍在奈奎斯特极限内(示例中为 80Hz)并且对于 f_s = 1/T = 0.1 Hz 的频率整数倍,似乎有一个我无法解释的比例因子,来自理论。
注意 scipy.fft
documentation 示例中也报告了这一点,但似乎并没有打扰他们,所以我认为这是一个已知的效果?
那里,信号如下:
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
据报道具有以下光谱:
其 bin 振幅似乎与时域中的信号不一致(组成它的两个正弦波的振幅为 1 和 0.5,而 FFT returns 第一个为 0.7,第二个为 0.5第二个)。
我根据经验发现 'scaling function' 是一个 sinc(\pi*t/T),就好像原始时域信号是 convolved 一样脉冲功能。然而,这从理论上讲是没有意义的,因为时域信号是乘以一个时间window,而不是卷积,这就是光谱泄漏现象。然而,如前所述,在这种情况下,这种效果不应该是可见的,因为信号在观察中都重复了整数次 window (T)
使用以下代码更正的图:
win_seed = np.append([1],np.sin(np.pi*t[1:int(N/2)]/T)/(np.pi*t[1:int(N/2)]/T))
win_correct = np.append(win_seed,win_seed[-1::-1])
plt.figure()
for f in np.linspace(5,80,16,dtype=int)[:-1]:
y = np.sin(2*np.pi*f*t)
yf = fft(y)
plt.plot(np.abs(yf)/N/win_correct)
为 scipy.fft
:
感谢您的见解!
问题出在以下行:
t = np.linspace(0,T,N)
默认情况下,np.linspace
包含端点,因此您获得的采样率与所需的 1/T
采样间隔略有不同。相应地,在频域中使用 fft
获得的频谱中的采样点仅略微偏离实际峰值,随着正弦波频率接近奈奎斯特速率,偏移量变得更加明显。
要使用 np.linspace
获得所需的 1/T
采样间隔,您应该通过将行更改为:
t = np.linspace(0,T,N,endpoint=False)
具有以下频谱(无同步补偿):
请注意,在上图中您没有看到预期的光谱泄漏效应。这是因为 FFT 的默认点数使得频谱恰好在峰裙的零交叉处被采样。我怀疑这可能是为什么 scipy.fft
's documentation 你已经看到(试图解释频谱泄漏效应)故意选择稍微偏离的频率的原因。然而,查看这种泄漏的另一种方法是简单地增加 FFT 点的数量一些小的因素(例如 4):
yf = fft(y,4*len(y))
使用以下结果频谱(显示预期的峰值幅度 和 频谱泄漏效应):