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 // From C++14: value initialized (past-end) it compare equal.
83 if (!IsValid() && !lhs.IsValid()) return true;
84 return fEntry == lhs.fEntry && fReader == lhs.fReader;
85 }
86
87 /// Compare two iterators for inequality.
88 bool operator!=(const Iterator_t& lhs) const {
89 return !(*this == lhs);
90 }
91
92 /// Increment the iterator (postfix i++).
94 Iterator_t ret = *this;
95 this->operator++();
96 return ret;
97 }
98
99 /// Increment the iterator (prefix ++i).
101 if (IsValid()) {
102 ++fEntry;
103 // Force validity check of new fEntry.
104 this->operator*();
105 // Don't set the old entry: op* will if needed, and
106 // in most cases it just adds a lot of spinning back
107 // and forth: in most cases the sequence is ++i; *i.
108 }
109 return *this;
110 }
111
112 /// Set the entry number in the reader and return it.
114 if (IsValid()) {
115 // If we cannot access that entry, mark the iterator invalid.
117 fEntry = -1;
118 }
119 }
120 // There really is no data in this iterator; return the number.
121 return fEntry;
122 }
123
124 const Long64_t& operator*() const {
125 return **const_cast<Iterator_t*>(this);
126 }
127 };
128
130
132 kEntryValid = 0, ///< data read okay
133 kEntryNotLoaded, ///< no entry has been loaded yet
134 kEntryNoTree, ///< the tree does not exist
135 kEntryNotFound, ///< the tree entry number does not exist
136 kEntryChainSetupError, ///< problem in accessing a chain element, e.g. file without the tree
137 kEntryChainFileError, ///< problem in opening a chain's file
138 kEntryDictionaryError, ///< problem reading dictionary info from tree
139 kEntryBeyondEnd, ///< last entry loop has reached its end
140 kEntryBadReader, ///< One of the readers was not successfully initialized.
141 kEntryUnknownError ///< LoadTree return less than -4, likely a 'newer' error code.
142 };
143
145 kNoTree = 0, ///< default state, no TTree is connected (formerly 'Zombie' state)
146 kLoadTreeNone, ///< Notify has not been called yet.
147 kInternalLoadTree, ///< Notify/LoadTree was last called from SetEntryBase
148 kExternalLoadTree ///< User code called LoadTree directly.
149 };
150
151 static constexpr const char * const fgEntryStatusText[kEntryUnknownError + 1] = {
152 "valid entry",
153 "the tree does not exist",
154 "the tree entry number does not exist",
155 "cannot access chain element",
156 "problem in opening a chain's file",
157 "problem reading dictionary info from tree",
158 "last entry loop has reached its end",
159 "one of the readers was not successfully initialized",
160 "LoadTree return less than -4, likely a 'newer' error code"
161 };
162
163 TTreeReader();
164
165 TTreeReader(TTree* tree, TEntryList* entryList = nullptr);
166 TTreeReader(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
167 TTreeReader(const char *keyname, TEntryList *entryList = nullptr) : TTreeReader(keyname, nullptr, entryList) {}
168
169 ~TTreeReader() override;
170
171 void SetTree(TTree* tree, TEntryList* entryList = nullptr);
172 void SetTree(const char* keyname, TEntryList* entryList = nullptr) {
173 SetTree(keyname, nullptr, entryList);
174 }
175 void SetTree(const char* keyname, TDirectory* dir, TEntryList* entryList = nullptr);
176
177 bool IsChain() const { return TestBit(kBitIsChain); }
178
179 bool IsInvalid() const { return fLoadTreeStatus == kNoTree; }
180
181 TTree* GetTree() const { return fTree; }
182 TEntryList* GetEntryList() const { return fEntryList; }
183
184 ///\{ \name Entry setters
185
186 /// Move to the next entry (or index of the TEntryList if that is set).
187 ///
188 /// \return false if the previous entry was already the last entry. This allows
189 /// the function to be used in `while (reader.Next()) { ... }`
190 bool Next() {
191 return SetEntry(GetCurrentEntry() + 1) == kEntryValid;
192 }
193
194 /// Set the next entry (or index of the TEntryList if that is set).
195 ///
196 /// \param entry If not TEntryList is set, the entry is a global entry (i.e.
197 /// not the entry number local to the chain's current tree).
198 /// \returns the `entry`'s read status, i.e. whether the entry is available.
199 EEntryStatus SetEntry(Long64_t entry) { return SetEntryBase(entry, false); }
200
201 /// Set the next local tree entry. If a TEntryList is set, this function is
202 /// equivalent to `SetEntry()`.
203 ///
204 /// \param entry Entry number of the TChain's current TTree. This is the
205 /// entry number passed for instance by `TSelector::Process(entry)`, i.e.
206 /// within `TSelector::Process()` always use `SetLocalEntry()` and not
207 /// `SetEntry()`!
208 /// \return the `entry`'s read status, i.e. whether the entry is available.
209 EEntryStatus SetLocalEntry(Long64_t entry) { return SetEntryBase(entry, true); }
210
211 EEntryStatus SetEntriesRange(Long64_t beginEntry, Long64_t endEntry);
212
213 /// Get the begin and end entry numbers
214 ///
215 /// \return a pair contained the begin and end entry numbers.
216 std::pair<Long64_t, Long64_t> GetEntriesRange() const { return std::make_pair(fBeginEntry, fEndEntry); }
217
218 /// Restart a Next() loop from entry 0 (of TEntryList index 0 of fEntryList is set).
219 void Restart();
220
221 ///\}
222
224
225 Long64_t GetEntries() const;
226 Long64_t GetEntries(bool force);
227
228 /// Returns the index of the current entry being read.
229 ///
230 /// If `IsChain()`, the returned index corresponds to the global entry number
231 /// (i.e. not the entry number local to the chain's current tree).
232 /// If `fEntryList`, the returned index corresponds to an index in the
233 /// TEntryList; to translate to the TChain's / TTree's entry number pass it
234 /// through `reader.GetEntryList()->GetEntry(reader.GetCurrentEntry())`.
235 Long64_t GetCurrentEntry() const { return fEntry; }
236
237 bool Notify() override;
238
239 /// Return an iterator to the 0th TTree entry.
241 return Iterator_t(*this, 0);
242 }
243 /// Return an iterator beyond the last TTree entry.
244 Iterator_t end() const { return Iterator_t(); }
245
246protected:
247 using NamedProxies_t = std::unordered_map<std::string, std::unique_ptr<ROOT::Internal::TNamedBranchProxy>>;
248 void Initialize();
249 ROOT::Internal::TNamedBranchProxy* FindProxy(const char* branchname) const
250 {
251 const auto proxyIt = fProxies.find(branchname);
252 return fProxies.end() != proxyIt ? proxyIt->second.get() : nullptr;
253 }
254
256 {
257 auto bpName = p->GetName();
258#ifndef NDEBUG
259 if (fProxies.end() != fProxies.find(bpName)) {
260 std::string err = "A proxy with key " + std::string(bpName) + " was already stored!";
261 throw std::runtime_error(err);
262 }
263#endif
264
265 fProxies[bpName].reset(p);
266 }
267
270
271 EEntryStatus SetEntryBase(Long64_t entry, bool local);
272
273 bool SetProxies();
274
275private:
276
277 std::string GetProxyKey(const char *branchname)
278 {
279 std::string key(branchname);
280 //key += reinterpret_cast<std::uintptr_t>(fTree);
281 return key;
282 }
283
285 kBitIsChain = BIT(14), ///< our tree is a chain
286 kBitHaveWarnedAboutEntryListAttachedToTTree = BIT(15), ///< the tree had a TEntryList and we have warned about that
287 kBitSetEntryBaseCallingLoadTree = BIT(16) ///< SetEntryBase is in the process of calling TChain/TTree::%LoadTree.
288 };
289
290 TTree* fTree = nullptr; ///< tree that's read
291 TEntryList* fEntryList = nullptr; ///< entry list to be used
292 EEntryStatus fEntryStatus = kEntryNotLoaded; ///< status of most recent read request
293 ELoadTreeStatus fLoadTreeStatus = kNoTree; ///< Indicator on how LoadTree was called 'last' time.
294 /// TTree and TChain will notify this object upon LoadTree, leading to a call to TTreeReader::Notify().
296 ROOT::Internal::TBranchProxyDirector* fDirector = nullptr; ///< proxying director, owned
297 std::deque<ROOT::Internal::TFriendProxy*> fFriendProxies; ///< proxying for friend TTrees, owned
298 std::deque<ROOT::Internal::TTreeReaderValueBase*> fValues; ///< readers that use our director
299 NamedProxies_t fProxies; ///< attached ROOT::TNamedBranchProxies; owned
300
301 Long64_t fEntry = -1; ///< Current (non-local) entry of fTree or of fEntryList if set.
302
303 /// The end of the entry loop. When set (i.e. >= 0), it provides a way
304 /// to stop looping over the TTree when we reach a certain entry: Next()
305 /// returns false when GetCurrentEntry() reaches fEndEntry.
307 Long64_t fBeginEntry = 0LL; ///< This allows us to propagate the range to the TTreeCache
308 bool fProxiesSet = false; ///< True if the proxies have been set, false otherwise
309 bool fSetEntryBaseCallingLoadTree = false; ///< True if during the LoadTree execution triggered by SetEntryBase.
310
313
314 ClassDefOverride(TTreeReader, 0); // A simple interface to read trees
315};
316
317#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:201
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.
Definition TTreeReader.h:88
Iterator_t operator++(int)
Increment the iterator (postfix i++).
Definition TTreeReader.h:93
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() const
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
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.