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.
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
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.
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'
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.