Logo ROOT   6.08/07
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 "TTreeReaderValue.h"
17 
18 /** \class TTreeReader
19  TTreeReader is a simple, robust and fast interface to read values from a TTree,
20  TChain or TNtuple.
21 
22  It uses TTreeReaderValue<T> and TTreeReaderArray<T> to access the data.
23 
24  Example code can be found in
25  tutorials/tree/hsimpleReader.C and tutorials/trees/h1analysisTreeReader.h and
26  tutorials/trees/h1analysisTreeReader.C for a TSelector.
27 
28  Roottest contains an
29  <a href="http://root.cern.ch/gitweb?p=roottest.git;a=tree;f=root/tree/reader;hb=HEAD">example</a>
30  showing the full power.
31 
32 A simpler analysis example - the one from the tutorials - can be found below:
33 it histograms a function of the px and py branches.
34 
35 ~~~{.cpp}
36 // A simple TTreeReader use: read data from hsimple.root (written by hsimple.C)
37 
38 #include "TFile.h
39 #include "TH1F.h
40 #include "TTreeReader.h
41 #include "TTreeReaderValue.h
42 
43 void hsimpleReader() {
44  // Create a histogram for the values we read.
45  TH1F("h1", "ntuple", 100, -4, 4);
46 
47  // Open the file containing the tree.
48  TFile *myFile = TFile::Open("$ROOTSYS/tutorials/hsimple.root");
49 
50  // Create a TTreeReader for the tree, for instance by passing the
51  // TTree's name and the TDirectory / TFile it is in.
52  TTreeReader myReader("ntuple", myFile);
53 
54  // The branch "px" contains floats; access them as myPx.
55  TTreeReaderValue<Float_t> myPx(myReader, "px");
56  // The branch "py" contains floats, too; access those as myPy.
57  TTreeReaderValue<Float_t> myPy(myReader, "py");
58 
59  // Loop over all entries of the TTree or TChain.
60  while (myReader.Next()) {
61  // Just access the data as if myPx and myPy were iterators (note the '*'
62  // in front of them):
63  myHist->Fill(*myPx + *myPy);
64  }
65 
66  myHist->Draw();
67 }
68 ~~~
69 
70 A more complete example including error handling and a few combinations of
71 TTreeReaderValue and TTreeReaderArray would look like this:
72 
73 ~~~{.cpp}
74 #include <TFile.h>
75 #include <TH1.h>
76 #include <TTreeReader.h>
77 #include <TTreeReaderValue.h>
78 #include <TTreeReaderArray.h>
79 
80 #include "TriggerInfo.h"
81 #include "Muon.h"
82 #include "Tau.h"
83 
84 #include <vector>
85 #include <iostream>
86 
87 bool CheckValue(ROOT::TTreeReaderValueBase& value) {
88  if (value->GetSetupStatus() < 0) {
89  std::cerr << "Error " << value->GetSetupStatus()
90  << "setting up reader for " << value->GetBranchName() << '\n';
91  return false;
92  }
93  return true;
94 }
95 
96 
97 // Analyze the tree "MyTree" in the file passed into the function.
98 // Returns false in case of errors.
99 bool analyze(TFile* file) {
100  // Create a TTreeReader named "MyTree" from the given TDirectory.
101  // The TTreeReader gives access to the TTree to the TTreeReaderValue and
102  // TTreeReaderArray objects. It knows the current entry number and knows
103  // how to iterate through the TTree.
104  TTreeReader reader("MyTree", file);
105 
106  // Read a single float value in each tree entries:
107  TTreeReaderValue<float> weight(reader, "event.weight");
108  if (!CheckValue(weight)) return false;
109 
110  // Read a TriggerInfo object from the tree entries:
111  TTreeReaderValue<TriggerInfo> triggerInfo(reader, "triggerInfo");
112  if (!CheckValue(triggerInfo)) return false;
113 
114  //Read a vector of Muon objects from the tree entries:
115  TTreeReaderValue<std::vector<Muon>> muons(reader, "muons");
116  if (!CheckValue(muons)) return false;
117 
118  //Read the pT for all jets in the tree entry:
119  TTreeReaderArray<double> jetPt(reader, "jets.pT");
120  if (!CheckValue(jetPt)) return false;
121 
122  // Read the taus in the tree entry:
123  TTreeReaderArray<Tau> taus(reader, "taus");
124  if (!CheckValue(taus)) return false;
125 
126 
127  // Now iterate through the TTree entries and fill a histogram.
128 
129  TH1F("hist", "TTreeReader example histogram", 10, 0., 100.);
130 
131  while (reader.Next()) {
132  // Access the TriggerInfo object as if it's a pointer.
133  if (!triggerInfo->hasMuonL1())
134  continue;
135 
136  // Ditto for the vector<Muon>.
137  if (!muons->size())
138  continue;
139 
140  // Access the jetPt as an array, whether the TTree stores this as
141  // a std::vector, std::list, TClonesArray or Jet* C-style array, with
142  // fixed or variable array size.
143  if (jetPt.GetSize() < 2 || jetPt[0] < 100)
144  continue;
145 
146  // Access the array of taus.
147  if (!taus.IsEmpty()) {
148  // Access a float value - need to dereference as TTreeReaderValue
149  // behaves like an iterator
150  float currentWeight = *weight;
151  for (const Tau& tau: taus) {
152  hist->Fill(tau.eta(), currentWeight);
153  }
154  }
155  } // TTree entry / event loop
156 }
157 ~~~
158 */
159 
161 
162 using namespace ROOT::Internal;
163 
164 ////////////////////////////////////////////////////////////////////////////////
165 /// Access data from tree.
166 
168  fTree(tree),
169  fDirectory(0),
170  fEntryStatus(kEntryNotLoaded),
171  fMostRecentTreeNumber(-1),
172  fDirector(0),
173  fLastEntry(-1),
174  fProxiesSet(kFALSE)
175 {
176  if (!fTree) {
177  Error("TTreeReader", "TTree is NULL!");
178  } else {
179  Initialize();
180  }
181 }
182 
183 ////////////////////////////////////////////////////////////////////////////////
184 /// Access data from the tree called keyname in the directory (e.g. TFile)
185 /// dir, or the current directory if dir is NULL. If keyname cannot be
186 /// found, or if it is not a TTree, IsZombie() will return true.
187 
188 TTreeReader::TTreeReader(const char* keyname, TDirectory* dir /*= NULL*/):
189  fTree(0),
190  fDirectory(dir),
193  fDirector(0),
194  fLastEntry(-1),
196 {
198  fDirectory->GetObject(keyname, fTree);
199  Initialize();
200 }
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 /// Tell all value readers that the tree reader does not exist anymore.
204 
206 {
207  for (std::deque<ROOT::Internal::TTreeReaderValueBase*>::const_iterator
208  i = fValues.begin(), e = fValues.end(); i != e; ++i) {
209  (*i)->MarkTreeReaderUnavailable();
210  }
211  delete fDirector;
212  fProxies.SetOwner();
213 }
214 
215 ////////////////////////////////////////////////////////////////////////////////
216 /// Initialization of the director.
217 
219 {
220  if (!fTree) {
221  MakeZombie();
224  } else {
225  if (fTree->GetEntryList()) {
226  Warning("Initialize()",
227  "TTreeReader support for TEntryList only available since ROOT 6.10!");
228  }
229  ResetBit(kZombie);
230  if (fTree->InheritsFrom(TChain::Class())) {
232  }
234  }
235 }
236 
237 ////////////////////////////////////////////////////////////////////////////////
238 /// Set the range of entries to be processed. This call is usually followed by
239 /// an iteration of the range using TTreeReader::Next(), which will visit the
240 /// the entries from `begiNEntry` to `endEntry - 1`.
241 /// If endEntry > beginEntry, this call is equivalent to
242 /// `SetEntry(beginEntry - 1); SetLastEntry(endEntry);`. Otherwise `endEntry` is ignored and
243 /// only `beginEntry` is set.
244 /// \return kEntryValid (more useful since ROOT v6.10).
245 
247 {
248  if (endEntry > beginEntry)
249  fLastEntry = endEntry;
250  else
251  fLastEntry = -1;
252  return SetEntry(beginEntry - 1);
253 }
254 
255 ////////////////////////////////////////////////////////////////////////////////
256 /// Restart a Next() loop from the first entry.
257 
259  fDirector->SetTree(nullptr);
260  fDirector->SetReadEntry(-1);
261  fProxiesSet = false; // we might get more value readers, meaning new proxies.
262 }
263 
264 ////////////////////////////////////////////////////////////////////////////////
265 /// Returns the index of the current entry being read
266 
268  if (!fDirector) return -1;
269  Long64_t currentTreeEntry = fDirector->GetReadEntry();
270  if (TestBit(kBitIsChain) && currentTreeEntry >= 0) {
271  return ((TChain*)fTree)->GetChainEntryNumber(currentTreeEntry);
272  }
273  return currentTreeEntry;
274 }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Load an entry into the tree, return the status of the read.
278 /// For chains, entry is the global (i.e. not tree-local) entry number, unless
279 /// `local` is `true`, in which case `entry` specifies the entry number within
280 /// the current tree. This is needed for instance for TSelector::Process().
281 
283 {
284  if (!fTree || !fDirector) {
286  return fEntryStatus;
287  }
288 
289  if (fProxiesSet && fDirector && fDirector->GetReadEntry() == -1
290  && fMostRecentTreeNumber != -1) {
291  // Passed the end of the chain, Restart() was not called:
292  // don't try to load entries anymore. Can happen in these cases:
293  // while (tr.Next()) {something()};
294  // while (tr.Next()) {somethingelse()}; // should not be calling somethingelse().
296  return fEntryStatus;
297  }
298 
299  Int_t treeNumberBeforeLoadTree = fTree->GetTreeNumber();
300 
301  TTree* treeToCallLoadOn = local ? fTree->GetTree() : fTree;
302  Long64_t loadResult = treeToCallLoadOn->LoadTree(entry);
303 
304  if (loadResult == -2) {
305  fDirector->SetTree(nullptr);
307  return fEntryStatus;
308  }
309 
310  if (fMostRecentTreeNumber != treeNumberBeforeLoadTree) {
311  // This can happen if someone switched trees behind us.
312  // Likely cause: a TChain::LoadTree() e.g. from TTree::Process().
313  // This means that "local" should be set!
314 
315  if (fTree->GetTreeNumber() != treeNumberBeforeLoadTree) {
316  // we have switched trees again, which means that "local" was not set!
317  // There are two entities switching trees which is bad.
318  R__ASSERT(!local && "Logic error - !local but tree number changed?");
319  Warning("SetEntryBase()",
320  "The current tree in the TChain %s has changed (e.g. by TTree::Process) "
321  "even though TTreeReader::SetEntry() was called, which switched the tree "
322  "again. Did you mean to call TTreeReader::SetLocalEntry()?",
323  fTree->GetName());
324  }
325  }
326 
327  if (fDirector->GetTree() != fTree->GetTree()
328  || fMostRecentTreeNumber != fTree->GetTreeNumber()) {
329  fDirector->SetTree(fTree->GetTree());
330  if (fProxiesSet) {
331  for (auto value: fValues) {
332  value->NotifyNewTree(fTree->GetTree());
333  }
334  }
335  }
336 
337  fMostRecentTreeNumber = fTree->GetTreeNumber();
338 
339  if (!fProxiesSet) {
340  // Tell readers we now have a tree
341  for (std::deque<ROOT::Internal::TTreeReaderValueBase*>::const_iterator
342  i = fValues.begin(); i != fValues.end(); ++i) { // Iterator end changes when parameterized arrays are read
343  (*i)->CreateProxy();
344 
345  if (!(*i)->GetProxy()){
347  return fEntryStatus;
348  }
349  }
350  // If at least one proxy was there and no error occurred, we assume the proxies to be set.
351  fProxiesSet = !fValues.empty();
352  }
353 
354  if (fLastEntry >= 0 && entry >= fLastEntry) {
356  return fEntryStatus;
357  }
358  fDirector->SetReadEntry(loadResult);
360  return fEntryStatus;
361 }
362 
363 ////////////////////////////////////////////////////////////////////////////////
364 /// Set (or update) the which tree to reader from. tree can be
365 /// a TTree or a TChain.
366 
368 {
369  fTree = tree;
370  if (fTree) {
371  ResetBit(kZombie);
372  if (fTree->InheritsFrom(TChain::Class())) {
374  }
375  }
376 
377  if (!fDirector) {
378  Initialize();
379  }
380  else {
382  fDirector->SetReadEntry(-1);
383  // Distinguish from end-of-chain case:
385  }
386 }
387 
388 ////////////////////////////////////////////////////////////////////////////////
389 /// Add a value reader for this tree.
390 
392 {
393  if (fProxiesSet) {
394  Error("RegisterValueReader",
395  "Error registering reader for %s: TTreeReaderValue/Array objects must be created before the call to Next() / SetEntry() / SetLocalEntry(), or after TTreeReader::Restart()!",
396  reader->GetBranchName());
397  return false;
398  }
399  fValues.push_back(reader);
400  return true;
401 }
402 
403 ////////////////////////////////////////////////////////////////////////////////
404 /// Remove a value reader for this tree.
405 
407 {
408  std::deque<ROOT::Internal::TTreeReaderValueBase*>::iterator iReader
409  = std::find(fValues.begin(), fValues.end(), reader);
410  if (iReader == fValues.end()) {
411  Error("DeregisterValueReader", "Cannot find reader of type %s for branch %s", reader->GetDerivedTypeName(), reader->fBranchName.Data());
412  return;
413  }
414  fValues.erase(iReader);
415 }
the tree does not exist
Definition: TTreeReader.h:132
object ctor failed
Definition: TObject.h:70
long long Long64_t
Definition: RtypesCore.h:69
TTreeReader is a simple, robust and fast interface to read values from a TTree, TChain or TNtuple...
Definition: TTreeReader.h:48
last entry was reached
Definition: TTreeReader.h:137
Long64_t GetCurrentEntry() const
Returns the index of the current entry being read.
void GetObject(const char *namecycle, T *&ptr)
Definition: TDirectory.h:147
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:157
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:209
#define R__ASSERT(e)
Definition: TError.h:98
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
const char * Class
Definition: TXMLSetup.cxx:64
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:739
THashTable fProxies
attached ROOT::TNamedBranchProxies; owned
Definition: TTreeReader.h:210
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.
the tree entry number does not exist
Definition: TTreeReader.h:133
TDirectory * fDirectory
directory (or current file for chains)
Definition: TTreeReader.h:205
EEntryStatus fEntryStatus
status of most recent read request
Definition: TTreeReader.h:206
EEntryStatus SetEntriesRange(Long64_t beginEntry, Long64_t endEntry)
Set the range of entries to be processed.
Long64_t fLastEntry
The last entry to be processed.
Definition: TTreeReader.h:215
ROOT::Internal::TBranchProxyDirector * fDirector
proxying director, owned
Definition: TTreeReader.h:208
Bool_t fProxiesSet
True if the proxies have been set, false otherwise.
Definition: TTreeReader.h:216
~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:925
EEntryStatus SetEntry(Long64_t entry)
Definition: TTreeReader.h:162
no entry has been loaded yet
Definition: TTreeReader.h:131
void Restart()
Restart a Next() loop from the first entry.
#define ClassImp(name)
Definition: Rtypes.h:279
Describe directory structure in memory.
Definition: TDirectory.h:44
TTree * fTree
tree that&#39;s read
Definition: TTreeReader.h:204
void Initialize()
Initialization of the director.
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:136
our tree is a chain
Definition: TTreeReader.h:201
void MakeZombie()
Definition: TObject.h:47
virtual const char * GetDerivedTypeName() const =0
A chain is a collection of files containg TTree objects.
Definition: TChain.h:35
Definition: tree.py:1
#define gDirectory
Definition: TDirectory.h:221
void SetTree(TTree *tree)
Set (or update) the which tree to reader from.
void ResetBit(UInt_t f)
Definition: TObject.h:156
Int_t fMostRecentTreeNumber
TTree::GetTreeNumber() of the most recent tree.
Definition: TTreeReader.h:207
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:911