PyROOT writing a set nested arrays

How does one use PyROOT to write a set of nested arrays with variable sizes? Is there an easy way as this is a common form in which data comes by?

I’ve tried recreating the branch everytime I iterate through the next set of nested arrays, using the length of it as the initializer for the branch size.

That’s a TTree question, not a PyROOT one. Might want to add some code to elicit an answer.

Hi Wlav,

I’ve attached an example of my code.

Essentially I’m trying to read data from jet cluster and toss events depending on the ratio of the jet pt. Then i’m trying to save them into a new root file which has the same format as the original so that it can be used in an another processing script. If I print out the original array format its like this. Please let me know if you need me to clarify things further.

[ array([ 1.18108533e+03, 9.04519287e+02, 3.02184497e+03,
1.23331250e+03, 4.84120697e+02, 4.28273499e+02,
1.82929712e+03, 7.83793579e+02, 1.61371826e+03,
5.18673193e+03, 2.20749536e+03, 5.80503357e+02,
2.04210571e+03, 4.70369720e+02, 4.28637891e+03,
1.39147302e+03, 5.77580908e+03, 1.47646942e+02,
8.06518066e+02, 4.67209961e+02, 5.18042053e+02,
1.89679260e+03, 1.18152222e+03, 7.88970764e+02,
6.42265076e+02, 5.77979553e+02, 2.48790527e+03,
2.90703217e+02, 4.10976904e+03, 1.98431555e+03,
2.00360913e+03, 2.54040869e+03, 1.16357837e+03,
3.36290576e+03, 5.99869263e+02, 8.91479675e+02,
2.18348901e+03, 5.91977722e+02, 1.90555939e+02,
2.48055444e+03, 5.88423218e+02, 1.27246399e+03,
7.86266052e+02, 2.87363678e+02, 1.04793005e+03,
5.77161865e+02, 6.40477417e+02, 3.56781342e+02,
3.56315063e+02, 4.83562500e+02, 7.90638123e+02,
9.00685669e+02, 9.04517395e+02, 2.53372757e+02,
5.39737122e+02, 1.72372852e+04, 4.67898750e+04,
3.61929625e+05], dtype=float32)
array([ 1.19759045e+03, 1.39756091e+03, 5.41287109e+02,
3.99256897e+02, 3.74767456e+02, 2.71507690e+03,
1.06788232e+03, 2.21911328e+03, 3.04491333e+03,
1.16833923e+03, 1.93684058e+03, 4.11025360e+02,
2.86714993e+01, 1.05827576e+02, 3.63362158e+03,
1.40520044e+03, 1.02330463e+03, 3.60290031e+01,
2.88414819e+03, 2.34773605e+02, 1.14307263e+03,
4.20900078e+01, 1.24197278e+03, 1.73647049e+02,
1.85284351e+03, 5.69345825e+02, 8.95068054e+02,
1.13068335e+03, 2.19429581e+02, 5.12877808e+02,
9.78123108e+02, 4.56866455e+02, 1.02758936e+03,
4.07080139e+02, 5.25493103e+02, 2.40770630e+03,
2.77651855e+02, 4.44729889e+02, 2.10584473e+03,
1.28448315e+03, 1.39501453e+03, 1.88084488e+01,
1.46668030e+03, 1.25668030e+03, 1.96674451e+03,
8.60963562e+02, 1.46088257e+03, 5.42577515e+02,
1.50466232e+02, 6.08737915e+02, 1.25062923e+01,
3.52039307e+03, 3.25381763e+03, 5.46108887e+02,
1.13470032e+03, 1.22876660e+03, 1.25030530e+03,
4.41629004e+03, 4.85909277e+03, 1.22660669e+03,
4.78635864e+02, 1.14753479e+03, 9.92383606e+02,
5.29895752e+02, 1.95257336e+03, 3.18306738e+04,
3.27122969e+04, 2.31173859e+05], dtype=float32)

EventsTossExample.py (1.9 KB)

Arguably, if you go root2array from TTree to multi-dim array, and you want to write the same original format back, array2root should be your friend, no?

(I haven’t tried, as your code relies on local files.)

Yes, i tried going a different route, whereby instead of creating a new array and then filling it, I would just remove the elements from the original array and then use array2root to save it. However I get an error that I believe has to do with the object type of the array.

All i did to try it was to save the original array by using

array2root(QCD_clus_E, “deletetest.root”, mode = “recreate”)

File “DeleteTest.py”, line 43, in
array2root(QCD_clus_E,“deletetest.root”, mode = “recreate”)
File “/usr/local/lib/python2.7/dist-packages/root_numpy/_tree.py”, line 617, in array2root
_librootnumpy.array2root(arr, filename, treename, mode)
File “root_numpy/src/tree.pyx”, line 704, in _librootnumpy.array2root (root_numpy/src/_librootnumpy.cpp:704)
File “root_numpy/src/tree.pyx”, line 677, in _librootnumpy.array2tree (root_numpy/src/_librootnumpy.cpp:677)
File “root_numpy/src/tree.pyx”, line 649, in _librootnumpy.array2tree (root_numpy/src/_librootnumpy.cpp:649)

forgot the last line of the error

TypeError: object of type ‘NoneType’ has no len()

What does ‘removing’ entail? Looks like what you’d really want is remove the elements, not the nested array (i.e. leave an array of size 0).

No, I actually want to remove the nested arrays. so if the arrays are as such A = [ [1,2,3], [4, 5, 6], [7, 8, 9] ] then after a random removal of the second array would leave A = [ [1, 2, 3], [7, 8, 9] ]. However I managed to sort of solve my problem, using the example ‘21.1.9.2 Writing a Tree’ in the user guide. The next issue is that I actually need them to be of type std::vector for my later script to work as it uses some of the vector member functions. Is there a simple way to do this?

I tried using:
cluster_E_entry = ROOT.vector(‘double’)()
Tree.Branch(‘clus_size’, clus_size, ‘clus_size/I’)
Tree.Branch(‘clus_E’, cluster_E_entry,‘clus_E[clus_size]’)

But it either does not fill the vectors or there’s garbage values.

Don’t decompose the vector, just store it wholesale:

cluster_E_entry = ROOT.vector('double')()
Tree.Branch('clus_E', cluster_E_entry)

Ok, How do I then fill this vector?

I’ve been doing something along the lines of

for j in range(length(jet_entries)):
clus_size[0] = length[j]
for k in range(clus_size[0]):
cluster_E_entry = df[0][j][k] # Panda dataframe that contains the original data.

Tree.Fill()

cluster_E_entry.push_back(df[0][j][k])

Hi wlav,

Thanks, even though this did what I wanted, it still did not work with the later script. It’s was quite a strange occurence since all the data was the same and so were the types, but it still wasn’t working. So the approach we took was to copy the original branch, and then write that to the new tree. I’ve attached the code of how we did it. Thanks a lot for your help!

EventsTossFinal.py (5.3 KB)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.