我目前正致力于将一些C代码翻译成Python。此代码用于帮助识别由射电天文学中使用的CLEAN算法引起的错误。为了进行此分析,必须在特定像素值(由ANT_pix给出)处找到强度映射的傅立叶变换,Q斯托克斯映射和U斯托克斯映射的值。这些地图只有257 * 257阵列。
下面的代码用C运行需要几秒钟,但用Python运行需要几个小时。我很确定它非常优化,因为我对Python的了解非常差。
感谢您提供任何帮助。
更新我的问题是,是否有更好的方法在Python中实现循环,这将加快速度。我在这里读了很多关于Python的其他问题的答案,如果可能的话,建议在Python中避免使用嵌套for循环,我只是想知道是否有人知道如何在没有循环或更好的情况下实现类似下面的Python代码的好方法优化的循环。我意识到这可能是一个很高的命令!
到目前为止,我一直在使用FFT,但我的主管希望看到DFT会产生什么样的差异。这是因为天线位置通常不会出现在精确像素值处。使用FFT需要舍入到最接近的像素值。
我使用Python作为CASA,用于减少射电天文数据集的计算机程序是用python编写的,并且在其中实现Python脚本远比C容易得多。
原始代码
def DFT_Vis(ANT_Pix="",IMap="",QMap="",UMap="", NMap="", Nvis=""):
UV=numpy.zeros([Nvis,6])
Offset=(NMap+1)/2
ANT=ANT_Pix+Offset;
i=0
l=0
k=0
SumI=0
SumRL=0
SumLR=0
z=0
RL=QMap+1j*UMap
LR=QMap-1j*UMap
Factor=[math.e**(-2j*math.pi*z/NMap) for z in range(NMap)]
for i in range(Nvis):
X=ANT[i,0]
Y=ANT[i,1]
for l in range(NMap):
for k in range(NMap):
Temp=Factor[int((X*l)%NMap)]*Factor[int((Y*k)%NMap)];
SumI+=IMap[l,k]*Temp
SumRL+=RL[l,k]*Temp
SumLR+=IMap[l,k]*Temp
k=1
UV[i,0]=SumI.real
UV[i,1]=SumI.imag
UV[i,2]=SumRL.real
UV[i,3]=SumRL.imag
UV[i,4]=SumLR.real
UV[i,5]=SumLR.imag
l=1
k=1
SumI=0
SumRL=0
SumLR=0
return(UV)
答案 0 :(得分:3)
您应该使用numpy的傅里叶变换代码,而不是自己编写代码:http://docs.scipy.org/doc/numpy/reference/routines.fft.html
答案 1 :(得分:1)
如果您有兴趣提高脚本的性能,cython可能是一种选择。
答案 2 :(得分:1)
我不是FFT的专家,但我的理解是FFT只是计算DFT的一种快速方法。所以对我来说,你的问题听起来像是在尝试编写一个冒泡排序算法,看看它是否提供了比quicksort更好的答案。它们都是排序算法,可以得到相同的结果!
所以我质疑你的基本前提。我想知道你是否可以改变你的数据四舍五入并从SciPy FFT代码得到相同的结果。
另外,根据我的DSP教科书,FFT可以产生比计算DFT更长的精确答案,因为浮点运算是不精确的,并且FFT在查找正确的过程中调用更少的浮点运算答案。
如果你有一些工作的C代码可以进行你想要的计算,你总是可以包装C代码让你从Python中调用它。在此讨论:Wrapping a C library in Python: C, Cython or ctypes?
要回答您的实际问题:正如@ ZoZo123所述,从range()
更改为xrange()
将是一个巨大的胜利。使用range()
,Python必须构建一个数字列表,然后在完成后销毁列表;使用xrange()
Python只创建一个迭代器,一次产生一个数字。 (但请注意,在Python 3.x中,range()
构成一个迭代器而没有xrange()
。)
此外,如果此代码不必与代码的其余部分集成,您可以尝试在PyPy下运行此代码。这正是PyPy可以最好地优化的那种代码。 PyPy的问题是,目前你的项目必须是“纯粹的”Python,看起来你正在使用NumPy。 (有些项目可以让NumPy和PyPy一起工作,但还没有完成。)http://pypy.org/
如果此代码确实需要与其余代码集成,那么我认为您需要查看Cython(正如@KrzysztofRosiński所述)。