我有以下数据数组,有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
条目,x0 y0等。是我想要的。 -1
条目是指示新框架的分隔符,在这些分隔符之后总是再次出现2个“数字”条目。
我制作了这段代码,它确实有用:
i = 2
pixels = np.int32(data_height)*np.int32(data_width)
data = np.zeros(pixels).reshape(data_height, data_width)
while i < len(rdata):
x = rdata[i]
y = rdata[i+1]
if x != -1 and y != -1:
data[y,x] = data[y,x] + 1
i = i + 2
elif x == -1 and y == -1:
i = i + 4
else:
print "something is wrong"
print i
print x
print y
rdata
是我的orignal数组。 data
是生成的矩阵,仅以零开头。 while循环从第一个x
坐标开始,在索引2处,然后如果它找到两个连续的-1
个条目,它将跳过四个条目。
脚本运行正常,但运行需要7秒。我怎样才能加快这个脚本的速度?我是python的初学者,从学习python的最困难的方法我知道虽然应该避免循环,但重写到for循环甚至更慢!
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
和y
坐标的位置?
更新:感谢所有答案!
我使用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全零,每帧有十几个,原始数据文件是4MB,因此应该可以进行一些压缩。
答案 0 :(得分:6)
听起来你想要的只是做一些布尔索引魔术来摆脱无效的帧内容,然后当然添加像素。
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)
答案 1 :(得分:2)
使用此功能删除-1
和number
s:
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数组,其中每个“图层”都是一个框架:
nf = splits.size + 1 # number of frames
splits -= 1 + 2*np.arange(nf-1) # account for missing `-1`s and `number`s
datastack = np.zeros((nf,h,w))
f0 = 0 # f0 = start of the frame
for i,f in enumerate(splits): # f = end of the frame
flat_data = np.ravel_multi_index(tuple(data[f0:f].T)[::-1], (h, w))
datastack[i] = np.bincount(flat_rdata, minlength=h*w).reshape(h, w)
f0 = f
现在,datastack[i]
是一个2D数组,显示数据的i
帧。
答案 2 :(得分:0)
如果x0, y0, x1, y1 != -1
你不能做filter(lambda a: a != -1, rdata)
这样的事情而不打扰ifs?这可以加快你的代码。