如何快速获得像root_numpy root2array()输出一样的uproot.iterate()输出

时间:2019-11-02 11:44:39

标签: uproot

array2root返回具有包含分支名称的dtype的元组列表。是否有一种方法可以从uproot.iterate()返回相同类型的格式,而无需在之后进行重塑?

输出应与

的输出相同
array = root2array(['file.root'], treename = 'tree', branches = ['pt', 'eta'])

哪个像np.array([(pt0, eta0), (pt1, eta1), ... dtype=[('pt', '<f4'), ('eta', '<f4')]]

1 个答案:

答案 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_buffereta_buffer的视图,碰巧是交错的,但它们的工作原理与数组一样好。 (我将说明分配buffer而不是仅仅分配20000的原因。)

现在说,您对默认值为10000interpretation的两个分支感兴趣。使用解释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 != 020000中第一列的视图,仅包含您想要的条目,因此stop - start != len(buffer)arrays[0]之间的区别是进入{{ 1}}。除以buffer得到的条目数。结束位置更容易计算。

arrays[0].ctypes.data的预分配必须足够大,以包括您想要的所有条目以及一篮子中需要删除的所有其他条目。如果篮子的大小不超过buffer.ctypes.data,则buffer是安全的。对于给定的buffer.itemsize,您可以使用以下方法确定任何分支的任何购物篮中最多的条目数:

buffer

显然,这不是这些函数设计的目的:20000旨在提高性能,以避免重新分配10000之类的大数组。但是,假设您希望将数据放在列中:treemax(branch.basket_numentries(i) for branch in tree.values() for i in range(branch.numbaskets)) 发送到for循环的主体。在上面的内容中,我们另外希望查看格式化为记录数组(“元组数组”)的数据,因此我们实际上是在查看被称为{{1} }。为了明智地做到这一点(避免与该子范围无关的条目),我们必须明确地将其切出,并且库中没有任何函数可以确定该子范围的位置。但是,

asarray

将是这种功能的一般实现。