【问题标题】:Parseval's Theorem does not hold for FFT of a sinusoid + noise?Parseval 定理不适用于正弦曲线 + 噪声的 FFT?
【发布时间】:2017-10-18 13:35:25
【问题描述】:

在此先感谢您提供有关此主题的任何帮助。我最近一直在尝试计算包含噪声时的离散傅立叶变换的 Parseval 定理。我的代码来自this code

我期望看到的是(当不包括噪声时)频域中的总功率是时域中总功率的一半,因为我已经切断了负频率。

然而,随着更多噪声被添加到时域信号中,信号+噪声的傅立叶变换的总功率变得远小于信号+噪声的总功率的一半。

我的代码如下:

import numpy as np
import numpy.fft as nf
import matplotlib.pyplot as plt

def findingdifference(randomvalues):  

    n               = int(1e7) #number of points
    tmax            = 40e-3 #measurement time
    f1              = 30e6 #beat frequency

    t               = np.linspace(-tmax,tmax,num=n) #define time axis
    dt              = t[1]-t[0] #time spacing

    gt              = np.sin(2*np.pi*f1*t)+randomvalues #make a sin + noise

    fftfreq         = nf.fftfreq(n,dt) #defining frequency (x) axis
    hkk             = nf.fft(gt) # fourier transform of sinusoid + noise
    hkn             = nf.fft(randomvalues) #fourier transform of just noise

    fftfreq         = fftfreq[fftfreq>0] #only taking positive frequencies
    hkk             = hkk[fftfreq>0]
    hkn             = hkn[fftfreq>0]

    timedomain_p    = sum(abs(gt)**2.0)*dt #parseval's theorem for time
    freqdomain_p    = sum(abs(hkk)**2.0)*dt/n # parseval's therom for frequency
    difference      = (timedomain_p-freqdomain_p)/timedomain_p*100 #percentage diff

    tdomain_pn   = sum(abs(randomvalues)**2.0)*dt #parseval's for time
    fdomain_pn   = sum(abs(hkn)**2.0)*dt/n # parseval's for frequency
    difference_n    = (tdomain_pn-fdomain_pn)/tdomain_pn*100 #percent diff

    return difference,difference_n

def definingvalues(max_amp,length):

    noise_amplitude     = np.linspace(0,max_amp,length) #defining noise amplitude
    difference          = np.zeros((2,len(noise_amplitude)))
    randomvals          = np.random.random(int(1e7)) #defining noise

    for i in range(len(noise_amplitude)):
        difference[:,i] = (findingdifference(noise_amplitude[i]*randomvals))

    return noise_amplitude,difference

def figure(max_amp,length):

    noise_amplitude,difference = definingvalues(max_amp,length)

    plt.figure()
    plt.plot(noise_amplitude,difference[0,:],color='red')
    plt.plot(noise_amplitude,difference[1,:],color='blue')
    plt.xlabel('Noise_Variable')
    plt.ylabel(r'Difference in $\%$')
    plt.show()

    return
figure(max_amp=3,length=21)

我的最终图表看起来像这样figure。解决这个问题时我做错了什么吗?这种趋势在增加噪音的情况下出现是否有物理原因?是否与对不完美的正弦信号进行傅立叶变换有关?我这样做的原因是为了了解我有真实数据的非常嘈杂的正弦信号。

【问题讨论】:

    标签: python-2.7 numpy fft


    【解决方案1】:

    如果您使用整个频谱(正 负)频率来计算功率,则 Parseval 定理通常成立。

    差异的原因是 DC (f=0) 分量,它被处理得有些特殊。

    首先,直流分量从何而来?您使用np.random.random 生成介于 0 和 1 之间的随机值。因此,平均而言,您将信号提高 0.5*noise_amplitude,这需要很大的功率。这个功率是在时域中正确计算的。

    但是,在频域中,只有一个 FFT bin 对应于 f=0。所有其他频率的功率分布在两个 bin 中,只有 DC 功率包含在一个 bin 中。

    通过缩放噪声,您可以添加直流电源。通过去除负频率,您可以去除一半的信号功率,但大部分噪声功率位于被充分利用的直流分量中。

    您有多种选择:

    1. 使用所有频率来计算功率。
    2. 使用没有直流分量的噪声:randomvals = np.random.random(int(1e7)) - 0.5
    3. 通过移除一半的直流电源“修复”功率计算:hkk[fftfreq==0] /= np.sqrt(2)

    我会选择选项 1。第二个可能还可以,我不推荐 3。

    最后,代码有个小问题:

    fftfreq         = fftfreq[fftfreq>0] #only taking positive frequencies
    hkk             = hkk[fftfreq>0]
    hkn             = hkn[fftfreq>0]
    

    这真的没有意义。最好改成

    hkk             = hkk[fftfreq>=0]
    hkn             = hkn[fftfreq>=0]
    

    或完全删除选项 1。

    【讨论】:

    • 非常感谢!这现在有效。我尝试了第一个和第二个选项,它们都有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多