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 {
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).
56 class Iterator_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 using iterator_category = std::input_iterator_tag;
66 using value_type = const Long64_t;
68 using pointer = const Long64_t *;
69 using const_pointer = const Long64_t *;
70 using reference = const Long64_t &;
71
72 /// Default-initialize the iterator as "past the end".
73 Iterator_t(): fEntry(-1), fReader(nullptr) {}
74
75 /// Initialize the iterator with the reader it steers and a
76 /// tree entry number; -1 is invalid.
78 fEntry(entry), fReader(&reader) {}
79
80 /// Compare two iterators for equality.
81 bool operator==(const Iterator_t &lhs) const
82 {
83 // From C++14: value initialized (past-end) it compare equal.
84 if (!IsValid() && !lhs.IsValid())
85 return true;
86 // The iterators refer to different readers
87 if (fReader != lhs.fReader)
88 return false;
89 // #16249: range based loop and the tree has zero entries
90 // as well as analogous cases.
91 // Getting the number of events can have a cost, for example in
92 // case of chains of remote files accessible with high latency.
93 // However, it is reasonable to assume that if iterators are
94 // being compared is because an iteration is taking place,
95 // therefore such cost has to be paid anyway, it's just
96 // anticipated.
97 if (fReader->GetTree()->GetEntriesFast() == 0 && fEntry == 0 && !lhs.IsValid()) {
98 return true;
99 }
100 if (lhs.fReader->GetTree()->GetEntriesFast() == 0 && lhs.fEntry == 0 && !IsValid()) {
101 return true;
102 }
103 return fEntry == lhs.fEntry;
104 }
105
106 /// Compare two iterators for inequality.
107 bool operator!=(const Iterator_t& lhs) const {
108 return !(*this == lhs);
109 }
110
111 /// Increment the iterator (postfix i++).
113 Iterator_t ret = *this;
114 this->operator++();
115 return ret;
116 }
117
118 /// Increment the iterator (prefix ++i).
120 if (IsValid()) {
121 ++fEntry;
122 // Force validity check of new fEntry.
123 this->operator*();
124 // Don't set the old entry: op* will if needed, and
125 // in most cases it just adds a lot of spinning back
126 // and forth: in most cases the sequence is ++i; *i.
127 }
128 return *this;
129 }
130
131 /// Set the entry number in the reader and return it.
133 if (IsValid()) {
134 // If we cannot access that entry, mark the iterator invalid.
136 fEntry = -1;
137 }
138 }
139 // There really is no data in this iterator; return the number.
140 return fEntry;
141 }
142
143 const Long64_t& operator*() const {
144 return **const_cast<Iterator_t*>(this);
145 }
146 };
147
149
151 kEntryValid = 0, ///< data read okay
152 kEntryNotLoaded, ///< no entry has been loaded yet
153 kEntryNoTree, ///< the tree does not exist
154 kEntryNotFound, ///< the tree entry number does not exist
155 kEntryChainSetupError, ///< problem in accessing a chain element, e.g. file without the tree
156 kEntryChainFileError, ///< problem in opening a chain's file
157 kEntryDictionaryError, ///< problem reading dictionary info from tree
158 kEntryBeyondEnd, ///< last entry loop has reached its end
159 kEntryBadReader, ///< One of the readers was not successfully initialized.
160 kEntryUnknownError ///< LoadTree return less than -4, likely a 'newer' error code.
161 };
162
164 kNoTree = 0, ///< default state, no TTree is connected (formerly 'Zombie' state)
165 kLoadTreeNone, ///< Notify has not been called yet.
166 kInternalLoadTree, ///< Notify/LoadTree was last called from SetEntryBase
167 kExternalLoadTree ///< User code called LoadTree directly.
168 };
169
170 static constexpr const char * const fgEntryStatusText[kEntryUnknownError + 1] = {
171 "valid entry",
172 "the tree does not exist",
173 "the tree entry number does not exist",
174 "cannot access chain element",
175 "problem in opening a chain's file",
176 "problem reading dictionary info from tree",
177 "last entry loop has reached its end",
178 "one of the readers was not successfully initialized",
179 "LoadTree return less than -4, likely a 'newer' error code"
180 };
181
182 TTreeReader();
183
184 TTreeReader(TTree* tree, TEntryList* entryList = nullptr);
185 TTreeReader(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
186 TTreeReader(const char *keyname, TEntryList *entryList = nullptr) : TTreeReader(keyname, nullptr, entryList) {}
187
188 ~TTreeReader() override;
189
190 void SetTree(TTree* tree, TEntryList* entryList = nullptr);
191 void SetTree(const char* keyname, TEntryList* entryList = nullptr) {
192 SetTree(keyname, nullptr, entryList);
193 }
194 void SetTree(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
195
196 bool IsChain() const { return TestBit(kBitIsChain); }
197
198 bool IsInvalid() const { return fLoadTreeStatus == kNoTree; }
199
200 TTree* GetTree() const { return fTree; }
201 TEntryList* GetEntryList() const { return fEntryList; }
202
203 ///\{ \name Entry setters
204
205 /// Move to the next entry (or index of the TEntryList if that is set).
206 ///
207 /// \return false if the previous entry was already the last entry. This allows
208 /// the function to be used in `while (reader.Next()) { ... }`
209 bool Next() {
210 return SetEntry(GetCurrentEntry() + 1) == kEntryValid;
211 }
212
213 /// Set the next entry (or index of the TEntryList if that is set).
214 ///
215 /// \param entry If not TEntryList is set, the entry is a global entry (i.e.
216 /// not the entry number local to the chain's current tree).
217 /// \returns the `entry`'s read status, i.e. whether the entry is available.
218 EEntryStatus SetEntry(Long64_t entry) { return SetEntryBase(entry, false); }
219
220 /// Set the next local tree entry. If a TEntryList is set, this function is
221 /// equivalent to `SetEntry()`.
222 ///
223 /// \param entry Entry number of the TChain's current TTree. This is the
224 /// entry number passed for instance by `TSelector::Process(entry)`, i.e.
225 /// within `TSelector::Process()` always use `SetLocalEntry()` and not
226 /// `SetEntry()`!
227 /// \return the `entry`'s read status, i.e. whether the entry is available.
228 EEntryStatus SetLocalEntry(Long64_t entry) { return SetEntryBase(entry, true); }
229
230 EEntryStatus SetEntriesRange(Long64_t beginEntry, Long64_t endEntry);
231
232 /// Get the begin and end entry numbers
233 ///
234 /// \return a pair contained the begin and end entry numbers.
235 std::pair<Long64_t, Long64_t> GetEntriesRange() const { return std::make_pair(fBeginEntry, fEndEntry); }
236
237 /// Restart a Next() loop from entry 0 (of TEntryList index 0 of fEntryList is set).
238 void Restart();
239
240 ///\}
241
243
244 Long64_t GetEntries() const;
245 Long64_t GetEntries(bool force);
246
247 /// Returns the index of the current entry being read.
248 ///
249 /// If `IsChain()`, the returned index corresponds to the global entry number
250 /// (i.e. not the entry number local to the chain's current tree).
251 /// If `fEntryList`, the returned index corresponds to an index in the
252 /// TEntryList; to translate to the TChain's / TTree's entry number pass it
253 /// through `reader.GetEntryList()->GetEntry(reader.GetCurrentEntry())`.
254 Long64_t GetCurrentEntry() const { return fEntry; }
255
256 bool Notify() override;
257
258 /// Return an iterator to the 0th TTree entry.
260 return Iterator_t(*this, 0);
261 }
262 /// Return an iterator beyond the last TTree entry.
263 Iterator_t end() { return Iterator_t(*this, -1); }
264
265protected:
266 using NamedProxies_t = std::unordered_map<std::string, std::unique_ptr<ROOT::Internal::TNamedBranchProxy>>;
267 void Initialize();
268 ROOT::Internal::TNamedBranchProxy* FindProxy(const char* branchname) const
269 {
270 const auto proxyIt = fProxies.find(branchname);
271 return fProxies.end() != proxyIt ? proxyIt->second.get() : nullptr;
272 }
273
275 {
276 auto bpName = p->GetName();
277#ifndef NDEBUG
278 if (fProxies.end() != fProxies.find(bpName)) {
279 std::string err = "A proxy with key " + std::string(bpName) + " was already stored!";
280 throw std::runtime_error(err);
281 }
282#endif
283
284 fProxies[bpName].reset(p);
285 }
286
289
290 EEntryStatus SetEntryBase(Long64_t entry, bool local);
291
292 bool SetProxies();
293
294private:
295
296 std::string GetProxyKey(const char *branchname)
297 {
298 std::string key(branchname);
299 //key += reinterpret_cast<std::uintptr_t>(fTree);
300 return key;
301 }
302
304 kBitIsChain = BIT(14), ///< our tree is a chain
305 kBitHaveWarnedAboutEntryListAttachedToTTree = BIT(15), ///< the tree had a TEntryList and we have warned about that
306 kBitSetEntryBaseCallingLoadTree = BIT(16) ///< SetEntryBase is in the process of calling TChain/TTree::%LoadTree.
307 };
308
309 TTree* fTree = nullptr; ///< tree that's read
310 TEntryList* fEntryList = nullptr; ///< entry list to be used
311 EEntryStatus fEntryStatus = kEntryNotLoaded; ///< status of most recent read request
312 ELoadTreeStatus fLoadTreeStatus = kNoTree; ///< Indicator on how LoadTree was called 'last' time.
313 /// TTree and TChain will notify this object upon LoadTree, leading to a call to TTreeReader::Notify().
315 ROOT::Internal::TBranchProxyDirector* fDirector = nullptr; ///< proxying director, owned
316 std::deque<ROOT::Internal::TFriendProxy*> fFriendProxies; ///< proxying for friend TTrees, owned
317 std::deque<ROOT::Internal::TTreeReaderValueBase*> fValues; ///< readers that use our director
318 NamedProxies_t fProxies; ///< attached ROOT::TNamedBranchProxies; owned
319
320 Long64_t fEntry = -1; ///< Current (non-local) entry of fTree or of fEntryList if set.
321
322 /// The end of the entry loop. When set (i.e. >= 0), it provides a way
323 /// to stop looping over the TTree when we reach a certain entry: Next()
324 /// returns false when GetCurrentEntry() reaches fEndEntry.
326 Long64_t fBeginEntry = 0LL; ///< This allows us to propagate the range to the TTreeCache
327 bool fProxiesSet = false; ///< True if the proxies have been set, false otherwise
328 bool fSetEntryBaseCallingLoadTree = false; ///< True if during the LoadTree execution triggered by SetEntryBase.
329
332
333 ClassDefOverride(TTreeReader, 0); // A simple interface to read trees
334};
335
336#endif // defined TTreeReader
long long Long64_t
Definition RtypesCore.h:80
#define BIT(n)
Definition Rtypes.h:85
#define ClassDefOverride(name, id)
Definition Rtypes.h:341
winID h TVirtualViewer3D TVirtualGLPainter p
Base class of TTreeReaderArray.
Base class of TTreeReaderValue.
This class is used to 'drive' and hold a serie of TBranchProxy objects which represent and give acces...
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:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
Iterate through the entries of a TTree.
Definition TTreeReader.h:56
const Long64_t * const_pointer
Definition TTreeReader.h:69
const Long64_t value_type
Definition TTreeReader.h:66
Iterator_t & operator++()
Increment the iterator (prefix ++i).
Iterator_t()
Default-initialize the iterator as "past the end".
Definition TTreeReader.h:73
const Long64_t & operator*() const
Long64_t fEntry
Entry number of the tree referenced by this iterator; -1 is invalid.
Definition TTreeReader.h:58
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:77
const Long64_t & reference
Definition TTreeReader.h:70
bool operator==(const Iterator_t &lhs) const
Compare two iterators for equality.
Definition TTreeReader.h:81
TTreeReader * fReader
The reader we select the entries on.
Definition TTreeReader.h:59
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:62
std::input_iterator_tag iterator_category
Definition TTreeReader.h:65
bool operator!=(const Iterator_t &lhs) const
Compare two iterators for inequality.
Iterator_t operator++(int)
Increment the iterator (postfix i++).
const Long64_t * pointer
Definition TTreeReader.h:68
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.
ELoadTreeStatus fLoadTreeStatus
Indicator on how LoadTree was called 'last' time.
void SetTree(const char *keyname, TEntryList *entryList=nullptr)
bool IsInvalid() const
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.
~TTreeReader() override
Tell all value readers that the tree reader does not exist anymore.
TNotifyLink< TTreeReader > fNotify
TTree and TChain will notify this object upon LoadTree, leading to a call to TTreeReader::Notify().
bool fProxiesSet
True if the proxies have been set, false otherwise.
bool 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
bool fSetEntryBaseCallingLoadTree
True if during the LoadTree execution triggered by SetEntryBase.
std::deque< ROOT::Internal::TTreeReaderValueBase * > fValues
readers that use our director
bool RegisterValueReader(ROOT::Internal::TTreeReaderValueBase *reader)
Add a value reader for this tree.
TTree * fTree
tree that's read
ROOT::Internal::TBranchProxyDirector * fDirector
proxying director, owned
TTree * GetTree() const
Iterator_t end()
Return an iterator beyond the last TTree entry.
EEntryStatus SetEntriesRange(Long64_t beginEntry, Long64_t endEntry)
Set the range of entries to be loaded by Next(); end will not be loaded.
std::deque< ROOT::Internal::TFriendProxy * > fFriendProxies
proxying for friend TTrees, owned
EEntryStatus SetEntryBase(Long64_t entry, bool local)
Load an entry into the tree, return the status of the read.
std::string GetProxyKey(const char *branchname)
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).
TEntryList * fEntryList
entry list to be used
Long64_t fEntry
Current (non-local) entry of fTree or of fEntryList if set.
bool Notify() override
Notify director and values of a change in 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.
bool SetProxies()
Tell readers we now have a tree.
NamedProxies_t fProxies
attached ROOT::TNamedBranchProxies; owned
TEntryList * GetEntryList() const
Iterator_t begin()
Return an iterator to the 0th TTree entry.
TTreeReader(const char *keyname, TEntryList *entryList=nullptr)
bool Next()
Move to the next entry (or index of the TEntryList if that is set).
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]
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
virtual Long64_t GetEntriesFast() const
Definition TTree.h:465
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...