我使用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生成的情节(我在两侧使用相同数量的系数)。可能有什么不对?
数据:
答案 0 :(得分:12)
当你调用fft(wolfer)
时,你告诉变换假设一个基本周期等于数据的长度。要重建数据,您必须使用相同基本周期= 2*pi/N
的基函数。出于同样的原因,您的时间索引xs
必须超过原始信号的时间范围。
另一个错误是忘记完全复杂的乘法。将其视为Y[omega]*exp(1j*n*omega/N)
。
这是固定代码。注意我将i
重命名为ctr
,以避免与sqrt(-1)
和n
与N
混淆,以遵循使用小写的常规信号处理惯例样本,以及总样本长度的大写。我还导入__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()