Accessing Value from a TTree
Up to now we have used TTree's ability to parse TTree::Draw() expressions and the TBrowser interface. Sometimes it's better to access the values in a script, one by one. There is a traditional way of doing this (TTree::SetBranchAddress() etc) and a new, recommended one: the TTreeReader. That's what we will use later and introduce here. The TTreeReader Concept
The TTree loads entry by entry into memory. You and the TTree need to agree what data the TTree should make available (i.e. for which branches) and what data these branches contain. First, we set up a TTreeReader object that connects our data requests to the TTree:
// Access a TTree called "MyTree" in the file:
TTreeReader reader("MyTree", file);
The TTreeReader Values and Arrays
This reader object can now be used by the data accessors. There are two types: TTreeReaderArray can iterate through collections (std::vector, TClonesArray, TList, MyType[12] - whatever) and TTreeReaderValue that doesn't. You can choose how you access the values - for our tree, all of these might make sense in different contexts:
TTreeReaderValue<float> rvMissingET(reader, "missingET");
// The following needs the definition of the Muon class - which is why accessing
// data member branches is much simpler.
TTreeReaderValue<std::vector<Muon>> rvMuons(reader, "muons");
TTreeReaderArray<float> raMuonPt(reader, "muons.fPt");
// Here, too we would need the definition of the Muon class.
TTreeReaderArray<Muon> raMuons(reader, "muons");
Accessing Data
The TTreeReader checks whether the type you specify is the type that's stored in the branch, i.e. whether it can actually access the data through the reader object. The TTreeReaderValue gets its values like so:
// Loop through all the TTree's entries
while (reader.Next()) {
// behaves like an iterator
float missingET = *rvMissingET;
...
}
A TTreeReaderArray allows you to get the size and access the n-th element:
while (reader.Next()) {
for (int iMuon = 0, nMuons = raMuonPt.GetSize(); iMuon < nMuons; ++iMuon) {
hist->Fill(raMuonPt[iMuon]);
}
}
Of course in C++11 you could also just do
while (reader.Next()) {
for (float pT: raMuonPt) {
hist->Fill(pT);
}
}
We will try all of this out later; you are welcome to write a little script to test this on our TTree.