围绕特定频率的许多细节FFT

时间:2014-03-09 01:53:13

标签: python numpy scipy fft

我有一个任意信号,我需要知道信号的频谱,我通过FFT得到。问题是,我需要在这个特定频率附近只有 的大量分辨率。问题是,如果我增加窗口宽度,或者如果我提高采样率,那就太慢了,我到处都会得到很多细节。我只希望在一个方面有很多细节,在其他地方只需要很少的细节。

我尝试在我需要的区域周围使用Goertzel滤镜,然后在其他地方使用FFT,但这并没有让我得到更多分辨率,我认为这是预期的。

有什么想法吗?我目前唯一的想法是围绕我想要的价值进行扫描和内部产品。

感谢。

1 个答案:

答案 0 :(得分:7)

提高采样率不会为您提供更高的光谱分辨率,它只会为您提供更多您不感兴趣的高频信息。增加光谱分辨率的唯一方法是增加窗口长度。有一种方法可以通过零填充来人为地增加窗口的长度,但这只会给你“假分辨率”,它只会产生正常点之间的平滑曲线。所以唯一的方法是在更长的时间内测量数据,没有免费的午餐。

对于您描述的问题,减少FFT计算时间的标准方法是使用解调。将您的数据乘以频率接近您感兴趣的频率的正弦值(可能是确切的频率,但这不是必需的),然后抽取您的日期(低频滤波,转角频率恰好低于您下来的奈奎斯特频率) - 采样率,然后是采样率)。这样,您的点数就少得多,因此您的FFT速度会更快。得到的频谱与原始频谱相似,但只是按解调频率移动。因此,在制作绘图时,只需将f_demod添加到x轴即可。

有一点需要注意的是,如果你乘以实数正弦,你的下采样频谱实际上将是两个镜像光谱的总和,因为真正的正弦由正负频率组成。这有两个解决方案

  1. 通过相同频率的正弦和余弦进行解调,这样您就可以获得2个光谱,然后取总和或差值就可以得到你的光谱。

  2. 通过乘以exp(2*pi*i*f_demod*t)形式的复数正弦进行解调。 FFT的输入现在很复杂,因此您必须计算双面光谱。但这正是您想要的,您将获得f_demod以下的频率。

  3. 我更喜欢第二种解决方案。快速举例:

    from __future__ import division
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.mlab import psd
    from scipy.signal import decimate
    
    f_line = 123.456
    f_demod = 122
    
    f_sample = 1000
    t_total = 100
    t_win = 10
    ratio = 10
    
    t = np.arange(0, t_total, 1 / f_sample) 
    x = np.sin(2*np.pi*f_line * t) + np.random.randn(len(t)) # sine plus white noise
    lo = 2**.5 * np.exp(-2j*np.pi*f_demod * t) # local oscillator
    y = decimate(x * lo, ratio) # demodulate and decimate to 100 Hz
    z = decimate(y, ratio) # decimate further to 10 Hz
    
    nfft = int(round(f_sample * t_win))
    X, fx = psd(x, NFFT = nfft, noverlap = nfft/2, Fs = f_sample)
    
    nfft = int(round(f_sample * t_win / ratio))
    Y, fy = psd(y, NFFT = nfft, noverlap = nfft/2, Fs = f_sample / ratio)
    
    nfft = int(round(f_sample * t_win / ratio**2))
    Z, fz = psd(z, NFFT = nfft, noverlap = nfft/2, Fs = f_sample / ratio**2)
    
    plt.semilogy(fx, X, fy + f_demod, Y, fz + f_demod, Z)
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('PSD (V^2/Hz)')
    plt.legend(('Full bandwidth FFT', '100 Hz FFT', '10 Hz FFT'))
    plt.show()
    

    结果:

    enter image description here

    如果放大,您会注意到结果在抽取滤波器的通带内几乎相同。需要注意的一点是,如果使用远大于10的抽取率,decimate中使用的低通滤波器将在数值上不稳定。对此的解决方案是在几个通道中对大比率进行抽取,即如果以1000倍的速度进行抽取,则会以10倍的速度进行3次抽取。