Python 在不使用ifft的情况下使用FFT结果重建时间序列数据

Python 在不使用ifft的情况下使用FFT结果重建时间序列数据,python,math,signal-processing,fft,Python,Math,Signal Processing,Fft,我使用fft分析了sunspots.dat数据(如下),fft是该领域的经典示例。我从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

我使用fft分析了sunspots.dat数据(如下),fft是该领域的经典示例。我从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生成的图(我在两侧使用相同数量的系数)。有什么不对劲吗

数据:

当调用
fft(wolfer)
时,您告诉变换假定基本周期等于数据长度。要重建数据,必须使用相同基本周期的基函数=
2*pi/N
。同样,您的时间索引
xs
必须覆盖原始信号的时间样本

另一个错误是忘了做完整的复数乘法。更容易将其视为
Y[omega]*exp(1j*n*omega/n)

这是固定密码。注:我将
I
重命名为
ctr
,以避免与
sqrt(-1)
混淆,并将
n
重命名为
n
以遵循通常的信号处理惯例,即使用小写表示样本,大写表示总样本长度。我还导入了
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuu除法
,以避免对整数除法的混淆

忘记前面添加:请注意,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()

只是出于好奇,你对光谱做了什么?如果您试图确定各种成分的相对光谱振幅,可能需要使用数据窗口(en.wikipedia.org/wiki/window_函数)。例如,如果你绘制
np.abs(fft(wolfer*hanning(len(wolfer)))
n=30附近的峰值显示出比没有窗口时稍多的结构。对于前20个,我只是将行更改为“For ctr in range(20)”,这与系数数量相同的ifft非常吻合。你的len(Y)显然使用了整个东西,这与数据非常吻合。很酷。谢谢。你可能想同时使用前20个和后20个。如果绘制abs(Y),您将看到系数是对称的。但是如果你打印这些值,你会发现它们实际上是彼此的复杂共轭体。这是由于FFT对真实数据的厄米对称性。结果是,如果不同时使用低频系数和高频系数,你将无法得到真正的答案。这将需要数周的时间来消化:)再次感谢。