2010-12-15 9 views
5

私はこの領域の古典的な例であるfftを使ってsunspots.datデータ(以下)を解析しました。私はfftの結果を実際の部品とimaginery部品で得ました。その後、フーリエ変換の式に従ってデータを再作成するために、これらの係数(最初の20)を使用しようとしました。 B_NするA_Nとimagineryに対応し、実際の部品を考えて、私はいくつかの理由ifftを使用せずにFFT結果を使って時系列データを再作成する

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)を呼ばれると

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

+2

スペクトルから何をやっていますか?さまざまなコンポーネントの相対的なスペクトル振幅を求める場合は、データウィンドウ(en.wikipedia.org/wiki/Window_function)を使用するとよいでしょう。例えば、 'np.abs(fft(wolfer * hanning(len(wolfer))))') 'をプロットすると、n = 30の周りのピークは、ウィンドウなしの場合より少し多くの構造を示します。 – mtrw

答えて

11

、あなたはデータの長さに等しい基本周期を想定する変換を語りました。データを再構成するには、基本周期= 2*pi/Nの基本関数を使用する必要があります。同じトークンで、あなたの時間インデックスxsは元の信号の時間サンプルの範囲を超えなければなりません。

もう一つの間違いは、完全な複素乗算に忘れることでした。これはY[omega]*exp(1j*n*omega/N)と考えるのが簡単です。

ここに固定コードがあります。注意sqrt(-1)nNと混同しないように、ictrに変更しました。サンプルの小文字と大文字のサンプルの長さの通常の信号処理規則に従ってください。また、整数除算についての混乱を避けるために__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*pi/N) + 1j*np.sin(x*ctr*2*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() 
+0

最初の20の場合、私は "for range for 20(20)"の行を変更しました。これはifftと同じ数の係数で完全に収まります。あなたのlen(Y)は明らかに全体を使い、それはデータに完全に合っています。とてもかっこいい。ありがとう。 – user423805

+1

最初の20と最後の20の両方を使いたいかもしれません。 'abs(Y)'をプロットすると、係数が対称であることがわかります。しかし、値を 'print'すれば、それらは実際には互いに複雑な複合体であることがわかります。これは、実際のデータに対するFFTのエルミート対称性によるものです。結論は、低周波数係数と高周波数係数の両方を使用せずに実際の答えを返さないということです。 – mtrw

+1

これを消化するには数週間かかるでしょう:)もう一度感謝します。 – user423805

関連する問題