[英]How can I plot a spectrogram of a signal by computing the power spectrum on binned windows?
[英]Computing a power spectrum
我想使用Python3计算功率谱。 从有关该主题的另一个主题中,我获得了基本要素。 我认为应该是这样的:
ps = np.abs(np.fft.fft(x))**2
timeres = t[1]-t[0]
freqs = np.fft.fftfreq(x.size, timeres)
idx = np.argsort(freqs)
plt.plot(freqs[idx], ps[idx])
plt.show()
在这里, t
是时间, x
是光子数。 我也尝试过:
W = fftfreq(x.size, timeres=t[1]-t[0])
f_x = rfft(x)
plt.plot(W,f_x)
plt.show()
但两者大多都给我一个零附近的峰值(尽管它们并不相同)。 我正在尝试据此计算功率谱:
这应该给我580Hz左右的信号。 我在这里做错了什么?
@kwinkunks的答案中有一些我觉得缺少的东西:
您提到在零处看到一个大峰值。 正如我在上面的评论中所说,如果您的输入信号的均值非零,那么这是可以预期的。 如果要消除直流分量 ,则应在进行DFT之前对信号进行反趋势处理,例如,减去均值。
尽管采用DFT的平方模可以粗略估计频谱密度,但这对信号中的任何噪声都非常敏感。 一种用于噪声数据的更健壮的方法是计算信号的多个较小段的周期图,然后将其平均化。 为了提高鲁棒性,这需要在频域中进行某种分辨率的折衷。 韦尔奇的方法使用了这一原理。
我个人将使用scipy.signal.welch
,它解决了我上面提到的所有要点:
from scipy.signal import welch
f, psd = welch(x,
fs=1./(t[1]-t[0]), # sample rate
window='hanning', # apply a Hanning window before taking the DFT
nperseg=256, # compute periodograms of 256-long segments of x
detrend='constant') # detrend x by subtracting the mean
对于它的价值,这是我的做法:
from scipy.fftpack import fft, fftfreq
import matplotlib.pyplot as plt
dt = 0.001
X = fft(x)
freq = fftfreq(x.size, d=dt)
# Only keep positive frequencies.
keep = freq>=0
X = X[keep]
freq = freq[keep]
ax1 = plt.subplot(111)
ax1.plot(freq, np.absolute(X)/3000.)
ax1.set_xlim(0,60)
plt.show()
例如,使用此信号...
T = 10
f = 2
f1 = 5
t = np.linspace(0, T, T/dt)
x = 0.4 * np.cos(2*np.pi*f*t) + np.cos(2*np.pi*f1*t)
我得到这个频谱:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.