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// Author: Vincenzo Eduardo Padulano CERN 09/2024
4
5/*************************************************************************
6 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#ifndef ROOT_TTreeReader
14#define ROOT_TTreeReader
15
16
17////////////////////////////////////////////////////////////////////////////
18// //
19// TTreeReader //
20// //
21// A simple interface for reading trees or chains. //
22// //
23// //
24////////////////////////////////////////////////////////////////////////////
25
26#include "TTree.h"
27#include "TTreeReaderUtils.h"
28#include "TNotifyLink.h"
29
30#include <deque>
31#include <iterator>
32#include <unordered_map>
33#include <string>
34
35class TDictionary;
36class TDirectory;
37class TFileCollection;
38
39namespace ROOT {
40namespace Internal {
42 class TFriendProxy;
43}
44}
45
46class TTreeReader: public TObject {
47public:
48
49 ///\class TTreeReader::Iterator_t
50 /// Iterate through the entries of a TTree.
51 ///
52 /// This iterator drives the associated TTreeReader; its
53 /// dereferencing (and actually even the iteration) will
54 /// set the entry number represented by this iterator.
55 /// It does not really represent a data element; it simply
56 /// returns the entry number (or -1 once the end of the tree
57 /// is reached).
58 class Iterator_t {
59 private:
60 Long64_t fEntry; ///< Entry number of the tree referenced by this iterator; -1 is invalid.
61 TTreeReader* fReader; ///< The reader we select the entries on.
62
63 /// Whether the iterator points to a valid entry.
64 bool IsValid() const { return fEntry >= 0; }
65
66 public:
67 using iterator_category = std::input_iterator_tag;
68 using value_type = const Long64_t;
70 using pointer = const Long64_t *;
71 using const_pointer = const Long64_t *;
72 using reference = const Long64_t &;
73
74 /// Default-initialize the iterator as "past the end".
75 Iterator_t(): fEntry(-1), fReader(nullptr) {}
76
77 /// Initialize the iterator with the reader it steers and a
78 /// tree entry number; -1 is invalid.
80 fEntry(entry), fReader(&reader) {}
81
82 /// Compare two iterators for equality.
83 bool operator==(const Iterator_t &lhs) const
84 {
85 // From C++14: value initialized (past-end) it compare equal.
86 if (!IsValid() && !lhs.IsValid())
87 return true;
88 // The iterators refer to different readers
89 if (fReader != lhs.fReader)
90 return false;
91 // #16249: range based loop and the tree has zero entries
92 // as well as analogous cases.
93 // Getting the number of events can have a cost, for example in
94 // case of chains of remote files accessible with high latency.
95 // However, it is reasonable to assume that if iterators are
96 // being compared is because an iteration is taking place,
97 // therefore such cost has to be paid anyway, it's just
98 // anticipated.
99 if (fReader->GetTree()->GetEntriesFast() == 0 && fEntry == 0 && !lhs.IsValid()) {
100 return true;
101 }
102 if (lhs.fReader->GetTree()->GetEntriesFast() == 0 && lhs.fEntry == 0 && !IsValid()) {
103 return true;
104 }
105 return fEntry == lhs.fEntry;
106 }
107
108 /// Compare two iterators for inequality.
109 bool operator!=(const Iterator_t& lhs) const {
110 return !(*this == lhs);
111 }
112
113 /// Increment the iterator (postfix i++).
115 Iterator_t ret = *this;
116 this->operator++();
117 return ret;
118 }
119
120 /// Increment the iterator (prefix ++i).
122 if (IsValid()) {
123 ++fEntry;
124 // Force validity check of new fEntry.
125 this->operator*();
126 // Don't set the old entry: op* will if needed, and
127 // in most cases it just adds a lot of spinning back
128 // and forth: in most cases the sequence is ++i; *i.
129 }
130 return *this;
131 }
132
133 /// Set the entry number in the reader and return it.
135 if (IsValid()) {
136 // If we cannot access that entry, mark the iterator invalid.
138 fEntry = -1;
139 }
140 }
141 // There really is no data in this iterator; return the number.
142 return fEntry;
143 }
144
145 const Long64_t& operator*() const {
146 return **const_cast<Iterator_t*>(this);
147 }
148 };
149
151
153 kEntryValid = 0, ///< data read okay
154 kEntryNotLoaded, ///< no entry has been loaded yet
155 kEntryNoTree, ///< the tree does not exist
156 kEntryNotFound, ///< the tree entry number does not exist
157 kEntryChainSetupError, ///< problem in accessing a chain element, e.g. file without the tree
158 kEntryChainFileError, ///< problem in opening a chain's file
159 kEntryDictionaryError, ///< problem reading dictionary info from tree
160 kEntryBeyondEnd, ///< last entry loop has reached its end
161 kEntryBadReader, ///< One of the readers was not successfully initialized.
162 kIndexedFriendNoMatch, ///< A friend with TTreeIndex doesn't have an entry for this index
163 kMissingBranchWhenSwitchingTree, ///< A branch was not found when switching to the next TTree in the chain
164 kEntryUnknownError ///< LoadTree return less than -6, likely a 'newer' error code.
165 };
166
168 kNoTree = 0, ///< default state, no TTree is connected (formerly 'Zombie' state)
169 kLoadTreeNone, ///< Notify has not been called yet.
170 kInternalLoadTree, ///< Notify/LoadTree was last called from SetEntryBase
171 kExternalLoadTree, ///< User code called LoadTree directly.
172 kMissingBranchFromTree ///< Missing expected branch when loading new tree
173 };
174
175 static constexpr const char *const fgEntryStatusText[kEntryUnknownError + 1] = {
176 "valid entry",
177 "the tree does not exist",
178 "the tree entry number does not exist",
179 "cannot access chain element",
180 "problem in opening a chain's file",
181 "problem reading dictionary info from tree",
182 "last entry loop has reached its end",
183 "one of the readers was not successfully initialized",
184 "A friend with TTreeIndex doesn't have an entry for this index",
185 "A branch was not found when switching to the next TTree in the chain",
186 "LoadTree return less than -6, likely a 'newer' error code"};
187
188 TTreeReader();
189
190 TTreeReader(TTree *tree, TEntryList *entryList = nullptr, bool warnAboutLongerFriends = true,
191 const std::vector<std::string> &suppressErrorsForMissingBranches = {});
192 TTreeReader(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
193 TTreeReader(const char *keyname, TEntryList *entryList = nullptr) : TTreeReader(keyname, nullptr, entryList) {}
194
195 ~TTreeReader() override;
196
197 void SetTree(TTree* tree, TEntryList* entryList = nullptr);
198 void SetTree(const char* keyname, TEntryList* entryList = nullptr) {
199 SetTree(keyname, nullptr, entryList);
200 }
201 void SetTree(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
202
203 bool IsChain() const { return TestBit(kBitIsChain); }
204
205 bool IsInvalid() const { return fLoadTreeStatus == kNoTree; }
206
207 TTree* GetTree() const { return fTree; }
208 TEntryList* GetEntryList() const { return fEntryList; }
209
210 ///\{ \name Entry setters
211
212 /// Move to the next entry (or index of the TEntryList if that is set).
213 ///
214 /// \return false if the previous entry was already the last entry. This allows
215 /// the function to be used in `while (reader.Next()) { ... }`
216 bool Next() {
217 return SetEntry(GetCurrentEntry() + 1) == kEntryValid;
218 }
219
220 /// Set the next entry (or index of the TEntryList if that is set).
221 ///
222 /// \param entry If not TEntryList is set, the entry is a global entry (i.e.
223 /// not the entry number local to the chain's current tree).
224 /// \returns the `entry`'s read status, i.e. whether the entry is available.
225 EEntryStatus SetEntry(Long64_t entry) { return SetEntryBase(entry, false); }
226
227 /// Set the next local tree entry. If a TEntryList is set, this function is
228 /// equivalent to `SetEntry()`.
229 ///
230 /// \param entry Entry number of the TChain's current TTree. This is the
231 /// entry number passed for instance by `TSelector::Process(entry)`, i.e.
232 /// within `TSelector::Process()` always use `SetLocalEntry()` and not
233 /// `SetEntry()`!
234 /// \return the `entry`'s read status, i.e. whether the entry is available.
235 EEntryStatus SetLocalEntry(Long64_t entry) { return SetEntryBase(entry, true); }
236
237 EEntryStatus SetEntriesRange(Long64_t beginEntry, Long64_t endEntry);
238
239 /// Get the begin and end entry numbers
240 ///
241 /// \return a pair contained the begin and end entry numbers.
242 std::pair<Long64_t, Long64_t> GetEntriesRange() const { return std::make_pair(fBeginEntry, fEndEntry); }
243
244 /// Restart a Next() loop from entry 0 (of TEntryList index 0 of fEntryList is set).
245 void Restart();
246
247 ///\}
248
250
251 Long64_t GetEntries() const;
252 Long64_t GetEntries(bool force);
253
254 /// Returns the index of the current entry being read.
255 ///
256 /// If `IsChain()`, the returned index corresponds to the global entry number
257 /// (i.e. not the entry number local to the chain's current tree).
258 /// If `fEntryList`, the returned index corresponds to an index in the
259 /// TEntryList; to translate to the TChain's / TTree's entry number pass it
260 /// through `reader.GetEntryList()->GetEntry(reader.GetCurrentEntry())`.
261 Long64_t GetCurrentEntry() const { return fEntry; }
262
263 bool Notify() override;
264
265 /// Return an iterator to the 0th TTree entry.
267 return Iterator_t(*this, 0);
268 }
269 /// Return an iterator beyond the last TTree entry.
270 Iterator_t end() { return Iterator_t(*this, -1); }
271
272protected:
273 using NamedProxies_t = std::unordered_map<std::string, std::unique_ptr<ROOT::Internal::TNamedBranchProxy>>;
274 void Initialize();
275 ROOT::Internal::TNamedBranchProxy* FindProxy(const char* branchname) const
276 {
277 const auto proxyIt = fProxies.find(branchname);
278 return fProxies.end() != proxyIt ? proxyIt->second.get() : nullptr;
279 }
280
281 void AddProxy(std::unique_ptr<ROOT::Internal::TNamedBranchProxy> p)
282 {
283 auto bpName = p->GetName();
284#ifndef NDEBUG
285 if (fProxies.end() != fProxies.find(bpName)) {
286 std::string err = "A proxy with key " + std::string(bpName) + " was already stored!";
287 throw std::runtime_error(err);
288 }
289#endif
290
291 fProxies[bpName] = std::move(p);
292 }
293
294 ROOT::Internal::TFriendProxy &AddFriendProxy(std::size_t friendIdx);
295
298
299 EEntryStatus SetEntryBase(Long64_t entry, bool local);
300
301 bool SetProxies();
302
303private:
304 std::string GetProxyKey(const char *branchname)
305 {
306 std::string key(branchname);
307 //key += reinterpret_cast<std::uintptr_t>(fTree);
308 return key;
309 }
310
312 kBitIsChain = BIT(14), ///< our tree is a chain
313 kBitHaveWarnedAboutEntryListAttachedToTTree = BIT(15), ///< the tree had a TEntryList and we have warned about that
314 kBitSetEntryBaseCallingLoadTree = BIT(16), ///< SetEntryBase is in the process of calling TChain/TTree::%LoadTree.
315 kBitIsExternalTree = BIT(17) ///< we do not own the tree
316 };
317
318 TTree* fTree = nullptr; ///< tree that's read
319 TEntryList* fEntryList = nullptr; ///< entry list to be used
320 EEntryStatus fEntryStatus = kEntryNotLoaded; ///< status of most recent read request
321 ELoadTreeStatus fLoadTreeStatus = kNoTree; ///< Indicator on how LoadTree was called 'last' time.
322 /// TTree and TChain will notify this object upon LoadTree, leading to a call to TTreeReader::Notify().
324 std::unique_ptr<ROOT::Internal::TBranchProxyDirector> fDirector{nullptr}; ///< proxying director
325 /// Proxies to friend trees, created in TTreeReader[Value,Array]::CreateProxy
326 std::vector<std::unique_ptr<ROOT::Internal::TFriendProxy>> fFriendProxies;
327 std::deque<ROOT::Internal::TTreeReaderValueBase*> fValues; ///< readers that use our director
328 NamedProxies_t fProxies; ///< attached ROOT::TNamedBranchProxies; owned
329
330 Long64_t fEntry = -1; ///< Current (non-local) entry of fTree or of fEntryList if set.
331
332 /// The end of the entry loop. When set (i.e. >= 0), it provides a way
333 /// to stop looping over the TTree when we reach a certain entry: Next()
334 /// returns false when GetCurrentEntry() reaches fEndEntry.
336 Long64_t fBeginEntry = 0LL; ///< This allows us to propagate the range to the TTreeCache
337 bool fProxiesSet = false; ///< True if the proxies have been set, false otherwise
338 bool fSetEntryBaseCallingLoadTree = false; ///< True if during the LoadTree execution triggered by SetEntryBase.
339
340 // Flag to activate or deactivate warnings in case the friend trees have
341 // more entries than the main one. In some cases we may want to deactivate
342 // this behaviour, notably in multithreaded runs where we have to partition
343 // the main tree but keep the entire friend trees in every thread to ensure
344 // alignment.
347
348 // List of branches for which we want to suppress the printed error about
349 // missing branch when switching to a new tree
350 std::vector<std::string> fSuppressErrorsForMissingBranches{};
351 std::vector<std::string> fMissingProxies{};
352
355
356 ClassDefOverride(TTreeReader, 0); // A simple interface to read trees
357};
358
359#endif // defined TTreeReader
long long Long64_t
Definition RtypesCore.h:69
#define BIT(n)
Definition Rtypes.h:90
#define ClassDefOverride(name, id)
Definition Rtypes.h:346
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.
Concrete implementation of the proxy around a Friend Tree.
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:456
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
Iterate through the entries of a TTree.
Definition TTreeReader.h:58
const Long64_t * const_pointer
Definition TTreeReader.h:71
const Long64_t value_type
Definition TTreeReader.h:68
Iterator_t & operator++()
Increment the iterator (prefix ++i).
Iterator_t()
Default-initialize the iterator as "past the end".
Definition TTreeReader.h:75
const Long64_t & operator*() const
Long64_t fEntry
Entry number of the tree referenced by this iterator; -1 is invalid.
Definition TTreeReader.h:60
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:79
const Long64_t & reference
Definition TTreeReader.h:72
bool operator==(const Iterator_t &lhs) const
Compare two iterators for equality.
Definition TTreeReader.h:83
TTreeReader * fReader
The reader we select the entries on.
Definition TTreeReader.h:61
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:64
std::input_iterator_tag iterator_category
Definition TTreeReader.h:67
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:70
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:46
TTreeReader()
Default constructor. Call SetTree to connect to a TTree.
std::vector< std::string > fMissingProxies
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::vector< std::string > fSuppressErrorsForMissingBranches
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
void AddProxy(std::unique_ptr< ROOT::Internal::TNamedBranchProxy > p)
@ kEntryNotFound
the tree entry number does not exist
@ kIndexedFriendNoMatch
A friend with TTreeIndex doesn't have an entry for this index.
@ kEntryUnknownError
LoadTree return less than -6, 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
@ kMissingBranchWhenSwitchingTree
A branch was not found when switching to the next TTree in the chain.
@ 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
bool fWarnAboutLongerFriends
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.
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)
void WarnIfFriendsHaveMoreEntries()
EEntryStatus GetEntryStatus() const
@ kInternalLoadTree
Notify/LoadTree was last called from SetEntryBase.
@ kMissingBranchFromTree
Missing expected branch when loading new tree.
@ 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 DeregisterValueReader(ROOT::Internal::TTreeReaderValueBase *reader)
Remove a value reader for this tree.
@ kBitIsExternalTree
we do not own the 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
ROOT::Internal::TFriendProxy & AddFriendProxy(std::size_t friendIdx)
TEntryList * GetEntryList() const
std::vector< std::unique_ptr< ROOT::Internal::TFriendProxy > > fFriendProxies
Proxies to friend trees, created in TTreeReader[Value,Array]::CreateProxy.
Iterator_t begin()
Return an iterator to the 0th TTree entry.
std::unique_ptr< ROOT::Internal::TBranchProxyDirector > fDirector
proxying director
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
Return a number greater or equal to the total number of entries in the dataset.
Definition TTree.h:505
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...