array2root
返回具有包含分支名称的dtype的元组列表。是否有一种方法可以从uproot.iterate()
返回相同类型的格式,而无需在之后进行重塑?
输出应与
的输出相同array = root2array(['file.root'], treename = 'tree', branches = ['pt', 'eta'])
哪个像np.array([(pt0, eta0), (pt1, eta1), ... dtype=[('pt', '<f4'), ('eta', '<f4')]]
答案 0 :(得分:0)
如果您对数组的大小有上限(即从iterate
获取数组,那么您可以传递entrysteps=10000
并知道它永远不会比{{ 1}}),那么您可以预分配数组,然后将其传递给uproot并进行uproot填充,而不用创建新的数组。您可以将其设置为记录数组:
10000
buffer = numpy.empty(20000, dtype=[("pt", "f8"), ("eta", "f8")])
pt_buffer = buffer["pt"]
eta_buffer = buffer["eta"]
和pt_buffer
是eta_buffer
的视图,碰巧是交错的,但它们的工作原理与数组一样好。 (我将说明分配buffer
而不是仅仅分配20000
的原因。)
现在说,您对默认值为10000
为interpretation
的两个分支感兴趣。使用解释uproot.asdtype(">f8", "f8")
和uproot.asarray(">f8", pt_buffer)
请求这些数组。第一个参数是Numpy dtype,将用于解释ROOT文件中的原始数据(big-endian,因此为uproot.asarray(">f8", eta_buffer)
),第二个参数是要将数据读取到的数组,就地。
">"
请参阅the documentation,了解此功能很少使用且并未广泛宣传的功能。
即使for arrays in tree.iterate({"pt": uproot.asarray(">f8", pt_buffer),
"eta": uproot.asarray(">f8", eta_buffer)},
outputtype=tuple, entrysteps=10000):
start = int((arrays[0].ctypes.data - buffer.ctypes.data) / buffer.itemsize)
stop = start + len(arrays[0])
array_of_tuples = buffer[start:stop]
print(array_of_tuples)
正在按照称为iterate
的字典填充并向您发送数组,它们还是arrays
记录数组(“元组数组”)的列视图。通过查看原始的buffer
,我们可以看到所需的结构。
但是,连根拔起实际上是用整个购物篮内容填充buffer
,从第一个相关购物篮的开头开始,到最后一个相关购物篮的结尾结束,以覆盖每个子范围:buffer
,{ {1}},[0, 10000)
等。因此,您需要的[10000, 20000)
部分可以在([20000, 30000)
中开始多个条目,并且很可能在buffer
({{ 1}})。由于start != 0
是20000
中第一列的视图,仅包含您想要的条目,因此stop - start != len(buffer)
和arrays[0]
之间的区别是进入{{ 1}}。除以buffer
得到的条目数。结束位置更容易计算。
arrays[0].ctypes.data
的预分配必须足够大,以包括您想要的所有条目以及一篮子中需要删除的所有其他条目。如果篮子的大小不超过buffer.ctypes.data
,则buffer
是安全的。对于给定的buffer.itemsize
,您可以使用以下方法确定任何分支的任何购物篮中最多的条目数:
buffer
显然,这不是这些函数设计的目的:20000
旨在提高性能,以避免重新分配10000
之类的大数组。但是,假设您希望将数据放在列中:tree
和max(branch.basket_numentries(i) for branch in tree.values()
for i in range(branch.numbaskets))
发送到for循环的主体。在上面的内容中,我们另外希望查看格式化为记录数组(“元组数组”)的数据,因此我们实际上是在查看被称为{{1} }。为了明智地做到这一点(避免与该子范围无关的条目),我们必须明确地将其切出,并且库中没有任何函数可以确定该子范围的位置。但是,
asarray
将是这种功能的一般实现。