Python Lomb Scargle vs FFT功率谱:具有均匀间隔数据的崩溃

Python Lomb Scargle vs FFT功率谱:具有均匀间隔数据的崩溃,python,numpy,scipy,signal-processing,Python,Numpy,Scipy,Signal Processing,我尝试创建一些例程,使用Lomb Scargle周期图(LSP)和FFT功率谱计算均匀和不均匀采样数据的功率谱。我遇到的问题是,在scipy中使用LSP实现时,我遇到了均匀采样数据的崩溃 据我所知,下面的代码可以工作,并产生几乎相同(和正确)的输出。然而,我被迫在Lomb Scargle函数中插入一个乱码,以增加频率抖动,因此它们与FFT不完全匹配。当我注释掉那一行时,我得到一个被零除的错误 这是scipy中Lomb Scargle实现的一个问题,还是我不应该将其用于均匀采样的数据??提前谢谢

我尝试创建一些例程,使用Lomb Scargle周期图(LSP)和FFT功率谱计算均匀和不均匀采样数据的功率谱。我遇到的问题是,在scipy中使用LSP实现时,我遇到了均匀采样数据的崩溃

据我所知,下面的代码可以工作,并产生几乎相同(和正确)的输出。然而,我被迫在Lomb Scargle函数中插入一个乱码,以增加频率抖动,因此它们与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()

这是一个好消息。代码包含一个arctan计算,实现为
atan(2*cs/(cc-ss))
,其中
cc
ss
取决于
x
freqs
的元素。对于某些输入,
cc-ss
可以为0。scipy 0.15.0中包含了使用atan2(2*cs,cc-ss)的固定代码。

不知道该方法,您的代码在您指定的频率为5时产生良好的脉冲。也许可以详细说明您的问题?问题是在Lomb scargle实现中,我必须随机扰动输入时间戳,以防止函数因被零除错误而崩溃。我会让这里的评论对未来的读者更为明显。那么我的猜测是,既然它是针对不均匀的采样率而做的,那么如果采样率恰好是均匀的,那么它就会崩溃,因为它会随着采样率的变化而变化。如果是这样的话,你的回溯应该会给出提示