Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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// 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 <set>
33#include <string>
34
35class TDictionary;
36class TDirectory;
37class TFileCollection;
38
39namespace ROOT {
40namespace Internal {
42class TFriendProxy;
43} // namespace Internal
44} // namespace ROOT
45
46class TTreeReader : public TObject {
47public:
48 ///\class TTreeReader::Iterator_t
49 /// Iterate through the entries of a TTree.
50 ///
51 /// This iterator drives the associated TTreeReader; its
52 /// dereferencing (and actually even the iteration) will
53 /// set the entry number represented by this iterator.
54 /// It does not really represent a data element; it simply
55 /// returns the entry number (or -1 once the end of the tree
56 /// is reached).
57 class Iterator_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 using iterator_category = std::input_iterator_tag;
67 using value_type = const Long64_t;
69 using pointer = const Long64_t *;
70 using const_pointer = const Long64_t *;
71 using reference = const Long64_t &;
72
73 /// Default-initialize the iterator as "past the end".
74 Iterator_t() : fEntry(-1), fReader(nullptr) {}
75
76 /// Initialize the iterator with the reader it steers and a
77 /// tree entry number; -1 is invalid.
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 { return !(*this == lhs); }
108
109 /// Increment the iterator (postfix i++).
111 {
112 Iterator_t ret = *this;
113 this->operator++();
114 return ret;
115 }
116
117 /// Increment the iterator (prefix ++i).
119 {
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 {
134 if (IsValid()) {
135 // If we cannot access that entry, mark the iterator invalid.
137 fEntry = -1;
138 }
139 }
140 // There really is no data in this iterator; return the number.
141 return fEntry;
142 }
143
144 const Long64_t &operator*() const { return **const_cast<Iterator_t *>(this); }
145 };
146
148
150 kEntryValid = 0, ///< data read okay
151 kEntryNotLoaded, ///< no entry has been loaded yet
152 kEntryNoTree, ///< the tree does not exist
153 kEntryNotFound, ///< the tree entry number does not exist
154 kEntryChainSetupError, ///< problem in accessing a chain element, e.g. file without the tree
155 kEntryChainFileError, ///< problem in opening a chain's file
156 kEntryDictionaryError, ///< problem reading dictionary info from tree
157 kEntryBeyondEnd, ///< last entry loop has reached its end
158 kEntryBadReader, ///< One of the readers was not successfully initialized.
159 kIndexedFriendNoMatch, ///< A friend with TTreeIndex doesn't have an entry for this index
160 kMissingBranchWhenSwitchingTree, ///< A branch was not found when switching to the next TTree in the chain
161 kEntryUnknownError ///< LoadTree return less than -6, likely a 'newer' error code.
162 };
163
165 kNoTree = 0, ///< default state, no TTree is connected (formerly 'Zombie' state)
166 kLoadTreeNone, ///< Notify has not been called yet.
167 kInternalLoadTree, ///< Notify/LoadTree was last called from SetEntryBase
168 kExternalLoadTree, ///< User code called LoadTree directly.
169 kMissingBranchFromTree ///< Missing expected branch when loading new tree
170 };
171
172 static constexpr const char *const fgEntryStatusText[kEntryUnknownError + 1] = {
173 "valid entry",
174 "the tree does not exist",
175 "the tree entry number does not exist",
176 "cannot access chain element",
177 "problem in opening a chain's file",
178 "problem reading dictionary info from tree",
179 "last entry loop has reached its end",
180 "one of the readers was not successfully initialized",
181 "A friend with TTreeIndex doesn't have an entry for this index",
182 "A branch was not found when switching to the next TTree in the chain",
183 "LoadTree return less than -6, likely a 'newer' error code"};
184
185 TTreeReader();
186
187 TTreeReader(TTree *tree, TEntryList *entryList = nullptr, bool warnAboutLongerFriends = true,
188 const std::set<std::string> &suppressErrorsForMissingBranches = {});
189 TTreeReader(const char *keyname, TDirectory *dir, TEntryList *entryList = nullptr);
190 TTreeReader(const char *keyname, TEntryList *entryList = nullptr) : TTreeReader(keyname, nullptr, entryList) {}
191
192 ~TTreeReader() override;
193
194 void SetTree(TTree *tree, TEntryList *entryList = nullptr);
195 void SetTree(const char *keyname, TEntryList *entryList = nullptr) { SetTree(keyname, nullptr, entryList); }
196 void SetTree(const char *keyname, TDirectory *dir, TEntryList *entryList = nullptr);
197
198 bool IsChain() const { return TestBit(kBitIsChain); }
199
200 bool IsInvalid() const { return fLoadTreeStatus == kNoTree; }
201
202 TTree *GetTree() const { return fTree; }
203 TEntryList *GetEntryList() const { return fEntryList; }
204
205 ///\{ \name Entry setters
206
207 /// Move to the next entry (or index of the TEntryList if that is set).
208 ///
209 /// \return false if the previous entry was already the last entry. This allows
210 /// the function to be used in `while (reader.Next()) { ... }`
211 bool Next() { return SetEntry(GetCurrentEntry() + 1) == kEntryValid; }
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.
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.
229
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;
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.
259 Iterator_t begin() { return Iterator_t(*this, 0); }
260 /// Return an iterator beyond the last TTree entry.
261 Iterator_t end() { return Iterator_t(*this, -1); }
262
267
268protected:
269 using NamedProxies_t = std::unordered_map<std::string, std::unique_ptr<ROOT::Internal::TNamedBranchProxy>>;
270 void Initialize();
272 {
273 const auto proxyIt = fProxies.find(branchname);
274 return fProxies.end() != proxyIt ? proxyIt->second.get() : nullptr;
275 }
276
277 void AddProxy(std::unique_ptr<ROOT::Internal::TNamedBranchProxy> p)
278 {
279 auto bpName = p->GetName();
280#ifndef NDEBUG
281 if (fProxies.end() != fProxies.find(bpName)) {
282 std::string err = "A proxy with key " + std::string(bpName) + " was already stored!";
283 throw std::runtime_error(err);
284 }
285#endif
286
287 fProxies[bpName] = std::move(p);
288 }
289
291
294
295 EEntryStatus SetEntryBase(Long64_t entry, bool local);
296
297 bool SetProxies();
298
299private:
300 std::string GetProxyKey(const char *branchname)
301 {
302 std::string key(branchname);
303 // key += reinterpret_cast<std::uintptr_t>(fTree);
304 return key;
305 }
306
308 kBitIsChain = BIT(14), ///< our tree is a chain
310 BIT(15), ///< the tree had a TEntryList and we have warned about that
311 kBitSetEntryBaseCallingLoadTree = BIT(16), ///< SetEntryBase is in the process of calling TChain/TTree::%LoadTree.
312 kBitIsExternalTree = BIT(17) ///< we do not own the tree
313 };
314
315 TTree *fTree = nullptr; ///< tree that's read
316 TEntryList *fEntryList = nullptr; ///< entry list to be used
317 EEntryStatus fEntryStatus = kEntryNotLoaded; ///< status of most recent read request
318 ELoadTreeStatus fLoadTreeStatus = kNoTree; ///< Indicator on how LoadTree was called 'last' time.
319 /// TTree and TChain will notify this object upon LoadTree, leading to a call to TTreeReader::Notify().
321 std::unique_ptr<ROOT::Internal::TBranchProxyDirector> fDirector{nullptr}; ///< proxying director
322 /// Proxies to friend trees, created in TTreeReader[Value,Array]::CreateProxy
323 std::vector<std::unique_ptr<ROOT::Internal::TFriendProxy>> fFriendProxies;
324 std::deque<ROOT::Internal::TTreeReaderValueBase *> fValues; ///< readers that use our director
325 NamedProxies_t fProxies; ///< attached ROOT::TNamedBranchProxies; owned
326
327 Long64_t fEntry = -1; ///< Current (non-local) entry of fTree or of fEntryList if set.
328
329 /// The end of the entry loop. When set (i.e. >= 0), it provides a way
330 /// to stop looping over the TTree when we reach a certain entry: Next()
331 /// returns false when GetCurrentEntry() reaches fEndEntry.
333 Long64_t fBeginEntry = 0LL; ///< This allows us to propagate the range to the TTreeCache
334 bool fProxiesSet = false; ///< True if the proxies have been set, false otherwise
335 bool fSetEntryBaseCallingLoadTree = false; ///< True if during the LoadTree execution triggered by SetEntryBase.
336
337 // Flag to activate or deactivate warnings in case the friend trees have
338 // more entries than the main one. In some cases we may want to deactivate
339 // this behaviour, notably in multithreaded runs where we have to partition
340 // the main tree but keep the entire friend trees in every thread to ensure
341 // alignment.
344
345 // List of branches for which we want to suppress the printed error about
346 // missing branch when switching to a new tree
347 std::set<std::string> fSuppressErrorsForMissingBranches{};
348 std::set<std::string> fMissingProxies{};
349
352
353 ClassDefOverride(TTreeReader, 0); // A simple interface to read trees
354};
355
356#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
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:205
Iterate through the entries of a TTree.
Definition TTreeReader.h:57
Iterator_t & operator++()
Increment the iterator (prefix ++i).
Iterator_t()
Default-initialize the iterator as "past the end".
Definition TTreeReader.h:74
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:78
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: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
std::input_iterator_tag iterator_category
Definition TTreeReader.h:66
bool operator!=(const Iterator_t &lhs) const
Compare two iterators for inequality.
Iterator_t operator++(int)
Increment the iterator (postfix i++).
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.
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,...
std::deque< ROOT::Internal::TTreeReaderValueBase * > fValues
readers that use our director
EEntryStatus fEntryStatus
status of most recent read request
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.
bool RegisterValueReader(ROOT::Internal::TTreeReaderValueBase *reader)
Add a value reader for this tree.
TTree * fTree
tree that's read
bool fWarnAboutLongerFriends
std::set< std::string > fMissingProxies
TTree * GetTree() const
void SetSuppressErrorsForMissingBranches(const std::set< std::string > &suppressErrorsForMissingBranches)
Iterator_t end()
Return an iterator beyond the last TTree entry.
std::unordered_map< std::string, std::unique_ptr< ROOT::Internal::TNamedBranchProxy > > NamedProxies_t
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
std::set< std::string > fSuppressErrorsForMissingBranches
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:506
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...