python 中光谱的多锥度光谱分析

Multi-taper Spectral Analysis with spectrum in python

我在 python (https://pyspectrum.readthedocs.io/en/latest/install.html) 上使用频谱库进行多锥度分析,但我无法完全理解输出的幅度。

这里用一段代码来说明:

from spectrum import *
N=500
dt=2*10**-3
# Creating a signal with 2 sinus waves.
x = np.linspace(0.0, N*dt, N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)

# classical FFT
yf = fft.fft(y)
xf = np.linspace(0.0, 1.0/(2.0*dt), N//2)

# The multitapered method
NW=2.5
k=4
[tapers, eigen] = dpss(N, NW, k)
Sk_complex, weights, eigenvalues=pmtm(y, e=eigen, v=tapers, NFFT=500, show=False)

Sk = abs(Sk_complex)
Sk = np.mean(Sk * np.transpose(weights), axis=0)

# ploting both the results
plt.plot(xf,abs(yf[0:N//2])*dt*2)

plt.plot(xf,Sk[0:N//2])

两个结果相似,发现频率峰值在 50 和 80 Hz。 经典 FFT 也发现了良好的振幅(1 和 0.5) 但是多锥度法找不到合适的振幅。在这个例子中,它是 important 的 5 倍左右。 有谁知道如何正确显示结果? 谢谢

据我了解,这里有几个因素在起作用。

首先,要获得功率谱密度的多锥估计,您应该这样计算:

Sk = abs(Sk_complex)**2
Sk = np.mean(Sk * np.transpose(weights), axis=0) * dt

也就是说,您需要平均功率谱,而不是傅里叶分量。

其次,要获得功率谱,您只需要使用 fft 将能谱除以您估计的 N,然后像您一样乘以 dt(并且您需要 **2 从傅立叶中获得功率组件):

plt.plot(xf,abs(yf[0:N//2])**2 / N * dt)
plt.plot(xf,Sk[0:N//2])

最后,应该直接比较的,与其说是功率谱密度中的幅值,不如说是总功率。你可以看看:

print(np.sum(abs(yf[0:N//2])**2/N * dt), np.sum(Sk[0:N//2]))

非常匹配。

所以你的整个代码变成:

from spectrum import *
N=500
dt=2*10**-3
# Creating a signal with 2 sinus waves.
x = np.linspace(0.0, N*dt, N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)

# classical FFT
yf = fft.fft(y)
xf = np.linspace(0.0, 1.0/(2.0*dt), N//2)

# The multitapered method
NW=2.5
k=4
[tapers, eigen] = dpss(N, NW, k)
Sk_complex, weights, eigenvalues=pmtm(y, e=eigen, v=tapers, NFFT=N, show=False)

Sk = abs(Sk_complex)**2
Sk = np.mean(Sk * np.transpose(weights), axis=0) * dt

# ploting both results
plt.figure()
plt.plot(xf,abs(yf[0:N//2])**2 / N * dt)
plt.plot(xf,Sk[0:N//2])

# ploting both results in log scale
plt.semilogy(xf, abs(yf[0:N // 2]) ** 2 / N * dt)
plt.semilogy(xf, Sk[0:N // 2])

# comparing total power
print(np.sum(abs(yf[0:N//2])**2 / N * dt), np.sum(Sk[0:N//2]))