Data from branches

This probably is a really simple question but for the life of me I can’t figure it out…

A while ago I learned how to go through a TTree structure and access its information:

file = TFile("muonsBinary.root", "read")
tree = file.Get("tnt")

for entry in tree:
    collision = SimCol()
    collision.m1.SetPtEtaPhiM(entry.pt1, entry.eta1, entry.phi1, 0.1)
    collision.m2.SetPtEtaPhiM(entry.pt2, entry.eta2, entry.phi2, 0.1)
    collision.calcInvMass()
    histo.Fill(collision.invMass)

file.Close()

Now I’m trying to do something similar, except the data I want is under a branch under a larger tree. I naively thought it was essentially the same as getting a tree under a tree, so I did this:

file = TFile("/Users/npolishetty/PycharmProjects/Physics2/mg5/MG5_aMC_v2_9_15_New/ppTOz_zTOmumu_13TeV/Events/run_01/tag_1_delphes_events.root", "read")
tree = file.Get("Delphes")
branch = tree.GetBranch("Muon")

for entry in branch:
    collision = SimCol()
    collision.m1.SetPtEtaPhiM(entry.Muon.PT[0], entry.Muon.Eta[0], entry.Muon.Phi[0], 0.1)
    collision.m2.SetPtEtaPhiM(entry.Muon.PT[1], entry.Muon.Eta[1], entry.Muon.Phi[1], 0.1)
    collision.calcInvMass()
    histo.Fill(collision.invMass)

file.Close()

But I get an error saying the TBranch element is not iterable. If someone could explain it or point me in the right direction of where to look, that’d be great. I’ve tried looking through ROOT manuals, but I can’t seem to find anything for branches.

Thanks in advance.

ROOT Version: 6.26.10

Hi @Revan,

That’s right, AFAIK TBranch objects are not iterable, i.e. after all, what you are iterating over it’s the TTree entries. For each entry in the TTree (that is, the first code excerpt that you posted), you can look at the values in the branches.

Specifically, I think it should work if you just change that by

for entry in tree:

Cheers,
J.

Yeah, that’s what I figured and ended up trying but I ran into issues with “TCloneArray.”
For clarity’s sake, here’s the hierarchy I’m looking at:

I’m trying to access each event under the muon branch so I can get each event’s pt, eta, and phi. However, when I try to do the following:

for entry in tree:
    collision = SimCol()
    collision.m1.SetPtEtaPhiM(entry.Muon.Muon.PT, entry.Muon.Muon.Eta, entry.Muon.Muon.Phi, 0.1)
    collision.m2.SetPtEtaPhiM(entry.Muon.Muon.PT, entry.Muon.Muon.Eta, entry.Muon.Muon.Phi, 0.1)
    collision.calcInvMass()
    histo.Fill(collision.invMass)

(SimCol is a class I made earlier in the script)
I get the following error:

npolishetty@NitoBOT SandboxROOT % python3.9 ROOTRunner3_copy.py
TClass::Init:0: RuntimeWarning: no dictionary for class HepMCEvent is available
TClass::Init:0: RuntimeWarning: no dictionary for class Event is available
TClass::Init:0: RuntimeWarning: no dictionary for class Weight is available
TClass::Init:0: RuntimeWarning: no dictionary for class GenParticle is available
TClass::Init:0: RuntimeWarning: no dictionary for class SortableObject is available
TClass::Init:0: RuntimeWarning: no dictionary for class Track is available
TClass::Init:0: RuntimeWarning: no dictionary for class Tower is available
TClass::Init:0: RuntimeWarning: no dictionary for class Jet is available
TClass::Init:0: RuntimeWarning: no dictionary for class MissingET is available
TClass::Init:0: RuntimeWarning: no dictionary for class Electron is available
TClass::Init:0: RuntimeWarning: no dictionary for class Photon is available
TClass::Init:0: RuntimeWarning: no dictionary for class Muon is available
TClass::Init:0: RuntimeWarning: no dictionary for class ScalarHT is available
Traceback (most recent call last):
  File "/Users/npolishetty/PycharmProjects/SandBoxROOT/ROOTRunner3_copy.py", line 28, in <module>
    collision.m1.SetPtEtaPhiM(entry.Muon.Muon.PT, entry.Muon.Muon.Eta, entry.Muon.Muon.Phi, 0.1)
