Logo ROOT   6.12/07
Reference Guide
TTreeReader.h
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Axel Naumann, 2010-08-02
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers. *
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 #ifndef ROOT_TTreeReader
13 #define ROOT_TTreeReader
14 
15 
16 ////////////////////////////////////////////////////////////////////////////
17 // //
18 // TTreeReader //
19 // //
20 // A simple interface for reading trees or chains. //
21 // //
22 // //
23 ////////////////////////////////////////////////////////////////////////////
24 
25 #include "THashTable.h"
26 #include "TTree.h"
27 #include "TTreeReaderUtils.h"
28 
29 #include <deque>
30 #include <iterator>
31 #include <unordered_map>
32 
33 class TDictionary;
34 class TDirectory;
35 class TFileCollection;
36 
37 namespace ROOT {
38 namespace Internal {
39  class TBranchProxyDirector;
40 }
41 }
42 
43 class TTreeReader: public TObject {
44 public:
45 
46  ///\class TTreeReader::Iterator_t
47  /// Iterate through the entries of a TTree.
48  ///
49  /// This iterator drives the associated TTreeReader; its
50  /// dereferencing (and actually even the iteration) will
51  /// set the entry number represented by this iterator.
52  /// It does not really represent a data element; it simply
53  /// returns the entry number (or -1 once the end of the tree
54  /// is reached).
55  class Iterator_t:
56  public std::iterator<std::input_iterator_tag, const Long64_t, Long64_t> {
57  private:
58  Long64_t fEntry; ///< Entry number of the tree referenced by this iterator; -1 is invalid.
59  TTreeReader* fReader; ///< The reader we select the entries on.
60 
61  /// Whether the iterator points to a valid entry.
62  bool IsValid() const { return fEntry >= 0; }
63 
64  public:
65  /// Default-initialize the iterator as "past the end".
66  Iterator_t(): fEntry(-1), fReader() {}
67 
68  /// Initialize the iterator with the reader it steers and a
69  /// tree entry number; -1 is invalid.
71  fEntry(entry), fReader(&reader) {}
72 
73  /// Compare two iterators for equality.
74  bool operator==(const Iterator_t& lhs) const {
75  // From C++14: value initialized (past-end) it compare equal.
76  if (!IsValid() && !lhs.IsValid()) return true;
77  return fEntry == lhs.fEntry && fReader == lhs.fReader;
78  }
79 
80  /// Compare two iterators for inequality.
81  bool operator!=(const Iterator_t& lhs) const {
82  return !(*this == lhs);
83  }
84 
85  /// Increment the iterator (postfix i++).
87  Iterator_t ret = *this;
88  this->operator++();
89  return ret;
90  }
91 
92  /// Increment the iterator (prefix ++i).
94  if (IsValid()) {
95  ++fEntry;
96  // Force validity check of new fEntry.
97  this->operator*();
98  // Don't set the old entry: op* will if needed, and
99  // in most cases it just adds a lot of spinning back
100  // and forth: in most cases teh sequence is ++i; *i.
101  }
102  return *this;
103  }
104 
105  /// Set the entry number in the reader and return it.
106  const Long64_t& operator*() {
107  if (IsValid()) {
108  // If we cannot access that entry, mark the iterator invalid.
109  if (fReader->SetEntry(fEntry) != kEntryValid) {
110  fEntry = -1;
111  }
112  }
113  // There really is no data in this iterator; return the number.
114  return fEntry;
115  }
116 
117  const Long64_t& operator*() const {
118  return **const_cast<Iterator_t*>(this);
119  }
120  };
121 
123 
125  kEntryValid = 0, ///< data read okay
126  kEntryNotLoaded, ///< no entry has been loaded yet
127  kEntryNoTree, ///< the tree does not exist
128  kEntryNotFound, ///< the tree entry number does not exist
129  kEntryChainSetupError, ///< problem in accessing a chain element, e.g. file without the tree
130  kEntryChainFileError, ///< problem in opening a chain's file
131  kEntryDictionaryError, ///< problem reading dictionary info from tree
132  kEntryBeyondEnd ///< last entry loop has reached its end
133  };
134 
135  static constexpr const char * const fgEntryStatusText[kEntryBeyondEnd + 1] = {
136  "valid entry",
137  "the tree does not exist",
138  "the tree entry number does not exist",
139  "cannot access chain element",
140  "problem in opening a chain's file",
141  "problem reading dictionary info from tree",
142  "last entry loop has reached its end"
143  };
144 
145  TTreeReader() = default;
146 
147  TTreeReader(TTree* tree, TEntryList* entryList = nullptr);
148  TTreeReader(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
149  TTreeReader(const char* keyname, TEntryList* entryList = nullptr):
150  TTreeReader(keyname, nullptr, entryList) {}
151 
152  ~TTreeReader();
153 
154  void SetTree(TTree* tree, TEntryList* entryList = nullptr);
155  void SetTree(const char* keyname, TEntryList* entryList = nullptr) {
156  SetTree(keyname, nullptr, entryList);
157  }
158  void SetTree(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
159 
160  Bool_t IsChain() const { return TestBit(kBitIsChain); }
161 
162  TTree* GetTree() const { return fTree; }
163  TEntryList* GetEntryList() const { return fEntryList; }
164 
165  ///\{ \name Entry setters
166 
167  /// Move to the next entry (or index of the TEntryList if that is set).
168  ///
169  /// \return false if the previous entry was already the last entry. This allows
170  /// the function to be used in `while (reader.Next()) { ... }`
172  return SetEntry(GetCurrentEntry() + 1) == kEntryValid;
173  }
174 
175  /// Set the next entry (or index of the TEntryList if that is set).
176  ///
177  /// \param entry If not TEntryList is set, the entry is a global entry (i.e.
178  /// not the entry number local to the chain's current tree).
179  /// \returns the `entry`'s read status, i.e. whether the entry is available.
180  EEntryStatus SetEntry(Long64_t entry) { return SetEntryBase(entry, kFALSE); }
181 
182  /// Set the next local tree entry. If a TEntryList is set, this function is
183  /// equivalent to `SetEntry()`.
184  ///
185  /// \param entry Entry number of the TChain's current TTree. This is the
186  /// entry number passed for instance by `TSelector::Process(entry)`, i.e.
187  /// within `TSelector::Process()` always use `SetLocalEntry()` and not
188  /// `SetEntry()`!
189  /// \return the `entry`'s read status, i.e. whether the entry is available.
190  EEntryStatus SetLocalEntry(Long64_t entry) { return SetEntryBase(entry, kTRUE); }
191 
192  /// Sets the entry that `Next()` will stop iteration on.
193  ///
194  /// \param beginEntry The first entry that `Next()` will load.
195  /// \param endEntry The entry that `Next()` will return `kFALSE` on (i.e. not
196  /// load anymore).
197  EEntryStatus SetEntriesRange(Long64_t beginEntry, Long64_t endEntry);
198 
199  /// Restart a Next() loop from entry 0 (of TEntryList index 0 of fEntryList is set).
200  void Restart();
201 
202  ///\}
203 
204  EEntryStatus GetEntryStatus() const { return fEntryStatus; }
205 
206  Long64_t GetEntries(Bool_t force) const;
207 
208  /// Returns the index of the current entry being read.
209  ///
210  /// If `IsChain()`, the returned index corresponds to the global entry number
211  /// (i.e. not the entry number local to the chain's current tree).
212  /// If `fEntryList`, the returned index corresponds to an index in the
213  /// TEntryList; to translate to the TChain's / TTree's entry number pass it
214  /// through `reader.GetEntryList()->GetEntry(reader.GetCurrentEntry())`.
215  Long64_t GetCurrentEntry() const { return fEntry; }
216 
217  /// Return an iterator to the 0th TTree entry.
219  return Iterator_t(*this, 0);
220  }
221  /// Return an iterator beyond the last TTree entry.
222  Iterator_t end() const { return Iterator_t(); }
223 
224 protected:
225  using NamedProxies_t = std::unordered_map<std::string, std::unique_ptr<ROOT::Internal::TNamedBranchProxy>>;
226  void Initialize();
227  ROOT::Internal::TNamedBranchProxy* FindProxy(const char* branchname) const
228  {
229  const auto proxyIt = fProxies.find(branchname);
230  return fProxies.end() != proxyIt ? proxyIt->second.get() : nullptr;
231  }
232 
234  {
235  auto bpName = p->GetName();
236 #ifndef NDEBUG
237  if (fProxies.end() != fProxies.find(bpName)) {
238  std::string err = "A proxy with key " + std::string(bpName) + " was already stored!";
239  throw std::runtime_error(err);
240  }
241 #endif
242 
243  fProxies[bpName].reset(p);
244  }
245 
246  Bool_t RegisterValueReader(ROOT::Internal::TTreeReaderValueBase* reader);
247  void DeregisterValueReader(ROOT::Internal::TTreeReaderValueBase* reader);
248 
249  EEntryStatus SetEntryBase(Long64_t entry, Bool_t local);
250 
251 private:
252 
253  std::string GetProxyKey(const char *branchname)
254  {
255  std::string key(branchname);
256  //key += reinterpret_cast<std::uintptr_t>(fTree);
257  return key;
258  }
259 
260  enum EStatusBits {
261  kBitIsChain = BIT(14), ///< our tree is a chain
262  kBitHaveWarnedAboutEntryListAttachedToTTree = BIT(15) ///< the tree had a TEntryList and we have warned about that
263  };
264 
265  TTree* fTree = nullptr; ///< tree that's read
266  TEntryList* fEntryList = nullptr; ///< entry list to be used
267  EEntryStatus fEntryStatus = kEntryNotLoaded; ///< status of most recent read request
268  Int_t fMostRecentTreeNumber = -1; ///< TTree::GetTreeNumber() of the most recent tree
269  ROOT::Internal::TBranchProxyDirector* fDirector = nullptr; ///< proxying director, owned
270  std::deque<ROOT::Internal::TTreeReaderValueBase*> fValues; ///< readers that use our director
271  NamedProxies_t fProxies; ///< attached ROOT::TNamedBranchProxies; owned
272 
273  Long64_t fEntry = -1; ///< Current (non-local) entry of fTree or of fEntryList if set.
274 
275  /// The end of the entry loop. When set (i.e. >= 0), it provides a way
276  /// to stop looping over the TTree when we reach a certain entry: Next()
277  /// returns kFALSE when GetCurrentEntry() reaches fEndEntry.
278  Long64_t fEndEntry = -1;
279  Bool_t fProxiesSet = kFALSE; ///< True if the proxies have been set, false otherwise
280 
283 
284  ClassDef(TTreeReader, 0); // A simple interface to read trees
285 };
286 
287 #endif // defined TTreeReader
ROOT::Internal::TNamedBranchProxy * FindProxy(const char *branchname) const
Definition: TTreeReader.h:227
the tree does not exist
Definition: TTreeReader.h:127
Iterate through the entries of a TTree.
Definition: TTreeReader.h:55
bool operator!=(const Iterator_t &lhs) const
Compare two iterators for inequality.
Definition: TTreeReader.h:81
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:43
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
Long64_t GetCurrentEntry() const
Returns the index of the current entry being read.
Definition: TTreeReader.h:215
std::string GetProxyKey(const char *branchname)
Definition: TTreeReader.h:253
TTreeReader(const char *keyname, TEntryList *entryList=nullptr)
Definition: TTreeReader.h:149
#define BIT(n)
Definition: Rtypes.h:78
std::deque< ROOT::Internal::TTreeReaderValueBase * > fValues
readers that use our director
Definition: TTreeReader.h:270
void SetTree(const char *keyname, TEntryList *entryList=nullptr)
Definition: TTreeReader.h:155
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Long64_t fEntry
Entry number of the tree referenced by this iterator; -1 is invalid.
Definition: TTreeReader.h:58
bool IsValid() const
Whether the iterator points to a valid entry.
Definition: TTreeReader.h:62
TTree * GetTree() const
Definition: TTreeReader.h:162
#define ClassDef(name, id)
Definition: Rtypes.h:320
the tree entry number does not exist
Definition: TTreeReader.h:128
Iterator_t begin()
Return an iterator to the 0th TTree entry.
Definition: TTreeReader.h:218
const Long64_t & operator*()
Set the entry number in the reader and return it.
Definition: TTreeReader.h:106
Iterator_t()
Default-initialize the iterator as "past the end".
Definition: TTreeReader.h:66
NamedProxies_t fProxies
attached ROOT::TNamedBranchProxies; owned
Definition: TTreeReader.h:271
Iterator_t end() const
Return an iterator beyond the last TTree entry.
Definition: TTreeReader.h:222
void Initialize(Bool_t useTMVAStyle=kTRUE)
Definition: tmvaglob.cxx:176
This class defines an abstract interface that must be implemented by all classes that contain diction...
Definition: TDictionary.h:158
TTime operator*(const TTime &t1, const TTime &t2)
Definition: TTime.h:85
void AddProxy(ROOT::Internal::TNamedBranchProxy *p)
Definition: TTreeReader.h:233
Iterator_t iterator
Definition: TTreeReader.h:122
EEntryStatus SetEntry(Long64_t entry)
Set the next entry (or index of the TEntryList if that is set).
Definition: TTreeReader.h:180
no entry has been loaded yet
Definition: TTreeReader.h:126
const Long64_t & operator*() const
Definition: TTreeReader.h:117
problem in opening a chain&#39;s file
Definition: TTreeReader.h:130
problem in accessing a chain element, e.g. file without the tree
Definition: TTreeReader.h:129
const Bool_t kFALSE
Definition: RtypesCore.h:88
Iterator_t operator++(int)
Increment the iterator (postfix i++).
Definition: TTreeReader.h:86
EEntryStatus SetLocalEntry(Long64_t entry)
Set the next local tree entry.
Definition: TTreeReader.h:190
Describe directory structure in memory.
Definition: TDirectory.h:34
EStatusBits
Definition: TObject.h:57
problem reading dictionary info from tree
Definition: TTreeReader.h:131
EEntryStatus GetEntryStatus() const
Definition: TTreeReader.h:204
Bool_t IsChain() const
Definition: TTreeReader.h:160
Iterator_t & operator++()
Increment the iterator (prefix ++i).
Definition: TTreeReader.h:93
TEntryList * GetEntryList() const
Definition: TTreeReader.h:163
Mother of all ROOT objects.
Definition: TObject.h:37
Bool_t Next()
Move to the next entry (or index of the TEntryList if that is set).
Definition: TTreeReader.h:171
Class that contains a list of TFileInfo&#39;s and accumulated meta data information about its entries...
Definition: tree.py:1
bool operator==(const Iterator_t &lhs) const
Compare two iterators for equality.
Definition: TTreeReader.h:74
A TTree object has a header with a name and a title.
Definition: TTree.h:70
TTreeReader * fReader
The reader we select the entries on.
Definition: TTreeReader.h:59
A List of entry numbers in a TTree or TChain.
Definition: TEntryList.h:25
const Bool_t kTRUE
Definition: RtypesCore.h:87
Iterator_t(TTreeReader &reader, Long64_t entry)
Initialize the iterator with the reader it steers and a tree entry number; -1 is invalid.
Definition: TTreeReader.h:70
std::unordered_map< std::string, std::unique_ptr< ROOT::Internal::TNamedBranchProxy > > NamedProxies_t
Definition: TTreeReader.h:225