的参数的定义scale
表明scipy.signal.welch
适当的缩放由函数执行:
scaling : { 'density', 'spectrum' }, optional 在计算 Pxx 单位为 V^2/Hz 的功率谱密度('密度')和计算Pxx 单位为V^2,如果 x 以 V 为单位,fs 以 Hz 为单位。默认为“密度”</p>
将提供正确的采样频率作为参数fs
以检索正确的频率和准确的功率谱密度。为了恢复类似于使用 计算的功率谱,np.multiply(u_fft, np.conj(u_fft))
必须分别提供 fft 帧的长度和应用的窗口作为帧的长度和boxcar
(相当于根本没有窗口)。scipy.signal.welch
可以通过测试正弦波来检查应用正确缩放的事实:
import numpy as np
import scipy.signal
import matplotlib.pyplot as plt
def abs2(x):
return x.real**2 + x.imag**2
if __name__ == '__main__':
framelength=1.0
N=1000
x=np.linspace(0,framelength,N,endpoint=False)
y=np.sin(44*2*np.pi*x)
#y=y-np.mean(y)
ffty=np.fft.fft(y)
#power spectrum, after real2complex transfrom (factor )
scale=2.0/(len(y)*len(y))
power=scale*abs2(ffty)
freq=np.fft.fftfreq(len(y) , framelength/len(y) )
# power spectrum, via scipy welch. 'boxcar' means no window, nperseg=len(y) so that fft computed on the whole signal.
freq2,power2=scipy.signal.welch(y, fs=len(y)/framelength,window='boxcar',nperseg=len(y),scaling='spectrum', axis=-1, average='mean')
for i in range(len(freq2)):
print i, freq2[i], power2[i], freq[i], power[i]
print np.sum(power2)
plt.figure()
plt.plot(freq[0:len(y)/2+1],power[0:len(y)/2+1],label='np.fft.fft()')
plt.plot(freq2,power2,label='scipy.signal.welch()')
plt.legend()
plt.xlim(0,np.max(freq[0:len(y)/2+1]))
plt.show()
对于实数到复数的变换,正确的缩放比例np.multiply(u_fft, np.conj(u_fft))
是 2./(u.size*u.size)。确实,缩放比例u_fft
是 1./u.size。此外,实数到复数的变换只报告一半的频率,因为 bin Nk 的幅度将是 bin k 的幅度的复共轭。因此,该 bin 的能量等于 bin k 的能量,并将与 bin k 的能量相加。因此因子 2。对于幅度为 1 的测试正弦波信号,能量报告为 0.5:它确实是幅度为 1 的平方正弦波的平均值。
如果帧的长度不是信号周期的倍数或信号不是周期性的,则加窗很有用。如果信号由阻尼波组成,则使用较小的 fft 帧很有用:信号可以被视为在特征时间上是周期性的:选择小于该特征时间但大于波周期的 fft 帧似乎是明智的。