AttributeError: 'TClonesArray' object has no attribute 'Muon'

Also, I’m aware I’m setting both collision.m1 and collision.m2 to the same data, I’m trying to figure out how to work with that too, as it was a bit clearer which data to use for each particle in the project I worked on earlier.

Hi @Revan,

In regard to these warnings, you will have to load the corresponding dictionary file that provides information for the abovementioned classes.

Accessing a branch whose name contains dots (.) in this way is not supported. Specifically, for the Muon.pt part at the end, Python is parsing it as get an attribute named Muon, then get an attribute named pt.
In this case, you should use the workaround mentioned in Looping tree and getting branch value, but branch has a dot(.) in its name - #6 by etejedor.

Cheers,
J.

1 Like

I know its a bit late, but when I try that solution:

for entry in tree:
    collision = SimCol()
    collision.m1.SetPtEtaPhiM(getattr(entry.Muon, "Muon.PT"), getattr(entry.Muon, "Muon.Eta"), getattr(entry.Muon, "Muon.Phi"), 0.1)
    collision.m2.SetPtEtaPhiM(getattr(entry.Muon, "Muon.PT"), getattr(entry.Muon, "Muon.Eta"), getattr(entry.Muon, "Muon.Phi"), 0.1)
    collision.calcInvMass()
    histo.Fill(collision.invMass)

I end up with the following:

TClass::Init:0: RuntimeWarning: no dictionary for class HepMCEvent is available
TClass::Init:0: RuntimeWarning: no dictionary for class Event is available
TClass::Init:0: RuntimeWarning: no dictionary for class Weight is available
TClass::Init:0: RuntimeWarning: no dictionary for class GenParticle is available
TClass::Init:0: RuntimeWarning: no dictionary for class SortableObject is available
TClass::Init:0: RuntimeWarning: no dictionary for class Track is available
TClass::Init:0: RuntimeWarning: no dictionary for class Tower is available
TClass::Init:0: RuntimeWarning: no dictionary for class Jet is available
TClass::Init:0: RuntimeWarning: no dictionary for class MissingET is available
TClass::Init:0: RuntimeWarning: no dictionary for class Electron is available
TClass::Init:0: RuntimeWarning: no dictionary for class Photon is available
TClass::Init:0: RuntimeWarning: no dictionary for class Muon is available
TClass::Init:0: RuntimeWarning: no dictionary for class ScalarHT is available
Traceback (most recent call last):
  File "/Users/npolishetty/PycharmProjects/SandBoxROOT/ROOTRunner3_copy.py", line 28, in <module>
    collision.m1.SetPtEtaPhiM(getattr(entry.Muon, "Muon.PT"), getattr(entry.Muon, "Muon.Eta"), getattr(entry.Muon, "Muon.Phi"), 0.1)
AttributeError: 'TClonesArray' object has no attribute 'Muon.PT'

Any chance that you can share the muonsBinary.root file so that I could try to make this work?

If you want, I can send the files, but I ended up getting it to work anyway. I found out the way I was traversing before was really simplified, and now I use this:

file = TFile("/Users/npolishetty/PycharmProjects/Physics2/mg5/MG5_aMC_v2_9_15_New/ppTOz_zTOmumu_13TeV/Events/run_01/tag_1_delphes_events.root", "read")
tree = file.Get("Delphes")
numEvents = tree.GetEntries()

for i in range(numEvents):
    entry = tree.GetEntry(i)
    collision = SimCol()
    for a in range(2):
        pt = tree.GetLeaf("Muon.PT").GetValue(a)
        eta = tree.GetLeaf("Muon.Eta").GetValue(a)
        phi = tree.GetLeaf("Muon.Phi").GetValue(a)
        collision.muons.append(TLorentzVector())
        collision.muons[-1].SetPtEtaPhiM(pt, eta, phi, 0.1)
    collision.calcInvMass()
    histo.Fill(collision.invMass)

Now the trick is to just replace the 2 in the nested for loop with however many muons are actually in each event.

1 Like

Hi @Revan,

I’m glad to hear that you finally fixed it! Then, I’ll mark the topic as solved.

Cheers,
J.