Parseval 定理不适用于正弦曲线 + 噪声的 FFT?
Parseval's Theorem does not hold for FFT of a sinusoid + noise?
在此先感谢您就此主题提供的任何帮助。我最近一直在尝试计算包含噪声时离散傅里叶变换的 Parseval 定理。我的代码基于 .
我期望看到的是(当不包括噪声时)频域中的总功率是时域中总功率的一半,因为我已经切断了负频率。
但是,随着时域信号加入更多的噪声,信号+噪声的傅里叶变换总功率变得远小于信号+噪声总功率的一半。
我的代码如下:
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。解决这个问题时我做错了什么吗?这种趋势随着噪声的增加而发生是否有物理原因?这与对不完美的正弦信号进行傅里叶变换有关吗?我这样做的原因是为了了解我有真实数据的非常嘈杂的正弦信号。
如果您使用整个频谱(正 和 负)频率来计算功率,Parseval 定理通常成立。
差异的原因是DC(f=0)分量,处理得有些特殊。
首先,直流分量从何而来?您使用 np.random.random
生成介于 0 和 1 之间的随机值。因此平均而言,您将信号提高 0.5*noise_amplitude,这需要很大的功率。此功率在时域中计算正确。
然而,在频域中,只有一个 FFT bin 对应于 f=0。所有其他频率的功率分布在两个仓中,只有直流电源包含在一个仓中。
通过缩放噪声,您可以添加直流电源。通过去除负频率,您去除了一半的信号功率,但大部分噪声功率位于被充分利用的直流分量中。
您有多种选择:
- 使用所有频率来计算功率。
- 使用没有直流分量的噪声:
randomvals = np.random.random(int(1e7)) - 0.5
- "Fix"去掉一半直流功率的功率计算:
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。
在此先感谢您就此主题提供的任何帮助。我最近一直在尝试计算包含噪声时离散傅里叶变换的 Parseval 定理。我的代码基于
我期望看到的是(当不包括噪声时)频域中的总功率是时域中总功率的一半,因为我已经切断了负频率。
但是,随着时域信号加入更多的噪声,信号+噪声的傅里叶变换总功率变得远小于信号+噪声总功率的一半。
我的代码如下:
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。解决这个问题时我做错了什么吗?这种趋势随着噪声的增加而发生是否有物理原因?这与对不完美的正弦信号进行傅里叶变换有关吗?我这样做的原因是为了了解我有真实数据的非常嘈杂的正弦信号。
如果您使用整个频谱(正 和 负)频率来计算功率,Parseval 定理通常成立。
差异的原因是DC(f=0)分量,处理得有些特殊。
首先,直流分量从何而来?您使用 np.random.random
生成介于 0 和 1 之间的随机值。因此平均而言,您将信号提高 0.5*noise_amplitude,这需要很大的功率。此功率在时域中计算正确。
然而,在频域中,只有一个 FFT bin 对应于 f=0。所有其他频率的功率分布在两个仓中,只有直流电源包含在一个仓中。
通过缩放噪声,您可以添加直流电源。通过去除负频率,您去除了一半的信号功率,但大部分噪声功率位于被充分利用的直流分量中。
您有多种选择:
- 使用所有频率来计算功率。
- 使用没有直流分量的噪声:
randomvals = np.random.random(int(1e7)) - 0.5
- "Fix"去掉一半直流功率的功率计算:
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。