Python rfft不能产生正确的相位信息

Python rfft不能产生正确的相位信息,python,numpy,scipy,signal-processing,fft,Python,Numpy,Scipy,Signal Processing,Fft,所以我正试图写一个代码来实现福尔曼相位校正来校正干涉图中相位相关的不对称性。该程序的前提是将exp(-i*相位角)的傅里叶变换与干涉图进行卷积。这项技术从60年代就已经出现了,它应该会起作用,但我一直有困难 因此,我使用python生成一个相位角正好为0的干涉图来调试我的代码。一旦我开始工作,我生成了一张相位为0.3弧度的干涉图,我的相位阵列看起来不像常数0.3,我不确定发生了什么。我试过numpy arctan、numpy arctan2和numpy angle,结果都很糟糕。我也尝试过对我的

所以我正试图写一个代码来实现福尔曼相位校正来校正干涉图中相位相关的不对称性。该程序的前提是将exp(-i*相位角)的傅里叶变换与干涉图进行卷积。这项技术从60年代就已经出现了,它应该会起作用,但我一直有困难

因此,我使用python生成一个相位角正好为0的干涉图来调试我的代码。一旦我开始工作,我生成了一张相位为0.3弧度的干涉图,我的相位阵列看起来不像常数0.3,我不确定发生了什么。我试过numpy arctan、numpy arctan2和numpy angle,结果都很糟糕。我也尝试过对我的数据进行切趾处理,但没有任何帮助,所以为了清晰起见,我将其删除

知道我为什么不能从程序中获得正确的阶段信息吗?如果将此代码插入python,就会得到一些不可靠的阶段图

我对我的处理函数很有信心,代码的真正部分在下面,我调用这些函数来处理干涉图。计算相角的基本程序为:

-将干涉图截断为少量点(我使用401) -旋转它,使零路径差(ZPD)成为第一个数据点 -将ZPD值乘以0.5(不确定原因,但学术论文称必须这样做) -对结果数据进行实(单边)fft -取虚数的反正切除以实数得到相角

所以我按照上面的程序来做一个人工生成的干涉图,相移为0.3弧度,但无法用这个程序重现相位误差。有什么想法吗?谢谢你们能提供的任何帮助

编辑:这个问题归结起来很多是,在应用fft之前,我应该如何安排我的信号(已知的,恒定的,相位误差为0.3),以使我的结果的虚部为常数0.3?此外,我应该使用python中哪种类型的fft来实现这个结果?我很有信心,我成功地生成了一个恒定相位误差为0.3的信号

代码:

进口商 将numpy作为np导入 导入scipy.integrate 将matplotlib.pyplot作为plt导入 plt.style.use('ggplot')) 从scipy.fftpack导入dct、idct、dst、idst 导入cmath 从scipy输入信号 从scipy.integrate导入simps 导入csv ##生成干涉图 xlist=np.arange(-0.03,0.03,(1/15798.69)) 纽卡斯=200 打印“生成干涉图…” def infGen(nu,xval): h=6.626*10**-34#J*s c=3*10**8#m/s kB=1.38*10**-23#J/K T=300.0#K 返回0.5*2*h*c*c*nu*nu*nu*(100.0**3)*1/(np.exp(h*c*nu*100/(kB*T))-1)*np.cos(2*np.pi*nu*xval+0.3) 干涉图=列表() intError=list() 对于范围内的i(len(xlist)): xval=xlist[i] 值,error=scipy.integrate.quad(infGen,5004000,args=(xval),limit=150) 干涉图。附加(值) intError.append(错误) ##处理功能 def截断(干涉图、中心突发): 截断=列表() 截断长度=2*Numpasse+1 对于范围内的i(截断长度): 截断.追加(干涉图[centerburst-(截断长度/2)+i]) #计算干涉图平均值以进行归一化 truncavg=np.平均值(截断) #通过平均值对干涉图进行标准化 对于范围内的i(len(截断)): 截断的[i]=截断的[i]-truncavg 返回截断 def rotateMertz(干涉图): 旋转=列表() 对于范围内的i(透镜(干涉图)-纽卡斯): 旋转.附加(干涉图[i+NUMPASE]) 对于范围内的i(强调): 旋转附加(干涉图[i]) 旋转返回 def getphaseangle(fftdata): phaseangle=list() 对于范围内的i(len(fftdata)): #相位角附加(np角(fftdata[i])) “”“如果fftdata[i].imag<0: 相位角[i]=相位角[i]+2*np.pi
如果fftdata[i].real>0且np.abs(fftdata[i].imag)是实数还是复数?干涉图是实数,因为它通常是一个物理测量值。您可以取“实数”“正如python所描述的那样,fft,因为我只对fft域中的正频率信息感兴趣。我的理解是numpys fft和rfft之间的唯一区别是fft提供负和正频率信息,而rfft只提供正的一半。您对干涉图的真实性/复杂性有何顾虑?您希望输出结果如何?0.3的恒定相位?是的!我已经定义了干涉图的相位偏移0.3,在干涉图的余弦定义中包括+0.3。我刚刚发现的另一点是fft正在删除数据点。例如,如果我取一个201点列表,然后取它的rfft,我得到一个101点数组。然后,如果我取它的irfft,我得到一个200点的数组,少1点。irfft(rfft(x))不应该返回x,而不是x减去1个数据点吗?
## Importer
import numpy as np
import scipy.integrate
import matplotlib.pyplot as plt
plt.style.use('ggplot')
from scipy.fftpack import dct,idct,dst,idst
import cmath
from scipy import signal
from scipy.integrate import simps
import csv

