我正试图抓住Python的fft功能,而我偶然发现的一个奇怪的事情是Parseval's theorem似乎不适用,因为它给出的差异大约为50现在,虽然它应该是0。
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack as fftpack
pi = np.pi
tdata = np.arange(5999.)/300
dt = tdata[1]-tdata[0]
datay = np.sin(pi*tdata)+2*np.sin(pi*2*tdata)
N = len(datay)
fouriery = abs(fftpack.rfft(datay))/N
freqs = fftpack.rfftfreq(len(datay), d=(tdata[1]-tdata[0]))
df = freqs[1] - freqs[0]
parceval = sum(datay**2)*dt - sum(fouriery**2)*df
print parceval
plt.plot(freqs, fouriery, 'b-')
plt.xlim(0,3)
plt.show()
我很确定它是一个归一化因子,但我似乎无法找到它,因为我能找到的有关此函数的所有信息都是scipy.fftpack.rfft documentation。
答案 0 :(得分:18)
归一化因子来自于尝试将Parseval定理应用于连续信号的傅里叶变换到离散序列。在the wikipedia article on the Discrete Fourier transform的侧面板上,讨论了傅里叶变换,傅里叶级数,离散傅里叶变换和用Dirac combs进行采样的关系。
简而言之,Parseval's theorem, when applied to DFTs不需要整合,只需要求和:通过乘以2*pi
和dt
汇总来创建df
另请注意,因为您使用的是scipy.fftpack.rfft
,所以您得到的数据不是数据的DFT,而只是正数的一半,因为负数将与它对称。因此,由于您只添加了一半数据,加上DC术语中的0
,因此缺少2
来到@unutbu找到的4*pi
。
在任何情况下,如果datay
保存您的序列,您可以验证Parseval定理如下:
fouriery = fftpack.rfft(datay)
N = len(datay)
parseval_1 = np.sum(datay**2)
parseval_2 = (fouriery[0]**2 + 2 * np.sum(fouriery[1:]**2)) / N
print parseval_1 - parseval_2
使用scipy.fftpack.fft
或numpy.fft.fft
第二次总结不需要采用这种奇怪的形式:
fouriery_1 = fftpack.fft(datay)
fouriery_2 = np.fft.fft(datay)
N = len(datay)
parseval_1 = np.sum(datay**2)
parseval_2_1 = np.sum(np.abs(fouriery_1)**2) / N
parseval_2_2 = np.sum(np.abs(fouriery_2)**2) / N
print parseval_1 - parseval_2_1
print parseval_1 - parseval_2_2