Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 "TTree.h"
26#include "TTreeReaderUtils.h"
27#include "TNotifyLink.h"
28
29#include <deque>
30#include <iterator>
31#include <unordered_map>
32#include <string>
33
34class TDictionary;
35class TDirectory;
36class TFileCollection;
37
38namespace ROOT {
39namespace Internal {
40 class TBranchProxyDirector;
41}
42}
43
44class TTreeReader: public TObject {
45public:
46
47 ///\class TTreeReader::Iterator_t
48 /// Iterate through the entries of a TTree.
49 ///
50 /// This iterator drives the associated TTreeReader; its
51 /// dereferencing (and actually even the iteration) will
52 /// set the entry number represented by this iterator.
53 /// It does not really represent a data element; it simply
54 /// returns the entry number (or -1 once the end of the tree
55 /// is reached).
57 public std::iterator<std::input_iterator_tag, const Long64_t, Long64_t> {
58 private:
59 Long64_t fEntry; ///< Entry number of the tree referenced by this iterator; -1 is invalid.
60 TTreeReader* fReader; ///< The reader we select the entries on.
61
62 /// Whether the iterator points to a valid entry.
63 bool IsValid() const { return fEntry >= 0; }
64
65 public:
66 /// Default-initialize the iterator as "past the end".
67 Iterator_t(): fEntry(-1), fReader(nullptr) {}
68
69 /// Initialize the iterator with the reader it steers and a
70 /// tree entry number; -1 is invalid.
72 fEntry(entry), fReader(&reader) {}
73
74 /// Compare two iterators for equality.
75 bool operator==(const Iterator_t& lhs) const {
76 // From C++14: value initialized (past-end) it compare equal.
77 if (!IsValid() && !lhs.IsValid()) return true;
78 return fEntry == lhs.fEntry && fReader == lhs.fReader;
79 }
80
81 /// Compare two iterators for inequality.
82 bool operator!=(const Iterator_t& lhs) const {
83 return !(*this == lhs);
84 }
85
86 /// Increment the iterator (postfix i++).
88 Iterator_t ret = *this;
89 this->operator++();
90 return ret;
91 }
92
93 /// Increment the iterator (prefix ++i).
95 if (IsValid()) {
96 ++fEntry;
97 // Force validity check of new fEntry.
98 this->operator*();
99 // Don't set the old entry: op* will if needed, and
100 // in most cases it just adds a lot of spinning back
101 // and forth: in most cases teh sequence is ++i; *i.
102 }
103 return *this;
104 }
105
106 /// Set the entry number in the reader and return it.
108 if (IsValid()) {
109 // If we cannot access that entry, mark the iterator invalid.
111 fEntry = -1;
112 }
113 }
114 // There really is no data in this iterator; return the number.
115 return fEntry;
116 }
117
118 const Long64_t& operator*() const {
119 return **const_cast<Iterator_t*>(this);
120 }
121 };
122
124
126 kEntryValid = 0, ///< data read okay
127 kEntryNotLoaded, ///< no entry has been loaded yet
128 kEntryNoTree, ///< the tree does not exist
129 kEntryNotFound, ///< the tree entry number does not exist
130 kEntryChainSetupError, ///< problem in accessing a chain element, e.g. file without the tree
131 kEntryChainFileError, ///< problem in opening a chain's file
132 kEntryDictionaryError, ///< problem reading dictionary info from tree
133 kEntryBeyondEnd, ///< last entry loop has reached its end
134 kEntryBadReader, ///< One of the readers was not successfully initialized.
135 kEntryUnknownError ///< LoadTree return less than -4, likely a 'newer' error code.
136 };
137
139 kNoTree = 0, ///< default state, no TTree is connected (formerly 'Zombie' state)
140 kLoadTreeNone, ///< Notify has not been called yet.
141 kInternalLoadTree, ///< Notify/LoadTree was last called from SetEntryBase
142 kExternalLoadTree ///< User code called LoadTree directly.
143 };
144
145 static constexpr const char * const fgEntryStatusText[kEntryUnknownError + 1] = {
146 "valid entry",
147 "the tree does not exist",
148 "the tree entry number does not exist",
149 "cannot access chain element",
150 "problem in opening a chain's file",
151 "problem reading dictionary info from tree",
152 "last entry loop has reached its end",
153 "one of the readers was not successfully initialized",
154 "LoadTree return less than -4, likely a 'newer' error code"
155 };
156
157 TTreeReader();
158
159 TTreeReader(TTree* tree, TEntryList* entryList = nullptr);
160 TTreeReader(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
161 TTreeReader(const char *keyname, TEntryList *entryList = nullptr) : TTreeReader(keyname, nullptr, entryList) {}
162
163 ~TTreeReader();
164
165 void SetTree(TTree* tree, TEntryList* entryList = nullptr);
166 void SetTree(const char* keyname, TEntryList* entryList = nullptr) {
167 SetTree(keyname, nullptr, entryList);
168 }
169 void SetTree(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
170
171 Bool_t IsChain() const { return TestBit(kBitIsChain); }
172
174
175 TTree* GetTree() const { return fTree; }
176 TEntryList* GetEntryList() const { return fEntryList; }
177
178 ///\{ \name Entry setters
179
180 /// Move to the next entry (or index of the TEntryList if that is set).
181 ///
182 /// \return false if the previous entry was already the last entry. This allows
183 /// the function to be used in `while (reader.Next()) { ... }`
185 return SetEntry(GetCurrentEntry() + 1) == kEntryValid;
186 }
187
188 /// Set the next entry (or index of the TEntryList if that is set).
189 ///
190 /// \param entry If not TEntryList is set, the entry is a global entry (i.e.
191 /// not the entry number local to the chain's current tree).
192 /// \returns the `entry`'s read status, i.e. whether the entry is available.
194
195 /// Set the next local tree entry. If a TEntryList is set, this function is
196 /// equivalent to `SetEntry()`.
197 ///
198 /// \param entry Entry number of the TChain's current TTree. This is the
199 /// entry number passed for instance by `TSelector::Process(entry)`, i.e.
200 /// within `TSelector::Process()` always use `SetLocalEntry()` and not
201 /// `SetEntry()`!
202 /// \return the `entry`'s read status, i.e. whether the entry is available.
204
205 /// Set the begin and end entry numbers
206 ///
207 /// \param beginEntry The first entry that `Next()` will load.
208 /// \param endEntry The entry that `Next()` will return `kFALSE` on (i.e. not
209 /// load anymore).
210 EEntryStatus SetEntriesRange(Long64_t beginEntry, Long64_t endEntry);
211
212 /// Get the begin and end entry numbers
213 ///
214 /// \return a pair contained the begin and end entry numbers.
215 std::pair<Long64_t, Long64_t> GetEntriesRange() const { return std::make_pair(fBeginEntry, fEndEntry); }
216
217 /// Restart a Next() loop from entry 0 (of TEntryList index 0 of fEntryList is set).
218 void Restart();
219
220 ///\}
221
223
224 Long64_t GetEntries() const;
226
227 /// Returns the index of the current entry being read.
228 ///
229 /// If `IsChain()`, the returned index corresponds to the global entry number
230 /// (i.e. not the entry number local to the chain's current tree).
231 /// If `fEntryList`, the returned index corresponds to an index in the
232 /// TEntryList; to translate to the TChain's / TTree's entry number pass it
233 /// through `reader.GetEntryList()->GetEntry(reader.GetCurrentEntry())`.
234 Long64_t GetCurrentEntry() const { return fEntry; }
235
236 Bool_t Notify();
237
238 /// Return an iterator to the 0th TTree entry.
240 return Iterator_t(*this, 0);
241 }
242 /// Return an iterator beyond the last TTree entry.
243 Iterator_t end() const { return Iterator_t(); }
244
245protected:
246 using NamedProxies_t = std::unordered_map<std::string, std::unique_ptr<ROOT::Internal::TNamedBranchProxy>>;
247 void Initialize();
248 ROOT::Internal::TNamedBranchProxy* FindProxy(const char* branchname) const
249 {
250 const auto proxyIt = fProxies.find(branchname);
251 return fProxies.end() != proxyIt ? proxyIt->second.get() : nullptr;
252 }
253
255 {
256 auto bpName = p->GetName();
257#ifndef NDEBUG
258 if (fProxies.end() != fProxies.find(bpName)) {
259 std::string err = "A proxy with key " + std::string(bpName) + " was already stored!";
260 throw std::runtime_error(err);
261 }
262#endif
263
264 fProxies[bpName].reset(p);
265 }
266
269
271
273
274private:
275
276 std::string GetProxyKey(const char *branchname)
277 {
278 std::string key(branchname);
279 //key += reinterpret_cast<std::uintptr_t>(fTree);
280 return key;
281 }
282
284 kBitIsChain = BIT(14), ///< our tree is a chain
285 kBitHaveWarnedAboutEntryListAttachedToTTree = BIT(15), ///< the tree had a TEntryList and we have warned about that
286 kBitSetEntryBaseCallingLoadTree = BIT(16) ///< SetEntryBase is in the process of calling TChain/TTree::LoadTree.
287 };
288
289 TTree* fTree = nullptr; ///< tree that's read
290 TEntryList* fEntryList = nullptr; ///< entry list to be used
291 EEntryStatus fEntryStatus = kEntryNotLoaded; ///< status of most recent read request
292 ELoadTreeStatus fLoadTreeStatus = kNoTree; ///< Indicator on how LoadTree was called 'last' time.
293 TNotifyLink<TTreeReader> fNotify; // Callback object used by the TChain to update this proxy
294 ROOT::Internal::TBranchProxyDirector* fDirector = nullptr; ///< proxying director, owned
295 std::deque<ROOT::Internal::TFriendProxy*> fFriendProxies; ///< proxying for friend TTrees, owned
296 std::deque<ROOT::Internal::TTreeReaderValueBase*> fValues; ///< readers that use our director
297 NamedProxies_t fProxies; ///< attached ROOT::TNamedBranchProxies; owned
298
299 Long64_t fEntry = -1; ///< Current (non-local) entry of fTree or of fEntryList if set.
300
301 /// The end of the entry loop. When set (i.e. >= 0), it provides a way
302 /// to stop looping over the TTree when we reach a certain entry: Next()
303 /// returns kFALSE when GetCurrentEntry() reaches fEndEntry.
305 Long64_t fBeginEntry = 0LL; ///< This allows us to propagate the range to the TTreeCache
306 Bool_t fProxiesSet = kFALSE; ///< True if the proxies have been set, false otherwise
307 Bool_t fSetEntryBaseCallingLoadTree = kFALSE; ///< True if during the LoadTree execution triggered by SetEntryBase.
308
311
312 ClassDef(TTreeReader, 0); // A simple interface to read trees
313};
314
315#endif // defined TTreeReader
const Bool_t kFALSE
Definition RtypesCore.h:92
bool Bool_t
Definition RtypesCore.h:63
long long Long64_t
Definition RtypesCore.h:73
const Bool_t kTRUE
Definition RtypesCore.h:91
#define ClassDef(name, id)
Definition Rtypes.h:325
#define BIT(n)
Definition Rtypes.h:85
Base class of TTreeReaderArray.
Base class of TTreeReaderValue.
This class defines an abstract interface that must be implemented by all classes that contain diction...
Describe directory structure in memory.
Definition TDirectory.h:45
A List of entry numbers in a TTree or TChain.
Definition TEntryList.h:26
Class that contains a list of TFileInfo's and accumulated meta data information about its entries.
Mother of all ROOT objects.
Definition TObject.h:37
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:187
Iterate through the entries of a TTree.
Definition TTreeReader.h:57
Iterator_t & operator++()
Increment the iterator (prefix ++i).
Definition TTreeReader.h:94
Iterator_t()
Default-initialize the iterator as "past the end".
Definition TTreeReader.h:67
const Long64_t & operator*() const
Long64_t fEntry
Entry number of the tree referenced by this iterator; -1 is invalid.
Definition TTreeReader.h:59
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:71
bool operator==(const Iterator_t &lhs) const
Compare two iterators for equality.
Definition TTreeReader.h:75
TTreeReader * fReader
The reader we select the entries on.
Definition TTreeReader.h:60
const Long64_t & operator*()
Set the entry number in the reader and return it.
bool IsValid() const
Whether the iterator points to a valid entry.
Definition TTreeReader.h:63
bool operator!=(const Iterator_t &lhs) const
Compare two iterators for inequality.
Definition TTreeReader.h:82
Iterator_t operator++(int)
Increment the iterator (postfix i++).
Definition TTreeReader.h:87
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:44
TTreeReader()
Default constructor. Call SetTree to connect to a TTree.
Bool_t fProxiesSet
True if the proxies have been set, false otherwise.
ELoadTreeStatus fLoadTreeStatus
Indicator on how LoadTree was called 'last' time.
void SetTree(const char *keyname, TEntryList *entryList=nullptr)
Long64_t GetEntries() const
Returns the number of entries of the TEntryList if one is provided, else of the TTree / TChain,...
EEntryStatus fEntryStatus
status of most recent read request
std::unordered_map< std::string, std::unique_ptr< ROOT::Internal::TNamedBranchProxy > > NamedProxies_t
void SetTree(TTree *tree, TEntryList *entryList=nullptr)
Set (or update) the which tree to read from.
std::pair< Long64_t, Long64_t > GetEntriesRange() const
Get the begin and end entry numbers.
TNotifyLink< TTreeReader > fNotify
Bool_t SetProxies()
Tell readers we now have a tree.
Bool_t IsChain() const
@ kEntryNotFound
the tree entry number does not exist
@ kEntryUnknownError
LoadTree return less than -4, likely a 'newer' error code.
@ kEntryDictionaryError
problem reading dictionary info from tree
@ kEntryChainSetupError
problem in accessing a chain element, e.g. file without the tree
@ kEntryNotLoaded
no entry has been loaded yet
@ kEntryBeyondEnd
last entry loop has reached its end
@ kEntryChainFileError
problem in opening a chain's file
@ kEntryNoTree
the tree does not exist
@ kEntryBadReader
One of the readers was not successfully initialized.
@ kEntryValid
data read okay
std::deque< ROOT::Internal::TTreeReaderValueBase * > fValues
readers that use our director
Bool_t Notify()
Callback from TChain and TTree's LoadTree.
TTree * fTree
tree that's read
ROOT::Internal::TBranchProxyDirector * fDirector
proxying director, owned
TTree * GetTree() const
Iterator_t end() const
Return an iterator beyond the last TTree entry.
~TTreeReader()
Tell all value readers that the tree reader does not exist anymore.
EEntryStatus SetEntriesRange(Long64_t beginEntry, Long64_t endEntry)
Set the begin and end entry numbers.
std::deque< ROOT::Internal::TFriendProxy * > fFriendProxies
proxying for friend TTrees, owned
std::string GetProxyKey(const char *branchname)
Bool_t fSetEntryBaseCallingLoadTree
True if during the LoadTree execution triggered by SetEntryBase.
EEntryStatus GetEntryStatus() const
@ kInternalLoadTree
Notify/LoadTree was last called from SetEntryBase.
@ kNoTree
default state, no TTree is connected (formerly 'Zombie' state)
@ kExternalLoadTree
User code called LoadTree directly.
@ kLoadTreeNone
Notify has not been called yet.
void Initialize()
Initialization of the director.
void Restart()
Restart a Next() loop from entry 0 (of TEntryList index 0 of fEntryList is set).
EEntryStatus SetEntryBase(Long64_t entry, Bool_t local)
Load an entry into the tree, return the status of the read.
TEntryList * fEntryList
entry list to be used
Long64_t fEntry
Current (non-local) entry of fTree or of fEntryList if set.
Bool_t RegisterValueReader(ROOT::Internal::TTreeReaderValueBase *reader)
Add a value reader for this tree.
Long64_t fBeginEntry
This allows us to propagate the range to the TTreeCache.
void AddProxy(ROOT::Internal::TNamedBranchProxy *p)
void DeregisterValueReader(ROOT::Internal::TTreeReaderValueBase *reader)
Remove a value reader for this tree.
@ kBitSetEntryBaseCallingLoadTree
SetEntryBase is in the process of calling TChain/TTree::LoadTree.
@ kBitHaveWarnedAboutEntryListAttachedToTTree
the tree had a TEntryList and we have warned about that
@ kBitIsChain
our tree is a chain
EEntryStatus SetLocalEntry(Long64_t entry)
Set the next local tree entry.
NamedProxies_t fProxies
attached ROOT::TNamedBranchProxies; owned
TEntryList * GetEntryList() const
Bool_t IsInvalid() const
Iterator_t begin()
Return an iterator to the 0th TTree entry.
TTreeReader(const char *keyname, TEntryList *entryList=nullptr)
Long64_t fEndEntry
The end of the entry loop.
Iterator_t iterator
EEntryStatus SetEntry(Long64_t entry)
Set the next entry (or index of the TEntryList if that is set).
static constexpr const char *const fgEntryStatusText[kEntryUnknownError+1]
Bool_t Next()
Move to the next entry (or index of the TEntryList if that is set).
ROOT::Internal::TNamedBranchProxy * FindProxy(const char *branchname) const
Long64_t GetCurrentEntry() const
Returns the index of the current entry being read.
A TTree represents a columnar dataset.
Definition TTree.h:79
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition tree.py:1