## Generate interferogram
xlist = np.arange(-0.03, 0.03,(1/15798.69))
numPhase = 200
print 'generating interferogram...'
def infGen(nu, xval):
    h = 6.626*10**-34 #J*s
    c = 3*10**8 #m/s
    kB = 1.38*10**-23 #J/K
    T = 300.0 # K    
    return 0.5*2*h*c*c*nu*nu*nu*(100.0**3)*1/(np.exp(h*c*nu*100/(kB*T))-1)*np.cos(2*np.pi*nu*xval+0.3)
interferogram = list()
intError = list()
for i in range(len(xlist)):
    xval = xlist[i]
    value, error = scipy.integrate.quad(infGen,500,4000,args = (xval),limit=150)
    interferogram.append(value)
    intError.append(error)

## Processing functions
def truncate(interferogram, centerburst):
    truncated=list()
    truncatedLength=2*numPhase+1
    for i in range(truncatedLength):
        truncated.append(interferogram[centerburst-(truncatedLength/2)+i])
    #Compute interferogram averages to normalize
    truncavg=np.average(truncated)
    #Normalize the interferograms by their averages
    for i in range(len(truncated)):
        truncated[i]=truncated[i]-truncavg
    return truncated
def rotateMertz(interferogram):
    rotated=list()
    for i in range(len(interferogram)-numPhase):
        rotated.append(interferogram[i+numPhase])
    for i in range(numPhase):
        rotated.append(interferogram[i])
    return rotated   
def getphaseangle(fftdata):
    phaseangle=list()
    for i in range(len(fftdata)):
        #phaseangle.append(np.angle(fftdata[i]))
        """if fftdata[i].imag < 0:
            phaseangle[i] = phaseangle[i]+2*np.pi
        if fftdata[i].real>0 and np.abs(fftdata[i].imag)<(10**-10) and fftdata[i].imag<0:
            phaseangle[i] = 0"""
        phaseangle.append(np.arctan(fftdata[i].imag/fftdata[i].real))
    return phaseangle
def findZPD(inf):
    # finds the index of the zpd for a given interferogram
    maxVal=max(np.abs(inf))
    x = [i for i, j in enumerate(inf) if j==maxVal]
    return x[0]

## Process Interferogram
inf = interferogram
phasedataTrunc = truncate(inf, findZPD(inf))
phasedataRot = rotateMertz(phasedataTrunc) # Rotates so ZPD is first value
phasedataRot[0] = phasedataRot[0]*0.5 # Multiply ZPD value by 0.5
phasedataFFT = np.fft.rfft(phasedataRot)
plt.figure('real part')
plt.plot(phasedataFFT.real)
plt.figure('imaginary part')
plt.plot(phasedataFFT.imag)
plt.figure('imaginary/real')
plt.plot(phasedataFFT.imag/phasedataFFT.real)
phaseAngle = getphaseangle(phasedataFFT)
plt.figure('phase angle')
plt.plot(phaseAngle)
plt.show()