2013-10-08 136 views
2

我有一個關於python的fftconvolve的問題。在我目前的研究中,我被要求計算兩個函數之間的一些卷積。爲此,我使用傅立葉變換(我使用numpy.fft並對其進行歸一化)進行計算。問題是,如果我想用fftconvolve包進行比較,它不能給出正確的結果。這裏是我的代碼:scipy.signal.fftconvolve沒有給出所需的結果

#!/usr/bin/python 
import numpy as np 
from scipy.signal import fftconvolve , convolve 

def FFT(array , sign): 
    if sign==1: 
    return np.fft.fftshift(np.fft.fft(np.fft.fftshift(array))) * dw/(2.0 * np.pi) 
    elif sign==-1: 
    return np.fft.fftshift(np.fft.ifft(np.fft.fftshift(array))) * dt * len(array) 


def convolve_arrays(array1,array2,sign): 
    sign = int(sign) 
    temp1 = FFT(array1 , sign,) 
    temp2 = FFT(array2 , sign,) 
    temp3 = np.multiply(temp1 , temp2) 
    return FFT(temp3 , -1 * sign)/(2. * np.pi) 

""" EXAMPLE """ 

dt = .1 
N  = 2**17 
t_max = N * dt/2 
time = dt * np.arange(-N/2 , N/2 , 1) 

dw = 2. * np.pi/(N * dt) 
w_max = N * dw/2. 
w  = dw * np.arange(-N/2 , N/2 , 1) 

eta_fourier = 1e-10 




Gamma = 1. 
epsilon = .5 
omega = .5 


G = zeros(N , complex) 
G[:] = 1./(w[:] - epsilon + 1j * eta_fourier) 

D = zeros(N , complex) 
D[:] = 1./(w[:] - omega + 1j * eta_fourier) - 1./(w[:] + omega + 1j * eta_fourier) 

H = convolve_arrays(D , G , 1)  
J = fftconvolve(D , G , mode = 'same') * np.pi/(2. * N) 

如果您繪製的HJ你會看到在w軸的轉變,也實/虛部,我不得不成倍爲了得到某種方式的J的結果關閉(但仍然沒有)到正確的結果。

有什麼建議嗎?

謝謝!

+3

請轉到['scipy.fftconvolve'](https://github.com/scipy/scipy/blob/master/scipy/signal/signaltools.py#L153)並觀察算法沒有你奇怪的變化或縮放你想用FFT功能實現什麼? –

回答

4

當計算卷積時,邊界條件很重要。

當您對兩個信號進行卷積時,結果的邊緣取決於您假定輸入的邊緣以外的值fftconvolve計算假設零填充邊界的卷積。請參考source code of fftconvolve。請注意他們去有心計通過實現零填充的邊界條件,特別是,這些行:

size = s1 + s2 - 1 

...

fsize = 2 ** np.ceil(np.log2(size)).astype(int) #For speed; often suboptimal! 
fslice = tuple([slice(0, int(sz)) for sz in size]) 

...

ret = ifftn(fftn(in1, fsize) * fftn(in2, fsize))[fslice].copy() 

...

return _centered(ret, s1) #strips off padding 

這是好東東!這可能值得仔細閱讀fftconvolve的代碼,如果你想了解基於傅里葉的卷積,那麼這是一個很好的教育。

簡要草圖

正向FFT零墊的每個信號,以防止週期邊界條件:

a = np.array([3, 4, 5]) 
b = np.fft.ifftn(np.fft.fftn(a, (5,))).real 
print b #[ 3. 4. 5. 0. 0.] 

正向FFT的乘積的逆FFT給出了填補的結果:

a = np.array([3, 4, 5]) 
b = np.array([0., 0.9, 0.1]) 
b = np.fft.ifftn(np.fft.fftn(a, (5,))* 
       np.fft.fftn(b, (5,)) 
       ).real 
print b #[ 0. 2.7 3.9 4.9 0.5] 

_centered函數剝離了最後的額外填充像素(假設你使用mode='same'選項)。

+0

它看起來像更新版本的fftconvolve [做得更好,選擇填補多少以獲得快速的FFT計算](https://github.com/scipy/scipy/blob/v0.15.1/scipy/signal/signaltools.py #L349) – Andrew

相關問題