Logo ROOT   6.12/06
Reference Guide
TTreeReader.cxx
Go to the documentation of this file.
1 // @(#)root/treeplayer:$Id$
2 // Author: Axel Naumann, 2011-09-21
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers and al. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TTreeReader.h"
13 
14 #include "TChain.h"
15 #include "TDirectory.h"
16 #include "TEntryList.h"
17 #include "TTreeReaderValue.h"
18 
19 /** \class TTreeReader
20  TTreeReader is a simple, robust and fast interface to read values from a TTree,
21  TChain or TNtuple.
22 
23  It uses `TTreeReaderValue<T>` and `TTreeReaderArray<T>` to access the data.
24 
25  Example code can be found in
26  tutorials/tree/hsimpleReader.C and tutorials/trees/h1analysisTreeReader.h and
27  tutorials/trees/h1analysisTreeReader.C for a TSelector.
28 
29  You can generate a skeleton of `TTreeReaderValue<T>` and `TTreeReaderArray<T>` declarations
30  for all of a tree's branches using `TTree::MakeSelector()`.
31 
32  Roottest contains an
33  <a href="http://root.cern.ch/gitweb?p=roottest.git;a=tree;f=root/tree/reader;hb=HEAD">example</a>
34  showing the full power.
35 
36 A simpler analysis example - the one from the tutorials - can be found below:
37 it histograms a function of the px and py branches.
38 
39 ~~~{.cpp}
40 // A simple TTreeReader use: read data from hsimple.root (written by hsimple.C)
41 
42 #include "TFile.h
43 #include "TH1F.h
44 #include "TTreeReader.h
45 #include "TTreeReaderValue.h
46 
47 void hsimpleReader() {
48  // Create a histogram for the values we read.
49  TH1F("h1", "ntuple", 100, -4, 4);
50 
51  // Open the file containing the tree.
52  TFile *myFile = TFile::Open("$ROOTSYS/tutorials/hsimple.root");
53 
54  // Create a TTreeReader for the tree, for instance by passing the
55  // TTree's name and the TDirectory / TFile it is in.
56  TTreeReader myReader("ntuple", myFile);
57 
58  // The branch "px" contains floats; access them as myPx.
59  TTreeReaderValue<Float_t> myPx(myReader, "px");
60  // The branch "py" contains floats, too; access those as myPy.
61  TTreeReaderValue<Float_t> myPy(myReader, "py");
62 
63  // Loop over all entries of the TTree or TChain.
64  while (myReader.Next()) {
65  // Just access the data as if myPx and myPy were iterators (note the '*'
66  // in front of them):
67  myHist->Fill(*myPx + *myPy);
68  }
69 
70  myHist->Draw();
71 }
72 ~~~
73 
74 A more complete example including error handling and a few combinations of
75 TTreeReaderValue and TTreeReaderArray would look like this:
76 
77 ~~~{.cpp}
78 #include <TFile.h>
79 #include <TH1.h>
80 #include <TTreeReader.h>
81 #include <TTreeReaderValue.h>
82 #include <TTreeReaderArray.h>
83 
84 #include "TriggerInfo.h"
85 #include "Muon.h"
86 #include "Tau.h"
87 
88 #include <vector>
89 #include <iostream>
90 
91 bool CheckValue(ROOT::Internal::TTreeReaderValueBase& value) {
92  if (value->GetSetupStatus() < 0) {
93  std::cerr << "Error " << value->GetSetupStatus()
94  << "setting up reader for " << value->GetBranchName() << '\n';
95  return false;
96  }
97  return true;
98 }
99 
100 
101 // Analyze the tree "MyTree" in the file passed into the function.
102 // Returns false in case of errors.
103 bool analyze(TFile* file) {
104  // Create a TTreeReader named "MyTree" from the given TDirectory.
105  // The TTreeReader gives access to the TTree to the TTreeReaderValue and
106  // TTreeReaderArray objects. It knows the current entry number and knows
107  // how to iterate through the TTree.
108  TTreeReader reader("MyTree", file);
109 
110  // Read a single float value in each tree entries:
111  TTreeReaderValue<float> weight(reader, "event.weight");
112 
113  // Read a TriggerInfo object from the tree entries:
114  TTreeReaderValue<TriggerInfo> triggerInfo(reader, "triggerInfo");
115 
116  //Read a vector of Muon objects from the tree entries:
117  TTreeReaderValue<std::vector<Muon>> muons(reader, "muons");
118 
119  //Read the pT for all jets in the tree entry:
120  TTreeReaderArray<double> jetPt(reader, "jets.pT");
121 
122  // Read the taus in the tree entry:
123  TTreeReaderArray<Tau> taus(reader, "taus");
124 
125 
126  // Now iterate through the TTree entries and fill a histogram.
127 
128  TH1F("hist", "TTreeReader example histogram", 10, 0., 100.);
129 
130  while (reader.Next()) {
131  if (!CheckValue(weight)) return false;
132  if (!CheckValue(triggerInfo)) return false;
133  if (!CheckValue(muons)) return false;
134  if (!CheckValue(jetPt)) return false;
135  if (!CheckValue(taus)) return false;
136 
137  // Access the TriggerInfo object as if it's a pointer.
138  if (!triggerInfo->hasMuonL1())
139  continue;
140 
141  // Ditto for the vector<Muon>.
142  if (!muons->size())
143  continue;
144 
145  // Access the jetPt as an array, whether the TTree stores this as
146  // a std::vector, std::list, TClonesArray or Jet* C-style array, with
147  // fixed or variable array size.
148  if (jetPt.GetSize() < 2 || jetPt[0] < 100)
149  continue;
150 
151  // Access the array of taus.
152  if (!taus.IsEmpty()) {
153  // Access a float value - need to dereference as TTreeReaderValue
154  // behaves like an iterator
155  float currentWeight = *weight;
156  for (const Tau& tau: taus) {
157  hist->Fill(tau.eta(), currentWeight);
158  }
159  }
160  } // TTree entry / event loop
161 }
162 ~~~
163 */
164 
166 
167 using namespace ROOT::Internal;
168 
169 // Provide some storage for the poor little symbol.
170 constexpr const char * const TTreeReader::fgEntryStatusText[TTreeReader::kEntryBeyondEnd + 1];
171 
172 ////////////////////////////////////////////////////////////////////////////////
173 /// Access data from tree.
174 
175 TTreeReader::TTreeReader(TTree* tree, TEntryList* entryList /*= nullptr*/):
176  fTree(tree),
177  fEntryList(entryList)
178 {
179  if (!fTree) {
180  Error("TTreeReader", "TTree is NULL!");
181  } else {
182  Initialize();
183  }
184 }
185 
186 ////////////////////////////////////////////////////////////////////////////////
187 /// Access data from the tree called keyname in the directory (e.g. TFile)
188 /// dir, or the current directory if dir is NULL. If keyname cannot be
189 /// found, or if it is not a TTree, IsZombie() will return true.
190 
191 TTreeReader::TTreeReader(const char* keyname, TDirectory* dir, TEntryList* entryList /*= nullptr*/):
192  fEntryList(entryList)
193 {
194  if (!dir) dir = gDirectory;
195  dir->GetObject(keyname, fTree);
196  Initialize();
197 }
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 /// Tell all value readers that the tree reader does not exist anymore.
201 
203 {
204  for (std::deque<ROOT::Internal::TTreeReaderValueBase*>::const_iterator
205  i = fValues.begin(), e = fValues.end(); i != e; ++i) {
206  (*i)->MarkTreeReaderUnavailable();
207  }
208  delete fDirector;
209  fProxies.SetOwner();
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// Initialization of the director.
214 
216 {
217  fEntry = -1;
218  if (!fTree) {
219  MakeZombie();
222  return;
223  }
224 
225  ResetBit(kZombie);
226  if (fTree->InheritsFrom(TChain::Class())) {
228  }
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// Set the range of entries to be loaded by `Next()`; end will not be loaded.
234 ///
235 /// If end <= begin, `end` is ignored (set to `-1`) and only `begin` is used.
236 /// Example:
237 ///
238 /// ~~~ {.cpp}
239 /// reader.SetEntriesRange(3, 5);
240 /// while (reader.Next()) {
241 /// // Will load entries 3 and 4.
242 /// }
243 /// ~~~
244 ///
245 /// \param beginEntry The first entry to be loaded by `Next()`.
246 /// \param endEntry The entry where `Next()` will return kFALSE, not loading it.
247 
249 {
250  if (beginEntry < 0)
251  return kEntryNotFound;
252  // Complain if the entries number is larger than the tree's / chain's / entry
253  // list's number of entries, unless it's a TChain and "max entries" is
254  // uninitialized (i.e. TTree::kMaxEntries).
255  if (beginEntry >= GetEntries(false) && !(IsChain() && GetEntries(false) == TTree::kMaxEntries)) {
256  Error("SetEntriesRange()", "first entry out of range 0..%lld", GetEntries(false));
257  return kEntryNotFound;
258  }
259 
260  if (endEntry > beginEntry)
261  fEndEntry = endEntry;
262  else
263  fEndEntry = -1;
264  if (beginEntry - 1 < 0)
265  Restart();
266  else {
267  EEntryStatus es = SetEntry(beginEntry - 1);
268  if (es != kEntryValid) {
269  Error("SetEntriesRange()", "Error setting first entry %lld: %s",
270  beginEntry, fgEntryStatusText[(int)es]);
271  return es;
272  }
273  }
274  return kEntryValid;
275 }
276 
278  fDirector->SetTree(nullptr);
279  fDirector->SetReadEntry(-1);
280  fProxiesSet = false; // we might get more value readers, meaning new proxies.
281  fEntry = -1;
282 }
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// Returns the number of entries of the TEntryList if one is provided, else
286 /// of the TTree / TChain, independent of a range set by SetEntriesRange().
287 ///
288 /// \param force If `IsChain()` and `force`, determines whether all TFiles of
289 /// this TChain should be opened to determine the exact number of entries
290 /// of the TChain. If `!IsChain()`, `force` is ignored.
291 
293  if (fEntryList)
294  return fEntryList->GetN();
295  if (!fTree)
296  return -1;
297  if (force)
298  return fTree->GetEntries();
299  return fTree->GetEntriesFast();
300 }
301 
302 
303 
304 ////////////////////////////////////////////////////////////////////////////////
305 /// Load an entry into the tree, return the status of the read.
306 /// For chains, entry is the global (i.e. not tree-local) entry number, unless
307 /// `local` is `true`, in which case `entry` specifies the entry number within
308 /// the current tree. This is needed for instance for TSelector::Process().
309 
311 {
312  if (!fTree || !fDirector) {
314  fEntry = -1;
315  return fEntryStatus;
316  }
317 
318  if (fTree->GetEntryList() && !TestBit(kBitHaveWarnedAboutEntryListAttachedToTTree)) {
319  Warning("SetEntryBase()",
320  "The TTree / TChain has an associated TEntryList. "
321  "TTreeReader ignores TEntryLists unless you construct the TTreeReader passing a TEntryList.");
323  }
324 
325  fEntry = entry;
326 
327  Long64_t entryAfterList = entry;
328  if (fEntryList) {
329  if (entry >= fEntryList->GetN()) {
330  // Passed the end of the chain, Restart() was not called:
331  // don't try to load entries anymore. Can happen in these cases:
332  // while (tr.Next()) {something()};
333  // while (tr.Next()) {somethingelse()}; // should not be calling somethingelse().
335  return fEntryStatus;
336  }
337  if (entry >= 0) entryAfterList = fEntryList->GetEntry(entry);
338  if (local && IsChain()) {
339  // Must translate the entry list's entry to the current TTree's entry number.
340  local = kFALSE;
341  }
342  }
343 
344  if (fProxiesSet && fDirector && fDirector->GetReadEntry() == -1
345  && fMostRecentTreeNumber != -1) {
346  // Passed the end of the chain, Restart() was not called:
347  // don't try to load entries anymore. Can happen in these cases:
348  // while (tr.Next()) {something()};
349  // while (tr.Next()) {somethingelse()}; // should not be calling somethingelse().
351  return fEntryStatus;
352  }
353 
354  Int_t treeNumberBeforeLoadTree = fTree->GetTreeNumber();
355 
356  TTree* treeToCallLoadOn = local ? fTree->GetTree() : fTree;
357  Long64_t loadResult = treeToCallLoadOn->LoadTree(entryAfterList);
358 
359  if (loadResult == -2) {
360  fDirector->SetTree(nullptr);
362  return fEntryStatus;
363  }
364 
365  if (fMostRecentTreeNumber != treeNumberBeforeLoadTree) {
366  // This can happen if someone switched trees behind us.
367  // Likely cause: a TChain::LoadTree() e.g. from TTree::Process().
368  // This means that "local" should be set!
369 
370  if (fTree->GetTreeNumber() != treeNumberBeforeLoadTree) {
371  // we have switched trees again, which means that "local" was not set!
372  // There are two entities switching trees which is bad.
373  R__ASSERT(!local && "Logic error - !local but tree number changed?");
374  Warning("SetEntryBase()",
375  "The current tree in the TChain %s has changed (e.g. by TTree::Process) "
376  "even though TTreeReader::SetEntry() was called, which switched the tree "
377  "again. Did you mean to call TTreeReader::SetLocalEntry()?",
378  fTree->GetName());
379  }
380  }
381 
382  if (fDirector->GetTree() != fTree->GetTree()
383  || fMostRecentTreeNumber != fTree->GetTreeNumber()) {
384  fDirector->SetTree(fTree->GetTree());
385  if (fProxiesSet) {
386  for (auto value: fValues) {
387  value->NotifyNewTree(fTree->GetTree());
388  }
389  }
390  }
391 
392  fMostRecentTreeNumber = fTree->GetTreeNumber();
393 
394  if (!fProxiesSet) {
395  // Tell readers we now have a tree.
396  // fValues gets insertions during this loop (when parameterized arrays are read),
397  // invalidating iterators. Use old-school counting instead.
398  for (size_t i = 0; i < fValues.size(); ++i) {
400  reader->CreateProxy();
401 
402  if (!reader->GetProxy()){
404  return fEntryStatus;
405  }
406  }
407  // If at least one proxy was there and no error occurred, we assume the proxies to be set.
408  fProxiesSet = !fValues.empty();
409  }
410 
411  if (fEndEntry >= 0 && entry >= fEndEntry) {
413  return fEntryStatus;
414  }
415  fDirector->SetReadEntry(loadResult);
417  return fEntryStatus;
418 }
419 
420 ////////////////////////////////////////////////////////////////////////////////
421 /// Set (or update) the which tree to read from. `tree` can be
422 /// a TTree or a TChain.
423 
424 void TTreeReader::SetTree(TTree* tree, TEntryList* entryList /*= nullptr*/)
425 {
426  fTree = tree;
427  fEntryList = entryList;
428  fEntry = -1;
429 
430  if (fTree) {
431  ResetBit(kZombie);
432  if (fTree->InheritsFrom(TChain::Class())) {
434  }
435  }
436 
437  if (!fDirector) {
438  Initialize();
439  }
440  else {
442  fDirector->SetReadEntry(-1);
443  // Distinguish from end-of-chain case:
445  }
446 }
447 
448 ////////////////////////////////////////////////////////////////////////////////
449 /// Set (or update) the which tree to read from, passing the name of a tree in a
450 /// directory.
451 ///
452 /// \param keyname - name of the tree in `dir`
453 /// \param dir - the `TDirectory` to load `keyname` from (or gDirectory if `nullptr`)
454 /// \param entryList - the `TEntryList` to attach to the `TTreeReader`.
455 
456 void TTreeReader::SetTree(const char* keyname, TDirectory* dir, TEntryList* entryList /*= nullptr*/)
457 {
458  TTree* tree = nullptr;
459  if (!dir)
460  dir = gDirectory;
461  dir->GetObject(keyname, tree);
462  SetTree(tree, entryList);
463 }
464 
465 ////////////////////////////////////////////////////////////////////////////////
466 /// Add a value reader for this tree.
467 
469 {
470  if (fProxiesSet) {
471  Error("RegisterValueReader",
472  "Error registering reader for %s: TTreeReaderValue/Array objects must be created before the call to Next() / SetEntry() / SetLocalEntry(), or after TTreeReader::Restart()!",
473  reader->GetBranchName());
474  return false;
475  }
476  fValues.push_back(reader);
477  return true;
478 }
479 
480 ////////////////////////////////////////////////////////////////////////////////
481 /// Remove a value reader for this tree.
482 
484 {
485  std::deque<ROOT::Internal::TTreeReaderValueBase*>::iterator iReader
486  = std::find(fValues.begin(), fValues.end(), reader);
487  if (iReader == fValues.end()) {
488  Error("DeregisterValueReader", "Cannot find reader of type %s for branch %s", reader->GetDerivedTypeName(), reader->fBranchName.Data());
489  return;
490  }
491  fValues.erase(iReader);
492 }
the tree does not exist
Definition: TTreeReader.h:126
long long Long64_t
Definition: RtypesCore.h:69
virtual Long64_t GetN() const
Definition: TEntryList.h:75
TTreeReader is a simple, robust and fast interface to read values from a TTree, TChain or TNtuple...
Definition: TTreeReader.h:42
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:139
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
std::deque< ROOT::Internal::TTreeReaderValueBase * > fValues
readers that use our director
Definition: TTreeReader.h:246
#define R__ASSERT(e)
Definition: TError.h:96
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Long64_t fEndEntry
The end of the entry loop.
Definition: TTreeReader.h:254
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
THashTable fProxies
attached ROOT::TNamedBranchProxies; owned
Definition: TTreeReader.h:247
Bool_t RegisterValueReader(ROOT::Internal::TTreeReaderValueBase *reader)
Add a value reader for this tree.
EEntryStatus SetEntryBase(Long64_t entry, Bool_t local)
Load an entry into the tree, return the status of the read.
void Class()
Definition: Class.C:29
the tree entry number does not exist
Definition: TTreeReader.h:127
object ctor failed
Definition: TObject.h:79
EEntryStatus fEntryStatus
status of most recent read request
Definition: TTreeReader.h:243
EEntryStatus SetEntriesRange(Long64_t beginEntry, Long64_t endEntry)
Sets the entry that Next() will stop iteration on.
TEntryList * fEntryList
entry list to be used
Definition: TTreeReader.h:242
ROOT::Internal::TBranchProxyDirector * fDirector
proxying director, owned
Definition: TTreeReader.h:245
Bool_t fProxiesSet
True if the proxies have been set, false otherwise.
Definition: TTreeReader.h:255
Long64_t GetEntries(Bool_t force) const
Returns the number of entries of the TEntryList if one is provided, else of the TTree / TChain...
~TTreeReader()
Tell all value readers that the tree reader does not exist anymore.
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual Long64_t GetEntry(Int_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next()...
Definition: TEntryList.cxx:657
EEntryStatus SetEntry(Long64_t entry)
Set the next entry (or index of the TEntryList if that is set).
Definition: TTreeReader.h:179
const Bool_t kFALSE
Definition: RtypesCore.h:88
TTreeReader()=default
void Restart()
Restart a Next() loop from entry 0 (of TEntryList index 0 of fEntryList is set).
#define ClassImp(name)
Definition: Rtypes.h:359
Describe directory structure in memory.
Definition: TDirectory.h:34
TTree * fTree
tree that&#39;s read
Definition: TTreeReader.h:241
void Initialize()
Initialization of the director.
the tree had a TEntryList and we have warned about that
Definition: TTreeReader.h:238
void DeregisterValueReader(ROOT::Internal::TTreeReaderValueBase *reader)
Remove a value reader for this tree.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
Definition: TRolke.cxx:630
problem reading dictionary info from tree
Definition: TTreeReader.h:130
our tree is a chain
Definition: TTreeReader.h:237
Bool_t IsChain() const
Definition: TTreeReader.h:159
Long64_t fEntry
Current (non-local) entry of fTree or of fEntryList if set.
Definition: TTreeReader.h:249
static constexpr const char *const fgEntryStatusText[kEntryBeyondEnd+1]
Definition: TTreeReader.h:134
void MakeZombie()
Definition: TObject.h:49
Definition: tree.py:1
#define gDirectory
Definition: TDirectory.h:213
void ResetBit(UInt_t f)
Definition: TObject.h:171
void SetTree(TTree *tree, TEntryList *entryList=nullptr)
Set (or update) the which tree to read from.
Int_t fMostRecentTreeNumber
TTree::GetTreeNumber() of the most recent tree.
Definition: TTreeReader.h:244
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:25
static constexpr Long64_t kMaxEntries
Definition: TTree.h:206
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
last entry loop has reached its end
Definition: TTreeReader.h:131