简体   繁体   English

使用 numpy.fft 的卷积导致时移

[英]Convolution using numpy.fft causes time shift

I'm trying to write a convolution code entirely in the spectral domain.我正在尝试完全在谱域中编写卷积代码。 I'm taking a spike series in time (example below only has one spike for simplicity) of n samples and calculating the Fourier series with numpy.fft.fft .我正在及时获取 n 个样本的尖峰序列(为简单起见,下面的示例只有一个尖峰)并使用numpy.fft.fft计算傅里叶级数。 I create a 'Ricker wavelet' of m samples (m << n) and calculate its Fourier series with numpy.fft.fft , but specifying that its output Fourier series be n samples long.我创建了 m 个样本 (m << n) 的“Ricker 小波”,并使用numpy.fft.fft计算其傅里叶级数,但指定其 output 傅里叶级数为 n 个样本长。 Both the spike series and wavelet have the same sampling interval.尖峰序列和小波具有相同的采样间隔。 The resulting convolved series is shifted (peak of wavelet is shifted along the time axis with respect to the spike).生成的卷积序列发生偏移(小波峰值相对于尖峰沿时间轴偏移)。 This shift seems to depend on the size, m, of the wavelet.这种转变似乎取决于小波的大小 m。

I thought it had something to do with the parameters of numpy.fft.fft(a, n=None, axis=-1, norm=None) , particularly the 'axis' parameter.我认为这与numpy.fft.fft(a, n=None, axis=-1, norm=None)的参数有关,尤其是“轴”参数。 But, I do not understand the documentation for this parameter at all.但是,我根本不理解这个参数的文档。

Can anyone help me understand why I'm getting this shift (if it isn't clear, let me be explicit and say that the peak of the wavelet in the convolved series must the at the same time sample of the spike in the input spike series)?谁能帮我理解为什么我会发生这种转变(如果不清楚,让我明确地说卷积序列中小波的峰值必须同时是输入尖峰中尖峰的样本系列)?

My code follows:我的代码如下:

################################################################################
#
# import libraries
#
import math
import numpy as np
import scipy
import matplotlib.pyplot as plt
import os
from matplotlib.ticker import MultipleLocator
from random import random
# Define lists
#
Time=[]; Ricker=[]; freq=25; rickersize=51; timeiter=0.002; serieslength=501; TIMElong=[]; Reflectivity=[];
Series=[]; IMPEDANCE=[]; CONVOLUTION=[];
#
# Create ricker wavelet and its time sequence
#
for i in range(0,rickersize):
    time=(float(i-rickersize//2)*timeiter)
    ricker=(1-2*math.pi*math.pi*freq*freq*time*time)*math.exp(-1*math.pi*math.pi*freq*freq*time*time)
    Time.append(time)
    Ricker.append(ricker)
#
# Do various FFT operations on the Ricker wavelet:
#   Normal FFT, FFT of longer Ricker, Amplitude of the FFTs, their inverse FFTs and their frequency sequence
#
FFT=np.fft.fft(Ricker); FFTlong=np.fft.fft(Ricker,n=serieslength,axis=0,norm=None);
AMP=abs(FFT); AMPlong=abs(FFTlong);
RICKER=np.fft.ifft(FFT); RICKERlong=np.fft.ifft(FFTlong);
FREQ=np.fft.fftfreq(len(Ricker),d=timeiter); FREQlong=np.fft.fftfreq(len(RICKERlong),d=timeiter)
PHASE=np.angle(FFT); PHASElong=np.angle(FFTlong);
#
# Create a single spike in the otherwise empty (0) series of length 'serieslength' (=len(RICKERlong)
#   this spikes mimics a very simple seismic reflectivity series in time
#
for i in range(0,serieslength):
    time=(float(i)*timeiter)
    TIMElong.append(time)
    if i==int(serieslength/2):
        Series.append(1)
    else:
        Series.append(0)
#
# Do various FFT operations on the spike series
#   Normal FFT, Amplitude of the FFT, its inverse FFT and frequency sequence
#
FFTSeries=np.fft.fft(Series)
AMPSeries=abs(FFTSeries)
SERIES=np.fft.ifft(FFTSeries)
FREQSeries=np.fft.fftfreq(len(Series),d=timeiter)
#
# Do convolution of the spike series with the (long) Ricker wavelet in the frequency domain and see result via inverse FFT
#
FFTConvolution=[FFTlong[i]*FFTSeries[i] for i in range(len(Series))]
CON=np.fft.ifft(FFTConvolution)
CONVOLUTION=[CON[i].real for i in range(len(Series))]
#
# plotting routines
#
fig,axs = plt.subplots(nrows=1,ncols=3, figsize=(14,8))
axs[0].barh(TIMElong,Series,height=0.005, color='black')
axs[1].plot(Ricker,Time,color='black', linestyle='solid',linewidth=1)
axs[2].plot(CONVOLUTION,TIMElong,color='black', linestyle='solid',linewidth=1)
#
axs[0].set_aspect(aspect=8); axs[0].set_title('Reflectivity',fontsize=12); axs[0].yaxis.grid(); axs[0].xaxis.grid(); 
axs[0].set_xlim(-2,2); axs[0].set_ylim(min(TIMElong),max(TIMElong)); axs[0].invert_yaxis(); axs[0].tick_params(axis='both',which='major',labelsize=12);
#
axs[1].set_aspect(aspect=6.2); axs[1].set_title('Ricker',fontsize=12); axs[1].yaxis.grid(); axs[1].xaxis.grid(); 
axs[1].set_xlim(-1.0,1.02); axs[1].set_ylim(min(Time),max(Time)); axs[1].invert_yaxis(); axs[1].tick_params(axis='both',which='major',labelsize=12);
#
axs[2].set_aspect(aspect=8); axs[2].set_title('Convolution',fontsize=12); axs[2].yaxis.grid(); axs[2].xaxis.grid();
axs[2].set_xlim(-2,2); axs[2].set_ylim(min(TIMElong),max(TIMElong)); axs[2].invert_yaxis(); axs[2].tick_params(axis='both',which='major',labelsize=12);
#
fig.tight_layout()
fig.show()
####

It turns out that, as far as I can understand, that my question has nothing to do with the peculiarities of python and numpy.事实证明,据我所知,我的问题与 python 和 numpy 的特性无关。 The problem is 'circular convolution'.问题是“循环卷积”。 That is, the convolution of two data sequences is longer by a combination of the lengths of both sequences.也就是说,两个数据序列的卷积通过两个序列的长度的组合而更长。 This has to be accounted for in the fft and ifft.这必须在 fft 和 ifft 中考虑。 I wasn't doing this.这不是我做的。 I still don't know exactly how to handle this, but it should be simpler now I know what the problem is.我仍然不知道如何处理这个问题,但现在我知道问题所在应该更简单了。

Apologies to those who tried to answer my malformed question.向那些试图回答我的畸形问题的人道歉。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM