有什么方法我可以比循环更快地迭代阵列



我正在编写一个代码,该代码将天文图上像素的通量与另一个位于另一个区域的相应区域进行比较。这两个地图都是数据的numpy阵列。

为了做到这一点,我需要将第一个地图(AV)上的像素索引转换为它们在天空坐标上的等效物,然后将这些天空坐标转换为其像素索引等效于第二张地图(CO)。然后,我将第二张地图的通量扩展,以匹配第一个地图的值。之后,我必须继续处理数据。

问题是,在第一张地图上有成千上万的像素,代码花了很长时间才能完成应该做的事情,这是故障排除的麻烦。我发现代码的这一部分最慢的东西是for循环。

有什么办法可以通过numpy数组迭代,能够使用索引并从每个像素中计算数据,比循环更快?有没有更好的方法来执行此操作。完全?

在伪代码中,我的代码是这样的:

for pixel i,j in 1st map:
    sky_x1,sky_y1 = pixel_2_skycoord(i,j)
    i2,j2 = skycoord_2_pixel(sky_x1,sky_y1)
    Avmap.append(Avflux[i,j])
    COmap.append(COflux[i2,j2]*scale)

实际代码是:

for i in xrange(0,sAv_y-1):
    for j in xrange(0,sAv_x-1):
        if not np.isnan(Avdata[i,j]):           
            y,x=wcs.utils.skycoord_to_pixel(wcs.utils.pixel_to_skycoord(i,j,wAv,0),wcs=wCO)
            x=x.astype(int)+0 #the zero is because i don't understand the problem with numpy but it fixes it anyway
            y=y.astype(int)+0 #i couldn't get the number from an array with 1 value but adding zero resolves it somehow
            COflux=COdata[x,y]
            ylist.append(Avdata[i,j])
            xlist.append(COflux*(AvArea/COArea))

罪魁祸首是循环的两个。Numpy具有许多功能,可以阻止用于循环的使用以允许快速编译的代码。诀窍是矢量化您的代码。

您可以查看Numpy的meshgrid函数,以将此数据转换为矢量化表单,然后您可以使用类似的内容,因此可以提出问题将任意函数应用于该向量。

沿着:

的线条
x_width = 15
y_width = 10
x, y = np.meshgrid(range(x_width), range(y_width))
def translate(x, y, x_o, y_o):
    x_new = x + x_o
    y_new = y + y_o
    return x_new, y_new
x_new, y_new = translate(x, y, 3, 3)
x_new[4,5], y[4,5]
(8, 4)

您必须避免循环,并在基础C代码,numpy或Astropy中进行沉重的计算,以进行天空/像素转换。使用astropy.wcs有几种选择。

第一个是用SkyCoord。让我们首先为您的像素索引创建一个价值网格:

In [30]: xx, yy = np.mgrid[:5, :5] 
    ...: xx, yy 
Out[30]: 
(array([[0, 0, 0, 0, 0],
        [1, 1, 1, 1, 1],
        [2, 2, 2, 2, 2],
        [3, 3, 3, 3, 3],
        [4, 4, 4, 4, 4]]), array([[0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4]]))

现在,我们可以从像素索引中创建SkyCoord对象(这是一个Numpy Array子类),并使用WCS:

In [33]: from astropy.coordinates import SkyCoord 
    ...: sky = SkyCoord.from_pixel(xx, yy, wcs) 
    ...: sky                                                                                   
Out[33]: 
<SkyCoord (FK5: equinox=2000.0): (ra, dec) in deg
    [[(53.17127889, -27.78771333), (53.17127889, -27.78765778),
      (53.17127889, -27.78760222), (53.17127889, -27.78754667),
      (53.17127889, -27.78749111)],
      ....

请注意,这是使用wcs.utils.skycoord_to_pixel。该对象还具有一种方法可以用WCS进行像素。我在这里出于实际目的将同样的事情:

In [34]: sky.to_pixel(wcs)                                                                     
Out[34]: 
(array([[ 0.00000000e+00, -1.11022302e-16, -2.22044605e-16,
         -3.33066907e-16,  1.13149046e-10],
        ...
        [ 4.00000000e+00,  4.00000000e+00,  4.00000000e+00,
          4.00000000e+00,  4.00000000e+00]]),
 array([[-6.31503738e-11,  1.00000000e+00,  2.00000000e+00,
          3.00000000e+00,  4.00000000e+00],
        ...
        [-1.11457732e-10,  1.00000000e+00,  2.00000000e+00,
          3.00000000e+00,  4.00000000e+00]]))

我们得到了新的X和Y索引的浮动值元组。因此,您需要将这些值舍入并将其转换为INT将其用作数组索引。

第二个选项是使用较低的功能,例如wcs.pixel_to_world_valueswcs.world_to_pixel_values,它采用NX2数组并返回此:

In [37]: wcs.pixel_to_world_values(np.array([xx.ravel(), yy.ravel()]).T)                       
Out[37]: 
array([[ 53.17127889, -27.78771333],
       [ 53.17127889, -27.78765778],
       [ 53.17127889, -27.78760222],
       [ 53.17127889, -27.78754667],
       ...

最新更新