Как использовать uproot для загрузки ссылочных значений (TRefArray) - PullRequest
1 голос
/ 08 октября 2019

Я пытаюсь использовать uproot, чтобы сделать базовый выбор из выходного файла Delphes .root. Примеры кода Delphhes c ++ циклически перебирают события и обращаются к восстановленным BranchElements, у которых есть методы для доступа к элементам ветви, принадлежащим различным классам.

например, корневой файл содержит <TBranchElement b'Jet' at 0x7fb36526b3c8>, который (на c ++) пример кода Delphes может использовать для получения object=jet->Constituents.At(i) в цикле "for", а затем, если это object равно object->IsA() == Tower::Class, тогда одинзвонит object->P4(), чтобы получить 4momentum. Таким образом, в то время как с помощью выкорчевывания можно получить только два значения по отдельности, в примерах Delphes один использует класс Jet для получения доступа к классу Tower (из которого реконструирован Jet) с использованием метода.

Информация, которую ясм .:

    Jet_size                   (no streamer)              asdtype('>i4')
    Jet                        TStreamerInfo              asdtype('>i4')
    Jet.fUniqueID              TStreamerBasicType         asjagged(asdtype('>u4'))
.
.
.
    Jet.Constituents           TStreamerInfo              asgenobj(SimpleArray(TRefArray))


<TBranchElement b'Jet' at 0x7fb3657825f8>

<TBranchElement b'Jet.Constituents' at 0x7fb47840cba8>

Для выкорчевывания, если кто-либо загружает TBranchElement как массив, то в Jet.Constituents[i] есть только элементы массива, которые являются списками чисел. Как бы я мог загрузить Jet.Constituents так, чтобы он ссылался на значения Tower.PT (или eta, phi и т. Д.), Которые он содержит?

1 Ответ

1 голос
/ 11 октября 2019

Если у вас есть массив TRefs, вы можете использовать их непосредственно как целочисленный индекс для другой коллекции. (См. этот учебник , начиная с In[29], для общего введения в индексирование целочисленными массивами, как в Numpy, так и в Awkward Array.)

То есть, если у вас есть массивTRef, как в в этом примере ,

import uproot
t = uproot.open("issue324.root")["Delphes"]
refs = t["Track.Particle"].array()
refs.id
# <JaggedArray [
#      [752 766 780 ... 1813 1367 1666]
#      ...
#      [745 762 783 ... 1863 1713 1717]]>

дает вам индексы и

pt = t["Particle.PT"].array()

массив, на который вы хотите сослаться, поэтому

pt[refs.id - 1]
# <JaggedArray [
#      [0.7637838 1.1044897 5.463864 ... 4.252923 1.9702696 9.213475]
#      ...
#      [1.2523094 0.37887865 0.7390242 ... 1.0288503 3.4785874 1.804613]]>

выбирает pt интересующие значения (исправляя тот факт, что эти индексы начинаются с 1, а индексы Python начинаются с 0).

Если у вас есть массив TRefArray как в этом примере ,

t["Tower.Particles"].array()
# <ObjectArray [[[1414, 1418, 1471, 1571], [1447], [1572],
#               ...,
#               [864, 1325], [992, 1437], [1262, 1501]]]>

это на самом деле ObjectArray, который генерирует под-массивы из данных по требованию (потому что ROOT не хранит данные с двойной неровностью изначально). Вы можете преобразовать их в собственный JaggedArrays, вызвав для них awkward.fromiter:

import awkward
a = awkward.fromiter(t["Tower.Particles"].array())
# <JaggedArray [[[1414 1418 1471 1571] [1447] [1572] 
#                ...
#                [864 1325] [992 1437] [1262 1501]]]>

, а затем использовать эти дважды зубчатые индексы в любой коллекции с двойной зубчатостью (в которой все числа элементов выстраиваются, какдля коллекции, на которую вы ссылаетесь).

...