GetEntryWithIndex(), SetBranchAddress(), and new trees in

Hello, I’d like some help accessing entries which correspond across across all five, and I’d like to do it without waiting for nested loops to run.

I have 5 ntuples in one file. Their entries correspond to the passage of particle through each of the detectors the ntuples represent. I’m only interested in the particles which can be found in all five of these. So, to keep it short, I store these tuples in a dictionary keyed by their names:

dumtuple = ROOT.TNtuple() # Just need an instance of this class, it seems.

print "Looping over input file contents, getting trees."
for key in ROOT.gDirectory.GetListOfKeys():
if dumtuple.Class() == key.ReadObj().Class():
tuples[key.GetName()] = key.ReadObj()

I built an index for each of these five ntuples:

for name, tuple in tuples.iteritems():
print “Building an index for “,name,”…”,
tuple.BuildIndex(“EventID”,“TrackID”)

…and then I can start by looping over the tuple with the smallest list, the one at the end of the particles’ path.

for ds_track in tuples[“Last”]:
(event, track) = (int(ds_track.EventID), int(ds_track.TrackID))

…but my difficulty is that while I can ‘get’ the entry I want in the other NTuples:

tuples[“Det1”].GetEntryWithIndex(event,track)

…yet I still don’t have access to its data.

Maybe all I want to ask is: How do I use SetBranchAddress() in python?

I have a very similar problem with how to make a new tree in Python, since that’s where I want to put some of these data from the these five trees: into a new one.

Many thanks,
-St. John

Hi,

can’t say I’m following you … but SetBranchAddress simply works as expected for objects (i.e. when passing the object its address is taken correctly). Just make sure to keep them alive (I like to make them private members of the tree they belong to). For builtin types such as int, double, etc., you need an array or a struct of which they are data members. The reason being that you need something of which an address can be taken and handed to C++. See http://wlav.web.cern.ch/wlav/pyroot/tpytree.html for examples.

Cheers,
Wim

Hi again,

Thanks, Wim, GetEntryWithIndex(), SetBranchAddress(), and new trees in helped a lot. In case it will help out someone out there, here’s what was needed:

To get values out of my five ntuples (named “Det1”, “Det2,”, “Det1,”, “Det4,”,and “Argu12”), I had ROOT make a struct, with one element for each leaf of each tree. Then I hooked it to all five TTrees:

#Invent a type of struct for holding stuff from the tree
ROOT.gROOT.ProcessLine(“struct treestuff { Int_t EventID; Int_t TrackID;
Float_t x1; Float_t y1; Float_t z1; Float_t t1; Float_t Px1; Float_t Py1; Float_t Pz1; Float_t PDGid1; Float_t ParentID1;
Float_t x2; Float_t y2; Float_t z2; Float_t t2; Float_t Px2; Float_t Py2; Float_t Pz2; Float_t PDGid2; Float_t ParentID2;
Float_t x3; Float_t y3; Float_t z3; Float_t t3; Float_t Px3; Float_t Py3; Float_t Pz3; Float_t PDGid3; Float_t ParentID3;
Float_t x4; Float_t y4; Float_t z4; Float_t t4; Float_t Px4; Float_t Py4; Float_t Pz4; Float_t PDGid4; Float_t ParentID4;
Float_t xT; Float_t yT; Float_t zT; Float_t tT; Float_t PxT; Float_t PyT; Float_t PzT; Float_t PDGidT; Float_t ParentIDT;
}” )

#Make one of them to use
pyTree = ROOT.treestuff()

#Hook the variables to their branches:
tuples[“Argu12”].SetBranchAddress( “EventID”,ROOT.AddressOf(pyTree,‘EventID’))
tuples[“Argu12”].SetBranchAddress( “TrackID”,ROOT.AddressOf(pyTree,‘TrackID’))

vars = (‘x’,‘y’,‘z’,‘t’,‘Px’,‘Py’,‘Pz’,‘PDGid’,‘ParentID’)
dets = (‘1’,‘2’,‘3’,‘4’,‘T’)
for var in vars:
for det in dets:
if det == ‘T’:
tuple = tuples[“Argu12”]
else:
tuple = tuples[“Det”+det]
tuple.SetBranchAddress(var, ROOT.AddressOf(pyTree,var+det))

…I also made my new tree,

The Output: A file with a tree in it.

outfile = ROOT.TFile(“MergedTree_gt1GeV.root”,“RECREATE”)
newTree = ROOT.TTree(“EventTree”,“EventTree”)

Two important branches to include:

EventID_p = array( ‘i’, [ 0 ] )
TrackID_p = array( ‘i’, [ 0 ] )
newTree.Branch(“EventID”,EventID_p,“EventID/I”)
newTree.Branch(“TrackID”,TrackID_p,“TrackID/I”)

…and all the others we want:

pointers = {}
for var in vars:
for det in dets:
name = var+det
pointers[name] = array( ‘d’, [ 0 ] )
newTree.Branch(name,pointers[name],name+"/d")

…where the tricky part is that dictionary called “pointers”, which I filled with single-entry arrays (!) of the right class type. That satisfied the pointer-to-a-variable-of-the-right-type requirement for the arguments of TTree::Branch().

Finally, my loop over one tree, get corresponding entries from all of the other four (if they exist), and stash all the variables in the new tree:

for ds_track in tuples[“Argu”+angle]:
## Unique identifiers for this track:
(event, track) = (int(ds_track.EventID), int(ds_track.TrackID))

if ds_track.Pz < 1000. : continue

Det1EntryNum = tuples["Det1"].GetEntryWithIndex(event,track)
Det2EntryNum = tuples["Det2"].GetEntryWithIndex(event,track)
Det3EntryNum = tuples["Det3"].GetEntryWithIndex(event,track)
Det4EntryNum = tuples["Det4"].GetEntryWithIndex(event,track)

## Ignore tracks not present in all detectors upstream of here:
if Det1EntryNum == -1 or Det2EntryNum == -1 or \
   Det3EntryNum == -1 or Det4EntryNum == -1 : continue

## What I hate about this is that the newTree looks completely uninvolved.
## Of course, it's tied in above, at newTree.Branch(name,pointers[name],name+"/f")
EventID_p[0] = event
TrackID_p[0] = track
for name, pointer in pointers.iteritems():
    ## getattr can return the value of pyTree's member with the right name.
    pointer[0] = getattr(pyTree,name)
newTree.Fill()

Thanks for pointing the way,
-jmsj