我正在尝试使用Python和astropy.io从FITS文件中的二进制表中提取数据。该表包含一个包含超过200万个事件的事件数组。我想要做的是将某些事件的TIME值存储在一个数组中,这样我就可以对该数组进行分析。我遇到的问题是,虽然在fortran(使用FITSIO)中,相同的操作在速度慢得多的处理器上花费了几秒钟,但使用astropy.io的Python中完全相同的操作需要几分钟。我想知道瓶颈究竟在哪里,以及是否有更有效的方法来访问各个元素以确定是否将每个时间值存储在新数组中。这是我到目前为止的代码:
from astropy.io import fits
minenergy=0.3
maxenergy=0.4
xcen=20000
ycen=20000
radius=50
datafile=fits.open('datafile.fits')
events=datafile['EVENTS'].data
datafile.close()
times=[]
for i in range(len(events)):
energy=events['PI'][i]
if energy<maxenergy*1000:
if energy>minenergy*1000:
x=events['X'][i]
y=events['Y'][i]
radius2=(x-xcen)*(x-xcen)+(y-ycen)*(y-ycen)
if radius2<=radius*radius:
times.append(events['TIME'][i])
print times
任何帮助将不胜感激。我是其他语言的好程序员,但我之前不必担心Python的效率。我之所以选择在Python中这样做的原因是我在使用fortran和FITSIO以及PGPLOT,以及来自Numerical Recipes的一些例程,但是我在这台机器上使用的新的fortran编译器无法被说服以产生正常工作程序(存在32-与64位等问题)。 Python似乎具有我需要的所有功能(FITS I / O,绘图等),但是如果需要永远访问列表中的各个元素,我将不得不找到另一种解决方案。
非常感谢。
答案 0 :(得分:7)
您需要使用numpy vector操作执行此操作。如果没有像numba这样的特殊工具,像你这样做大循环在Python中总是很慢,因为它是一种解释型语言。你的程序看起来应该更像:
energy = events['PI'] / 1000.
e_ok = (energy > min_energy) & (energy < max_energy)
rad2 = (events['X'][e_ok] - xcen)**2 + (events['Y'][e_ok] - ycen)**2
r_ok = rad2 < radius**2
times = events['TIMES'][e_ok][r_ok]
这应该具有与Fortran相当的性能。您还可以过滤整个事件表,例如:
events_filt = events[e_ok][r_ok]
times = events_filt['TIMES']