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 <string>
33
34class TDictionary;
35class TDirectory;
36class TFileCollection;
37
38namespace ROOT {
39namespace Internal {
41class TFriendProxy;
42} // namespace Internal
43} // namespace ROOT
44
45class TTreeReader : public TObject {
46public:
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
79 /// Compare two iterators for equality.
80 bool operator==(const Iterator_t &lhs) const
81 {
82 // From C++14: value initialized (past-end) it compare equal.
83 if (!IsValid() && !lhs.IsValid())
84 return true;
85 // The iterators refer to different readers
86 if (fReader != lhs.fReader)
87 return false;
88 // #16249: range based loop and the tree has zero entries
89 // as well as analogous cases.
90 // Getting the number of events can have a cost, for example in
91 // case of chains of remote files accessible with high latency.
92 // However, it is reasonable to assume that if iterators are
93 // being compared is because an iteration is taking place,
94 // therefore such cost has to be paid anyway, it's just
95 // anticipated.
96 if (fReader->GetTree()->GetEntriesFast() == 0 && fEntry == 0 && !lhs.IsValid()) {
97 return true;
98 }
99 if (lhs.fReader->GetTree()->GetEntriesFast() == 0 && lhs.fEntry == 0 && !IsValid()) {
100 return true;
101 }
102 return fEntry == lhs.fEntry;
103 }
104
105 /// Compare two iterators for inequality.
106 bool operator!=(const Iterator_t &lhs) const { return !(*this == lhs); }
107
108 /// Increment the iterator (postfix i++).
110 {
111 Iterator_t ret = *this;
112 this->operator++();
113 return ret;
114 }
115
116 /// Increment the iterator (prefix ++i).
118 {
119 if (IsValid()) {
120 ++fEntry;
121 // Force validity check of new fEntry.
122 this->operator*();
123 // Don't set the old entry: op* will if needed, and
124 // in most cases it just adds a lot of spinning back
125 // and forth: in most cases the sequence is ++i; *i.
126 }
127 return *this;
128 }
129
130 /// Set the entry number in the reader and return it.
132 {
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 { return **const_cast<Iterator_t *>(this); }
144 };
145
147
149 kEntryValid = 0, ///< data read okay
150 kEntryNotLoaded, ///< no entry has been loaded yet
151 kEntryNoTree, ///< the tree does not exist
152 kEntryNotFound, ///< the tree entry number does not exist
153 kEntryChainSetupError, ///< problem in accessing a chain element, e.g. file without the tree
154 kEntryChainFileError, ///< problem in opening a chain's file
155 kEntryDictionaryError, ///< problem reading dictionary info from tree
156 kEntryBeyondEnd, ///< last entry loop has reached its end
157 kEntryBadReader, ///< One of the readers was not successfully initialized.
158 kIndexedFriendNoMatch, ///< A friend with TTreeIndex doesn't have an entry for this index
159 kMissingBranchWhenSwitchingTree, ///< A branch was not found when switching to the next TTree in the chain
160 kEntryUnknownError ///< LoadTree return less than -6, 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 kMissingBranchFromTree ///< Missing expected branch when loading new tree
169 };
170
171 static constexpr const char *const fgEntryStatusText[kEntryUnknownError + 1] = {
172 "valid entry",
173 "the tree does not exist",
174 "the tree entry number does not exist",
175 "cannot access chain element",
176 "problem in opening a chain's file",
177 "problem reading dictionary info from tree",
178 "last entry loop has reached its end",
179 "one of the readers was not successfully initialized",
180 "A friend with TTreeIndex doesn't have an entry for this index",
181 "A branch was not found when switching to the next TTree in the chain",
182 "LoadTree return less than -6, likely a 'newer' error code"};
183
184 TTreeReader();
185
186 TTreeReader(TTree *tree, TEntryList *entryList = nullptr, bool warnAboutLongerFriends = true,
187 const std::vector<std::string> &suppressErrorsForMissingBranches = {});
188 TTreeReader(const char *keyname, TDirectory *dir, TEntryList *entryList = nullptr);
189 TTreeReader(const char *keyname, TEntryList *entryList = nullptr) : TTreeReader(keyname, nullptr, entryList) {}
190
191 ~TTreeReader() override;
192
193 void SetTree(TTree *tree, TEntryList *entryList = nullptr);
194 void SetTree(const char *keyname, TEntryList *entryList = nullptr) { SetTree(keyname, nullptr, entryList); }
195 void SetTree(const char *keyname, TDirectory *dir, TEntryList *entryList = nullptr);
196
197 bool IsChain() const { return TestBit(kBitIsChain); }
198
199 bool IsInvalid() const { return fLoadTreeStatus == kNoTree; }
200
201 TTree *GetTree() const { return fTree; }
202 TEntryList *GetEntryList() const { return fEntryList; }
203
204 ///\{ \name Entry setters
205
206 /// Move to the next entry (or index of the TEntryList if that is set).
207 ///
208 /// \return false if the previous entry was already the last entry. This allows
209 /// the function to be used in `while (reader.Next()) { ... }`
210 bool Next() { return SetEntry(GetCurrentEntry() + 1) == kEntryValid; }
211
212 /// Set the next entry (or index of the TEntryList if that is set).
213 ///
214 /// \param entry If not TEntryList is set, the entry is a global entry (i.e.
215 /// not the entry number local to the chain's current tree).
216 /// \returns the `entry`'s read status, i.e. whether the entry is available.
218
219 /// Set the next local tree entry. If a TEntryList is set, this function is
220 /// equivalent to `SetEntry()`.
221 ///
222 /// \param entry Entry number of the TChain's current TTree. This is the
223 /// entry number passed for instance by `TSelector::Process(entry)`, i.e.
224 /// within `TSelector::Process()` always use `SetLocalEntry()` and not
225 /// `SetEntry()`!
226 /// \return the `entry`'s read status, i.e. whether the entry is available.
228
230
231 /// Get the begin and end entry numbers
232 ///
233 /// \return a pair contained the begin and end entry numbers.
234 std::pair<Long64_t, Long64_t> GetEntriesRange() const { return std::make_pair(fBeginEntry, fEndEntry); }
235
236 /// Restart a Next() loop from entry 0 (of TEntryList index 0 of fEntryList is set).
237 void Restart();
238
239 ///\}
240
242
243 Long64_t GetEntries() const;
245
246 /// Returns the index of the current entry being read.
247 ///
248 /// If `IsChain()`, the returned index corresponds to the global entry number
249 /// (i.e. not the entry number local to the chain's current tree).
250 /// If `fEntryList`, the returned index corresponds to an index in the
251 /// TEntryList; to translate to the TChain's / TTree's entry number pass it
252 /// through `reader.GetEntryList()->GetEntry(reader.GetCurrentEntry())`.
253 Long64_t GetCurrentEntry() const { return fEntry; }
254
255 bool Notify() override;
256
257 /// Return an iterator to the 0th TTree entry.
258 Iterator_t begin() { return Iterator_t(*this, 0); }
259 /// Return an iterator beyond the last TTree entry.
260 Iterator_t end() { return Iterator_t(*this, -1); }
261
262protected:
263 using NamedProxies_t = std::unordered_map<std::string, std::unique_ptr<ROOT::Internal::TNamedBranchProxy>>;
264 void Initialize();
266 {
267 const auto proxyIt = fProxies.find(branchname);
268 return fProxies.end() != proxyIt ? proxyIt->second.get() : nullptr;
269 }
270
271 void AddProxy(std::unique_ptr<ROOT::Internal::TNamedBranchProxy> p)
272 {
273 auto bpName = p->GetName();
274#ifndef NDEBUG
275 if (fProxies.end() != fProxies.find(bpName)) {
276 std::string err = "A proxy with key " + std::string(bpName) + " was already stored!";
277 throw std::runtime_error(err);
278 }
279#endif
280
281 fProxies[bpName] = std::move(p);
282 }
283
285
288
289 EEntryStatus SetEntryBase(Long64_t entry, bool local);
290
291 bool SetProxies();
292
293private:
294 std::string GetProxyKey(const char *branchname)
295 {
296 std::string key(branchname);
297 // key += reinterpret_cast<std::uintptr_t>(fTree);
298 return key;
299 }
300
302 kBitIsChain = BIT(14), ///< our tree is a chain
304 BIT(15), ///< the tree had a TEntryList and we have warned about that
305 kBitSetEntryBaseCallingLoadTree = BIT(16), ///< SetEntryBase is in the process of calling TChain/TTree::%LoadTree.
306 kBitIsExternalTree = BIT(17) ///< we do not own the tree
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 std::unique_ptr<ROOT::Internal::TBranchProxyDirector> fDirector{nullptr}; ///< proxying director
316 /// Proxies to friend trees, created in TTreeReader[Value,Array]::CreateProxy
317 std::vector<std::unique_ptr<ROOT::Internal::TFriendProxy>> fFriendProxies;
318 std::deque<ROOT::Internal::TTreeReaderValueBase *> fValues; ///< readers that use our director
319 NamedProxies_t fProxies; ///< attached ROOT::TNamedBranchProxies; owned
320
321 Long64_t fEntry = -1; ///< Current (non-local) entry of fTree or of fEntryList if set.
322
323 /// The end of the entry loop. When set (i.e. >= 0), it provides a way
324 /// to stop looping over the TTree when we reach a certain entry: Next()
325 /// returns false when GetCurrentEntry() reaches fEndEntry.
327 Long64_t fBeginEntry = 0LL; ///< This allows us to propagate the range to the TTreeCache
328 bool fProxiesSet = false; ///< True if the proxies have been set, false otherwise
329 bool fSetEntryBaseCallingLoadTree = false; ///< True if during the LoadTree execution triggered by SetEntryBase.
330
331 // Flag to activate or deactivate warnings in case the friend trees have
332 // more entries than the main one. In some cases we may want to deactivate
333 // this behaviour, notably in multithreaded runs where we have to partition
334 // the main tree but keep the entire friend trees in every thread to ensure
335 // alignment.
338
339 // List of branches for which we want to suppress the printed error about
340 // missing branch when switching to a new tree
341 std::vector<std::string> fSuppressErrorsForMissingBranches{};
342 std::vector<std::string> fMissingProxies{};
343
346
347 ClassDefOverride(TTreeReader, 0); // A simple interface to read trees
348};
349
350#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:199
Iterate through the entries of a TTree.
Definition TTreeReader.h:56
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
bool operator==(const Iterator_t &lhs) const
Compare two iterators for equality.
Definition TTreeReader.h:80
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++).
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:45
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,...
std::deque< ROOT::Internal::TTreeReaderValueBase * > fValues
readers that use our director
EEntryStatus fEntryStatus
status of most recent read request
std::vector< std::string > fSuppressErrorsForMissingBranches
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
TTree * GetTree() const
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
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...