我正在尝试创建一些例程来计算均匀和不均匀采样数据的功率谱,使用 Lomb-Scargle 周期图 (LSP) 和 FFT 功率谱。我遇到的问题是,在 scipy 中使用 LSP 实现时,我遇到了均匀采样数据的崩溃。
据我所知,下面的代码有效,并产生几乎相同(且正确)的输出。然而,我被迫在 Lomb-Scargle 函数中插入一个 kludge 来为频率添加抖动,因此它们与 FFT 的不完全匹配。当我注释掉那行时,我得到一个被零除的错误。
这是 scipy 中 Lomb-Scargle 实现的问题,还是我根本不应该将它用于均匀采样的数据?提前致谢。
import numpy as np
import scipy.signal as sp
import matplotlib.pyplot as plt
def one_sided_fft(t,x):
full_amplitude_spectrum = np.abs(np.fft.fft(x))/x.size
full_freqs = np.fft.fftfreq(x.size, np.mean(np.ediff1d(t)))
oneinds = np.where(full_freqs >=0.0)
one_sided_freqs = full_freqs[oneinds]
one_sided_amplitude_spectrum=2*full_amplitude_spectrum[oneinds]
return one_sided_freqs, one_sided_amplitude_spectrum
def power_spectrum(t,x):
onef, oneamps = one_sided_fft(t,x)
return onef, oneamps**2
def lomb_scargle_pspec(t, x):
tstep = np.mean(np.ediff1d(t))
freqs = np.fft.fftfreq(x.size, tstep)
idxx = np.argsort(freqs)
one_sided_freqs = freqs[idxx]
one_sided_freqs = one_sided_freqs[one_sided_freqs>0]
#KLUDGE TO KEEP PERIODOGRAM FROM CRASHING
one_sided_freqs = one_sided_freqs+0.00001*np.random.random(one_sided_freqs.size)
#THE FOLLOWING LINE CRASHES WITHOUT THE KLUDGE
pgram = sp.lombscargle(t, x, one_sided_freqs*2*np.pi)
return one_sided_freqs, (pgram/(t.size/4))
if __name__ == "__main__":
#Sample data
fs = 100.0
fund_freq=5
ampl = 0.4
t = np.arange(0,10,1/fs)
x = ampl*np.cos(2*np.pi*fund_freq*t)
#power spectrum calculations
powerf, powerspec = power_spectrum(t,x)
lsf, lspspec = lomb_scargle_pspec(t,x)
#plotting
fig, (ax0, ax1, ax2)= plt.subplots(nrows=3)
fig.tight_layout()
ax0.plot(t, x)
ax0.set_title('Input Data, '+str(fund_freq)+' Hz, '+
'Amplitude: '+str(ampl)+
' Fs = '+str(fs)+' Hz')
ax0.set_ylabel('Volts')
ax0.set_xlabel('Time[s]')
ax1.plot(powerf, powerspec)
ax1.set_title('FFT-based Power Spectrum')
ax1.set_ylabel('Volts**2')
ax1.set_xlabel('Freq[Hz]')
ax2.plot(lsf, lspspec)
ax2.set_title('Lomb-Scargle Power Spectrum')
ax2.set_ylabel('Volts**2')
ax2.set_xlabel('Freq[Hz]')
plt.show()
最佳答案
这是一个 bug in lombscargle
。该代码包含实现为 atan(2 * cs / (cc - ss))
的反正切计算,其中 cc
和 ss
取决于 x
和 freqs
的元素。对于某些输入,cc - ss
可以为 0。使用 atan2(2 * cs, cc - ss)
的固定代码包含在 scipy 0.15.0 中。
关于python - Lomb-Scargle 与 FFT 功率谱 : crashes with evenly spaced data,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24702807/