在数组中循环匹配模式时加速

2024-04-19 20:13:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下数据数组,有200万个条目:

[20965  1239   296   231    -1    -1 20976  1239   299   314   147   337
   255   348    -1    -1 20978  1239   136   103   241   154    27   293
    -1    -1 20984  1239    39   161   180   184    -1    -1 20990  1239
   291    31   405    50   569   357    -1    -1 20997  1239   502    25
   176   215   360   281    -1    -1 21004  1239    -1    -1 21010  1239
   286   104   248   252    -1    -1 21017  1239   162    38   331   240
   368   363   321   412    -1    -1 21024  1239   428   323    -1    -1
 21030  1239    -1    -1 21037  1239   325    28   353   102   477   189
   366   251   143   452 ... ect

这个阵列包含了一个CCD芯片上光子的x,y坐标,我想通过这个阵列,把所有这些光子事件加在一个与CCD芯片尺寸相等的矩阵中。在

格式如下:number number x0 y0 x1 y1 -1 -1。我不太关心的两个number条目,x0y0等等。是我想出去的。-1条目是一个分隔符,表示一个新的帧,在这些分隔符之后总是有2个“number”条目。在

我做了一个代码,它确实有效:

^{pr2}$

rdata是我的原始数组。data是结果矩阵,它只以零开始。while循环从索引2的第一个x坐标开始,如果找到两个连续的-1条目的话,它将跳过四个条目。在

这个脚本运行得很好,但是运行需要7秒。如何加快脚本的速度?对于python来说,重写循环是最难的!在

for i in range(2, len(rdata), 2):

    x = rdata[i]
    y = rdata[i+1]

    if x != -1 and y != -1:
        px = rdata[i-2]
        py = rdata[i-1]

        if px != -1 and py != -1:
            data[y,x] = data[y,x] + 1

也许有人可以想出一个更快的方法,类似于np.argwhere(rdata == -1)并使用这个输出来提取x和{}坐标的位置?在


更新:谢谢所有的回答!在

我使用askewchan的方法来保存帧信息,但是,由于我的数据文件有300000帧长,当我试图生成一个维数为300000、640、480的numpy数组时,出现了内存错误。我可以通过生成一个生成器对象来解决这个问题:

def bindata(splits, h, w, data):

    f0=0
    for i,f in enumerate(splits):
        flat_rdata = np.ravel_multi_index(tuple(data[f0:f].T)[::-1], (h, w))
        dataslice = np.zeros((w,h), dtype='h')
        dataslice = np.bincount(flat_rdata, minlength=pixels).reshape(h, w)
        f0 = f
        yield dataslice

然后,我使用Gohlke的tifffile.py的修改版本从数组中生成tif,从数据生成tiff文件。它工作得很好,但是我需要找到一种方法来压缩数据,因为tiff文件是>;4gb(此时脚本崩溃)。我有非常稀疏的数组,640*480全零,每帧有十几个1,原始数据文件是4MB,所以一些压缩应该是可能的。在


Tags: 文件数据方法py脚本numberdatanp
3条回答

听起来你只需要做一些布尔索引魔术来去除无效的帧内容,然后当然把像素加起来。在

rdata = rdata.reshape(-1, 2)
mask = (rdata != -1).all(1)

# remove every x, y pair that is after a pair with a -1.
mask[1:][mask[:-1] == False] = False
# remove first x, y pair
mask[0] = False

rdata = rdata[mask]

# Now need to use bincount, [::-1], since you use data[y,x]:
flat_rdata = np.ravel_multi_index(tuple(rdata.T)[::-1], (data_height, data_width))

res = np.bincount(flat_rdata, minlength=data_height * data_width)
res = res.reshape(data_height, data_width)

使用此命令可删除-1numbers:

rdata = np.array("20965  1239   296   231    -1    -1 20976  1239   299   314   147   337 255   348    -1    -1 20978  1239   136   103   241   154    27   293 -1    -1 20984  1239    39   161   180   184    -1    -1 20990  1239 291    31   405    50   569   357    -1    -1 20997  1239   502    25 176   215   360   281    -1    -1 21004  1239    -1    -1 21010  1239 286   104   248   252    -1    -1 21017  1239   162    38   331   240 368   363   321   412    -1    -1 21024  1239   428   323    -1    -1 21030  1239    -1    -1 21037  1239   325    28   353   102   477   189 366   251   143   452".split(), dtype=int)

rdata = rdata.reshape(-1,2)
splits = np.where(np.all(rdata==-1, axis=1))[0]
nonxy = np.hstack((splits,splits+1))
data = np.delete(rdata, nonxy, axis=0)[1:]

现在,使用@seberg的部分方法将x-y列表转换为数组,您可以制作一个3D数组,其中每个“层”都是一个帧:

^{pr2}$

{cd3>现在显示的是

如果x0, y0, x1, y1 != -1你能不能不做一些类似filter(lambda a: a != -1, rdata)的事情,然后不去烦ifs?这样可以加快你的代码速度。在

相关问题 更多 >