使用FFT结果重新创建时间序列数据,而不使用ifft

时间:2010-12-15 15:25:07

标签: python math signal-processing fft

我使用fft分析了sunspots.dat数据(下面),这是该领域的一个典型例子。我从真实和想象部分的fft中获得了结果。然后我尝试使用这些系数(前20个)来重建符合傅立叶变换公式的数据。思考实部对应a_n和想象到b_n,我有

import numpy as np
from scipy import *
from matplotlib import pyplot as gplt
from scipy import fftpack

def f(Y,x):
    total = 0
    for i in range(20):
        total += Y.real[i]*np.cos(i*x) + Y.imag[i]*np.sin(i*x)
    return total

tempdata = np.loadtxt("sunspots.dat")

year=tempdata[:,0]
wolfer=tempdata[:,1]

Y=fft(wolfer)
n=len(Y)
print n

xs = linspace(0, 2*pi,1000)
gplt.plot(xs, [f(Y, x) for x in xs], '.')
gplt.show()       

出于某种原因,我的情节不会反映ifft生成的情节(我在两侧使用相同数量的系数)。可能有什么不对?

数据:

http://linuxgazette.net/115/misc/andreasen/sunspots.dat

1 个答案:

答案 0 :(得分:12)

当你调用fft(wolfer)时,你告诉变换假设一个基本周期等于数据的长度。要重建数据,您必须使用相同基本周期= 2*pi/N的基函数。出于同样的原因,您的时间索引xs必须超过原始信号的时间范围。

另一个错误是忘记完全复杂的乘法。将其视为Y[omega]*exp(1j*n*omega/N)

更容易

这是固定代码。注意我将i重命名为ctr,以避免与sqrt(-1)nN混淆,以遵循使用小写的常规信号处理惯例样本,以及总样本长度的大写。我还导入__future__ division以避免混淆整数除法。

之前忘了添加:请注意,SciPy的fft在累积后不会除以N。在使用Y[n]之前,我没有把它分开;如果你想要获得相同的数字,而不是仅仅看到相同的形状,你应该这样做。

最后,请注意我正在对整个频率系数进行求和。当我绘制np.abs(Y)时,看起来在较高频率中存在重要值,至少在样本70左右之前。我认为通过对整个范围进行求和,查看正确的结果,然后减去系数并查看发生的情况,可以更容易地理解结果。

from __future__ import division
import numpy as np
from scipy import *
from matplotlib import pyplot as gplt
from scipy import fftpack

def f(Y,x, N):
    total = 0
    for ctr in range(len(Y)):
        total += Y[ctr] * (np.cos(x*ctr*2*np.pi/N) + 1j*np.sin(x*ctr*2*np.pi/N))
    return real(total)

tempdata = np.loadtxt("sunspots.dat")

year=tempdata[:,0]
wolfer=tempdata[:,1]

Y=fft(wolfer)
N=len(Y)
print(N)

xs = range(N)
gplt.plot(xs, [f(Y, x, N) for x in xs])
gplt.show()