Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TTreeReader.cxx
Go to the documentation of this file.
1// @(#)root/treeplayer:$Id$
2// Author: Axel Naumann, 2011-09-21
3
4/*************************************************************************
5 * Copyright (C) 1995-2013, Rene Brun and Fons Rademakers and al. *
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#include "TTreeReader.h"
13
14#include "TChain.h"
15#include "TDirectory.h"
16#include "TEntryList.h"
17#include "TTreeCache.h"
18#include "TTreeReaderValue.h"
19#include "TFriendElement.h"
20#include "TFriendProxy.h"
22
23// clang-format off
24/**
25 \class TTreeReader
26 \ingroup treeplayer
27 \brief A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree, TChain or TNtuple
28
29 TTreeReader is associated to TTreeReaderValue and TTreeReaderArray which are handles to concretely
30 access the information in the dataset.
31
32 Example code can be found in
33 - tutorials/tree/hsimpleReader.C
34 - tutorials/tree/h1analysisTreeReader.C
35 - <a href="https://github.com/root-project/roottest/tree/master/root/tree/reader">This example</a>
36
37 You can generate a skeleton of `TTreeReaderValue<T>` and `TTreeReaderArray<T>` declarations
38 for all of a tree's branches using `TTree::MakeSelector()`.
39
40 Roottest contains an
41 <a href="https://github.com/root-project/roottest/tree/master/root/tree/reader">example</a>
42 showing the full power.
43
44A simpler analysis example can be found below: it histograms a function of the px and py branches.
45
46~~~{.cpp}
47// A simple TTreeReader use: read data from hsimple.root (written by hsimple.C)
48
49#include "TFile.h"
50#include "TH1F.h"
51#include "TTreeReader.h"
52#include "TTreeReaderValue.h"
53
54void hsimpleReader() {
55 // Create a histogram for the values we read.
56 TH1F("h1", "ntuple", 100, -4, 4);
57
58 // Open the file containing the tree.
59 TFile *myFile = TFile::Open("$ROOTSYS/tutorials/hsimple.root");
60
61 // Create a TTreeReader for the tree, for instance by passing the
62 // TTree's name and the TDirectory / TFile it is in.
63 TTreeReader myReader("ntuple", myFile);
64
65 // The branch "px" contains floats; access them as myPx.
66 TTreeReaderValue<Float_t> myPx(myReader, "px");
67 // The branch "py" contains floats, too; access those as myPy.
68 TTreeReaderValue<Float_t> myPy(myReader, "py");
69
70 // Loop over all entries of the TTree or TChain.
71 while (myReader.Next()) {
72 // Just access the data as if myPx and myPy were iterators (note the '*'
73 // in front of them):
74 myHist->Fill(*myPx + *myPy);
75 }
76
77 myHist->Draw();
78}
79~~~
80
81A more complete example including error handling and a few combinations of
82TTreeReaderValue and TTreeReaderArray would look like this:
83
84~~~{.cpp}
85#include <TFile.h>
86#include <TH1.h>
87#include <TTreeReader.h>
88#include <TTreeReaderValue.h>
89#include <TTreeReaderArray.h>
90
91#include "TriggerInfo.h"
92#include "Muon.h"
93#include "Tau.h"
94
95#include <vector>
96#include <iostream>
97
98bool CheckValue(ROOT::Internal::TTreeReaderValueBase& value) {
99 if (value.GetSetupStatus() < 0) {
100 std::cerr << "Error " << value.GetSetupStatus()
101 << "setting up reader for " << value.GetBranchName() << '\n';
102 return false;
103 }
104 return true;
105}
106
107
108// Analyze the tree "MyTree" in the file passed into the function.
109// Returns false in case of errors.
110bool analyze(TFile* file) {
111 // Create a TTreeReader named "MyTree" from the given TDirectory.
112 // The TTreeReader gives access to the TTree to the TTreeReaderValue and
113 // TTreeReaderArray objects. It knows the current entry number and knows
114 // how to iterate through the TTree.
115 TTreeReader reader("MyTree", file);
116
117 // Read a single float value in each tree entries:
118 TTreeReaderValue<float> weight(reader, "event.weight");
119
120 // Read a TriggerInfo object from the tree entries:
121 TTreeReaderValue<TriggerInfo> triggerInfo(reader, "triggerInfo");
122
123 //Read a vector of Muon objects from the tree entries:
124 TTreeReaderValue<std::vector<Muon>> muons(reader, "muons");
125
126 //Read the pT for all jets in the tree entry:
127 TTreeReaderArray<double> jetPt(reader, "jets.pT");
128
129 // Read the taus in the tree entry:
130 TTreeReaderArray<Tau> taus(reader, "taus");
131
132
133 // Now iterate through the TTree entries and fill a histogram.
134
135 TH1F("hist", "TTreeReader example histogram", 10, 0., 100.);
136
137 bool firstEntry = true;
138 while (reader.Next()) {
139 if (firstEntry) {
140 // Check that branches exist and their types match our expectation.
141 if (!CheckValue(weight)) return false;
142 if (!CheckValue(triggerInfo)) return false;
143 if (!CheckValue(muons)) return false;
144 if (!CheckValue(jetPt)) return false;
145 if (!CheckValue(taus)) return false;
146 firstentry = false;
147 }
148
149 // Access the TriggerInfo object as if it's a pointer.
150 if (!triggerInfo->hasMuonL1())
151 continue;
152
153 // Ditto for the vector<Muon>.
154 if (!muons->size())
155 continue;
156
157 // Access the jetPt as an array, whether the TTree stores this as
158 // a std::vector, std::list, TClonesArray or Jet* C-style array, with
159 // fixed or variable array size.
160 if (jetPt.GetSize() < 2 || jetPt[0] < 100)
161 continue;
162
163 // Access the array of taus.
164 if (!taus.IsEmpty()) {
165 // Access a float value - need to dereference as TTreeReaderValue
166 // behaves like an iterator
167 float currentWeight = *weight;
168 for (const Tau& tau: taus) {
169 hist->Fill(tau.eta(), currentWeight);
170 }
171 }
172 } // TTree entry / event loop
173
174 // Return true if we have iterated through all entries.
175 return reader.GetEntryStatus() == TTreeReader::kEntryBeyondEnd;
176}
177~~~
178*/
179// clang-format on
180
182
183using namespace ROOT::Internal;
184
185// Provide some storage for the poor little symbol.
187
188////////////////////////////////////////////////////////////////////////////////
189/// Default constructor. Call SetTree to connect to a TTree.
190
191TTreeReader::TTreeReader() : fNotify(this) {}
192
193////////////////////////////////////////////////////////////////////////////////
194/// Access data from tree.
195///
196/// \param tree The TTree or TChain to read from
197/// \param entryList It can be a single TEntryList with global entry numbers (supported, as
198/// an extension, also in the case of a TChain) or, if the first parameter
199/// is a TChain, a TEntryList with sub-TEntryLists with local entry numbers.
200/// In the latter case, the TEntryList must be associated to the TChain, as
201/// per chain.SetEntryList(&entryList).
202
203TTreeReader::TTreeReader(TTree *tree, TEntryList *entryList /*= nullptr*/, bool warnAboutLongerFriends)
204 : fTree(tree), fEntryList(entryList), fNotify(this), fWarnAboutLongerFriends(warnAboutLongerFriends)
205{
206 if (!fTree) {
207 ::Error("TTreeReader::TTreeReader", "TTree is NULL!");
208 } else {
209 // We do not own the tree
211 Initialize();
212 }
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// Access data from the tree called keyname in the directory (e.g. TFile)
217/// dir, or the current directory if dir is NULL. If keyname cannot be
218/// found, or if it is not a TTree, IsInvalid() will return true.
219///
220/// \param keyname The name of the TTree to read from file
221/// \param dir The TDirectory to read keyname from
222/// \param entryList It can be a single TEntryList with global entry numbers (supported, as
223/// an extension, also in the case of a TChain) or, if the first parameter
224/// is a TChain, a TEntryList with sub-TEntryLists with local entry numbers.
225/// In the latter case, the TEntryList must be associated to the TChain, as
226/// per chain.SetEntryList(&entryList).
227
228TTreeReader::TTreeReader(const char* keyname, TDirectory* dir, TEntryList* entryList /*= nullptr*/):
229 fEntryList(entryList),
230 fNotify(this)
231{
232 if (!dir) dir = gDirectory;
233 dir->GetObject(keyname, fTree);
234 if (!fTree) {
235 std::string msg = "No TTree called ";
236 msg += keyname;
237 msg += " was found in the selected TDirectory.";
238 Error("TTreeReader", "%s", msg.c_str());
239 }
240 Initialize();
241}
242
243////////////////////////////////////////////////////////////////////////////////
244/// Tell all value readers that the tree reader does not exist anymore.
245
247{
248 for (std::deque<ROOT::Internal::TTreeReaderValueBase*>::const_iterator
249 i = fValues.begin(), e = fValues.end(); i != e; ++i) {
250 (*i)->MarkTreeReaderUnavailable();
251 }
252 if (fTree && fNotify.IsLinked())
254
256 // a plain TTree is automatically added to the current directory,
257 // do not delete it here
258 if (IsChain()) {
259 delete fTree;
260 }
261 }
262}
263
264////////////////////////////////////////////////////////////////////////////////
265/// Initialization of the director.
266
268{
269 fEntry = -1;
270 if (!fTree) {
273 return;
274 }
275
279 } else if (fEntryList && fEntryList->GetLists()) {
280 Error("Initialize", "We are not processing a TChain but the TEntryList contains sublists. Please "
281 "provide a simple TEntryList with no sublists instead.");
284 return;
285 }
286
287 fDirector = std::make_unique<ROOT::Internal::TBranchProxyDirector>(fTree, -1);
288
289 if (!fNotify.IsLinked()) {
291
292 if (fTree->GetTree()) {
293 // The current TTree is already available.
295 Notify();
297 }
298 }
299}
300
301////////////////////////////////////////////////////////////////////////////////
302/// Notify director and values of a change in tree. Called from TChain and TTree's LoadTree.
303/// TTreeReader registers its fNotify data member with the TChain/TTree which
304/// in turn leads to this method being called upon the execution of LoadTree.
306{
307
310 // This can happen if someone switched trees behind us.
311 // Likely cause: a TChain::LoadTree() e.g. from TTree::Process().
312 // This means that "local" should be set!
313 // There are two entities switching trees which is bad.
314 Warning("SetEntryBase()",
315 "The current tree in the TChain %s has changed (e.g. by TTree::Process) "
316 "even though TTreeReader::SetEntry() was called, which switched the tree "
317 "again. Did you mean to call TTreeReader::SetLocalEntry()?",
318 fTree->GetName());
319 }
321 } else {
323 }
324
326 Warning("SetEntryBase()",
327 "The TTree / TChain has an associated TEntryList. "
328 "TTreeReader ignores TEntryLists unless you construct the TTreeReader passing a TEntryList.");
330 }
331
332 if (!fDirector->Notify()) {
333 Error("SetEntryBase()", "There was an error while notifying the proxies.");
334 return false;
335 }
336
337 if (fProxiesSet) {
338 for (auto value: fValues) {
339 value->NotifyNewTree(fTree->GetTree());
340 }
341 }
342
343 return true;
344}
345
346////////////////////////////////////////////////////////////////////////////////
347/// Tell readers we now have a tree.
348/// fValues gets insertions during this loop (when parametrized arrays are read),
349/// invalidating iterators. Use old-school counting instead.
350
352
353 for (size_t i = 0; i < fValues.size(); ++i) {
355 reader->CreateProxy();
356 if (!reader->GetProxy()){
357 return false;
358 }
359
360 }
361 // If at least one proxy was there and no error occurred, we assume the proxies to be set.
362 fProxiesSet = !fValues.empty();
363
364 // Now we need to properly set the TTreeCache. We do this in steps:
365 // 1. We set the entry range according to the entry range of the TTreeReader
366 // 2. We add to the cache the branches identifying them by the name the user provided
367 // upon creation of the TTreeReader{Value, Array}s
368 // 3. We stop the learning phase.
369 // Operations 1, 2 and 3 need to happen in this order. See: https://sft.its.cern.ch/jira/browse/ROOT-9773?focusedCommentId=87837
370 if (fProxiesSet) {
371 const auto curFile = fTree->GetCurrentFile();
372 if (curFile && fTree->GetTree()->GetReadCache(curFile, true)) {
373 if (!(-1LL == fEndEntry && 0ULL == fBeginEntry)) {
374 // We need to avoid to pass -1 as end entry to the SetCacheEntryRange method
375 const auto lastEntry = (-1LL == fEndEntry) ? fTree->GetEntriesFast() : fEndEntry;
377 }
378 for (auto value: fValues) {
379 fTree->AddBranchToCache(value->GetProxy()->GetBranchName(), true);
380 }
382 }
383 }
384
385 return true;
386}
387
389{
391 return;
392 if (!fTree)
393 return;
394 // Make sure all proxies are set, as in certain situations we might get to this
395 // point without having set the proxies first. For example, when processing a
396 // TChain and calling `SetEntry(N)` with N beyond the real number of entries.
397 // If the proxies can't be set return from the function and give up the warning.
398 if (!fProxiesSet && !SetProxies())
399 return;
400
401 // If we are stopping the reading because we reached the last entry specified
402 // explicitly via SetEntriesRange, do not bother the user with a warning
403 if (fEntry == fEndEntry)
404 return;
405
406 const std::string mainTreeName =
408
409 const auto *friendsList = fTree->GetListOfFriends();
410 if (!friendsList || friendsList->GetEntries() == 0)
411 return;
412
413 for (decltype(fFriendProxies.size()) idx = 0; idx < fFriendProxies.size(); idx++) {
414 const auto &fp = fFriendProxies[idx];
415 // In case the friend is indexed it may very well be that it has a different number of events
416 // e.g. the friend contains information about luminosity block and
417 // all the entries in the main tree are from the same luminosity block
418 if (fp->HasIndex())
419 continue;
420 const auto *frTree = fp->GetDirector()->GetTree();
421 if (!frTree)
422 continue;
423
424 // Need to retrieve the real friend tree from the main tree
425 // because the current friend proxy points to the tree it is currently processing
426 // i.e. the current tree in a chain in case the real friend is a TChain
427 auto *frEl = static_cast<TFriendElement *>(friendsList->At(idx));
428 if (!frEl)
429 continue;
430 auto *frTreeFromMain = frEl->GetTree();
431 if (!frTreeFromMain)
432 continue;
433 // We are looking for the situation where there are actually still more
434 // entries to read in the friend. The following checks if the current entry to read
435 // is greater than the available entries in the dataset. If not, then we know there
436 // are more entries left in the friend.
437 //
438 // GetEntriesFast gives us a single handle to assess all the following:
439 // * If the friend is a TTree, it returns the total number of entries
440 // * If it is a TChain, then two more scenarios may occur:
441 // - If we have processed until the last file, then it returns the total
442 // number of entries.
443 // - If we have not processed all files yet, then it returns TTree::kMaxEntries.
444 // Thus, fEntry will always be smaller and the warning will be issued.
445 if (fEntry >= frTreeFromMain->GetEntriesFast())
446 continue;
447 // The friend tree still has entries beyond the last one of the main
448 // tree, warn the user about it.
449 const std::string frTreeName = dynamic_cast<const TChain *>(frTree)
450 ? frTree->GetName()
452 std::string msg = "Last entry available from main tree '" + mainTreeName + "' was " + std::to_string(fEntry - 1) +
453 " but friend tree '" + frTreeName + "' has more entries beyond the end of the main tree.";
454 Warning("SetEntryBase()", "%s", msg.c_str());
455 }
456}
457////////////////////////////////////////////////////////////////////////////////
458/// Set the range of entries to be loaded by `Next()`; end will not be loaded.
459///
460/// If end <= begin, `end` is ignored (set to `-1`, i.e. will run on all entries from `begin` onwards).
461///
462/// Example:
463///
464/// ~~~ {.cpp}
465/// reader.SetEntriesRange(3, 5);
466/// while (reader.Next()) {
467/// // Will load entries 3 and 4.
468/// }
469/// ~~~
470///
471/// Note that if a TEntryList is present, beginEntry and endEntry refer to the beginEntry-th/endEntry-th entries of the
472/// TEntryList (or the main TEntryList in case it has sub-entrylists). In other words, SetEntriesRange can
473/// be used to only loop over part of the TEntryList, but not to further restrict the actual TTree/TChain entry numbers
474/// considered.
475///
476/// \param beginEntry The first entry to be loaded by `Next()`.
477/// \param endEntry The entry where `Next()` will return false, not loading it.
478
480{
481 if (beginEntry < 0)
482 return kEntryNotFound;
483 // Complain if the entries number is larger than the tree's / chain's / entry
484 // list's number of entries, unless it's a TChain and "max entries" is
485 // uninitialized (i.e. TTree::kMaxEntries).
486 if (beginEntry >= GetEntries(false) && !(IsChain() && GetEntries(false) == TTree::kMaxEntries)) {
487 Error("SetEntriesRange()", "Start entry (%lld) must be lower than the available entries (%lld).", beginEntry,
488 GetEntries(false));
489 return kEntryNotFound;
490 }
491
492 // Update data members to correctly reflect the defined range
493 if (endEntry > beginEntry)
494 fEndEntry = endEntry;
495 else
496 fEndEntry = -1;
497
498 fBeginEntry = beginEntry;
499
500 if (beginEntry - 1 < 0)
501 // Reset the cache if reading from the first entry of the tree
502 Restart();
503 else {
504 // Load the first entry in the range. SetEntry() will also call SetProxies(),
505 // thus adding all the branches to the cache and triggering the learning phase.
506 EEntryStatus es = SetEntry(beginEntry - 1);
507 if (es != kEntryValid) {
508 Error("SetEntriesRange()", "Error setting first entry %lld: %s",
509 beginEntry, fgEntryStatusText[(int)es]);
510 return es;
511 }
512 }
513
514 return kEntryValid;
515}
516
518 fDirector->SetReadEntry(-1);
519 fProxiesSet = false; // we might get more value readers, meaning new proxies.
520 fEntry = -1;
521 if (const auto curFile = fTree->GetCurrentFile()) {
522 if (auto tc = fTree->GetTree()->GetReadCache(curFile, true)) {
523 tc->DropBranch("*", true);
524 tc->ResetCache();
525 }
526 }
527}
528
529////////////////////////////////////////////////////////////////////////////////
530/// Returns the number of entries of the TEntryList if one is provided, else
531/// of the TTree / TChain, independent of a range set by SetEntriesRange()
532/// by calling TTree/TChain::%GetEntriesFast.
533
534
536 if (fEntryList)
537 return fEntryList->GetN();
538 if (!fTree)
539 return -1;
540 return fTree->GetEntriesFast();
541}
542
543
544////////////////////////////////////////////////////////////////////////////////
545/// Returns the number of entries of the TEntryList if one is provided, else
546/// of the TTree / TChain, independent of a range set by SetEntriesRange().
547///
548/// \param force If `IsChain()` and `force`, determines whether all TFiles of
549/// this TChain should be opened to determine the exact number of entries
550/// of the TChain. If `!IsChain()`, `force` is ignored.
551
553 if (fEntryList)
554 return fEntryList->GetN();
555 if (!fTree)
556 return -1;
557 if (force) {
559 auto res = fTree->GetEntries();
560 // Go back to where we were:
563 return res;
564 }
565 return fTree->GetEntriesFast();
566}
567
568
569
570////////////////////////////////////////////////////////////////////////////////
571/// Load an entry into the tree, return the status of the read.
572/// For chains, entry is the global (i.e. not tree-local) entry number, unless
573/// `local` is `true`, in which case `entry` specifies the entry number within
574/// the current tree. This is needed for instance for TSelector::Process().
575
577{
578 if (IsInvalid()) {
580 fEntry = -1;
581 return fEntryStatus;
582 }
583
584 fEntry = entry;
585
586 Long64_t entryAfterList = entry;
587 if (fEntryList) {
588 if (entry >= fEntryList->GetN()) {
589 // Passed the end of the chain, Restart() was not called:
590 // don't try to load entries anymore. Can happen in these cases:
591 // while (tr.Next()) {something()};
592 // while (tr.Next()) {somethingelse()}; // should not be calling somethingelse().
594 return fEntryStatus;
595 }
596 if (entry >= 0) {
597 if (fEntryList->GetLists()) {
599 int treenum = -1;
600 entryAfterList = fEntryList->GetEntryAndTree(entry, treenum);
601 entryAfterList += static_cast<TChain *>(fTree)->GetTreeOffset()[treenum];
602 // We always translate local entry numbers to global entry numbers for TChain+TEntryList with sublists
603 local = false;
604 } else {
605 // Could be a TTree or a TChain (TTreeReader also supports single TEntryLists for TChains).
606 // In both cases, we are using the global entry numbers coming from the single TEntryList.
607 entryAfterList = fEntryList->GetEntry(entry);
608 }
609 }
610 }
611
612 TTree* treeToCallLoadOn = local ? fTree->GetTree() : fTree;
613
615 const Long64_t loadResult = treeToCallLoadOn->LoadTree(entryAfterList);
617
618 if (loadResult < 0) {
619 // ROOT-9628 We cover here the case when:
620 // - We deal with a TChain
621 // - The last file is opened
622 // - The TTree is not correctly loaded
623 // The system is robust against issues with TTrees associated to the chain
624 // when they are not at the end of it.
625 if (loadResult == -3 && TestBit(kBitIsChain) && !fTree->GetTree()) {
626 fDirector->Notify();
627 if (fProxiesSet) {
628 for (auto value: fValues) {
629 value->NotifyNewTree(fTree->GetTree());
630 }
631 }
632 Warning("SetEntryBase()",
633 "There was an issue opening the last file associated to the TChain "
634 "being processed.");
636 return fEntryStatus;
637 }
638
639 if (loadResult == -2) {
640 fDirector->Notify();
641 if (fProxiesSet) {
642 for (auto value: fValues) {
643 value->NotifyNewTree(fTree->GetTree());
644 }
645 }
648 return fEntryStatus;
649 }
650
651 if (loadResult == -1) {
652 // The chain is empty
654 return fEntryStatus;
655 }
656
657 if (loadResult == -4) {
658 // The TChainElement corresponding to the entry is missing or
659 // the TTree is missing from the file.
660 fDirector->Notify();
661 if (fProxiesSet) {
662 for (auto value: fValues) {
663 value->NotifyNewTree(fTree->GetTree());
664 }
665 }
667 return fEntryStatus;
668 }
669
670 Warning("SetEntryBase()",
671 "Unexpected error '%lld' in %s::LoadTree", loadResult,
672 treeToCallLoadOn->IsA()->GetName());
673
675 return fEntryStatus;
676 }
677
678 if (!fProxiesSet) {
679 if (!SetProxies()) {
681 return fEntryStatus;
682 }
683 }
684
685 if ((fEndEntry >= 0 && entry >= fEndEntry) || (fEntry >= fTree->GetEntriesFast())) {
688 return fEntryStatus;
689 }
690 fDirector->SetReadEntry(loadResult);
692
693 for (auto &&fp : fFriendProxies) {
694 if (fp->GetReadEntry() >= 0)
695 continue;
696 // We are going to read an invalid entry from a friend, propagate
697 // this information to the user.
698 const auto *frTree = fp->GetDirector()->GetTree();
699 if (!frTree)
700 continue;
701 const std::string frTreeName = dynamic_cast<const TChain *>(frTree)
702 ? frTree->GetName()
704 // If the friend does not have a TTreeIndex, the cause of a failure reading an entry
705 // is most probably a difference in number of entries between main tree and friend tree
706 if (!fp->HasIndex()) {
707 std::string msg = "Cannot read entry " + std::to_string(entry) + " from friend tree '" + frTreeName +
708 "'. The friend tree has less entries than the main tree. Make sure all trees "
709 "of the dataset have the same number of entries.";
710 throw std::runtime_error{msg};
711 }
712 // TODO: Also handle the opposite situation where the friend has a TTreeIndex
713 }
714
715 return fEntryStatus;
716}
717
718////////////////////////////////////////////////////////////////////////////////
719/// Set (or update) the which tree to read from. `tree` can be
720/// a TTree or a TChain.
721
722void TTreeReader::SetTree(TTree* tree, TEntryList* entryList /*= nullptr*/)
723{
725 // a plain TTree is automatically added to the current directory,
726 // do not delete it here
727 if (IsChain()) {
728 delete fTree;
729 }
730 }
731
732 fTree = tree;
733 fEntryList = entryList;
734 fEntry = -1;
735
738 if (fTree) {
741 } else {
743 }
744
745 if (!fDirector) {
746 Initialize();
747 }
748 else {
749 fDirector->SetTree(fTree);
750 fDirector->SetReadEntry(-1);
751 }
752}
753
754////////////////////////////////////////////////////////////////////////////////
755/// Set (or update) the which tree to read from, passing the name of a tree in a
756/// directory.
757///
758/// \param keyname - name of the tree in `dir`
759/// \param dir - the `TDirectory` to load `keyname` from (or gDirectory if `nullptr`)
760/// \param entryList - the `TEntryList` to attach to the `TTreeReader`.
761
762void TTreeReader::SetTree(const char* keyname, TDirectory* dir, TEntryList* entryList /*= nullptr*/)
763{
764 TTree* tree = nullptr;
765 if (!dir)
766 dir = gDirectory;
767 dir->GetObject(keyname, tree);
768 SetTree(tree, entryList);
769}
770
771////////////////////////////////////////////////////////////////////////////////
772/// Add a value reader for this tree.
773
775{
776 if (fProxiesSet) {
777 Error("RegisterValueReader",
778 "Error registering reader for %s: TTreeReaderValue/Array objects must be created before the call to Next() / SetEntry() / SetLocalEntry(), or after TTreeReader::Restart()!",
779 reader->GetBranchName());
780 return false;
781 }
782 fValues.push_back(reader);
783 return true;
784}
785
786////////////////////////////////////////////////////////////////////////////////
787/// Remove a value reader for this tree.
788
790{
791 std::deque<ROOT::Internal::TTreeReaderValueBase*>::iterator iReader
792 = std::find(fValues.begin(), fValues.end(), reader);
793 if (iReader == fValues.end()) {
794 Error("DeregisterValueReader", "Cannot find reader of type %s for branch %s", reader->GetDerivedTypeName(), reader->fBranchName.Data());
795 return;
796 }
797 fValues.erase(iReader);
798}
#define e(i)
Definition RSha256.hxx:103
long long Long64_t
Definition RtypesCore.h:69
#define ClassImp(name)
Definition Rtypes.h:377
#define gDirectory
Definition TDirectory.h:384
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:125
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Base class of TTreeReaderValue.
Detail::TBranchProxy * GetProxy() const
virtual const char * GetDerivedTypeName() const =0
TString fBranchName
Name of the branch to read data from.
virtual void CreateProxy()
Create the proxy object for our branch.
A chain is a collection of files containing TTree objects.
Definition TChain.h:33
static TClass * Class()
Describe directory structure in memory.
Definition TDirectory.h:45
void GetObject(const char *namecycle, T *&ptr)
Get an object with proper type checking.
Definition TDirectory.h:212
A List of entry numbers in a TTree or TChain.
Definition TEntryList.h:26
virtual TList * GetLists() const
Definition TEntryList.h:76
virtual Long64_t GetEntryAndTree(Long64_t index, Int_t &treenum)
Return the index of "index"-th non-zero entry in the TTree or TChain and the # of the corresponding t...
virtual Long64_t GetEntry(Long64_t index)
Return the number of the entry #index of this TEntryList in the TTree or TChain See also Next().
virtual Long64_t GetN() const
Definition TEntryList.h:78
A TFriendElement TF describes a TTree object TF in a file.
virtual TTree * GetTree()
Return pointer to friend TTree.
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
void PrependLink(Chain &chain)
Set this link as the head of the chain's list of notify subscribers.
Definition TNotifyLink.h:82
void RemoveLink(Chain &chain)
Remove this link from a chain's list of notify subscribers.
Bool_t IsLinked()
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition TObject.cxx:780
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition TObject.cxx:524
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
void ResetBit(UInt_t f)
Definition TObject.h:198
const char * Data() const
Definition TString.h:376
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.
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
void SetTree(TTree *tree, TEntryList *entryList=nullptr)
Set (or update) the which tree to read from.
~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
@ kEntryBeyondEnd
last entry loop has reached its end
@ kEntryChainFileError
problem in opening a chain's file
@ kEntryNoTree
the tree does not exist
@ 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
std::deque< std::unique_ptr< ROOT::Internal::TFriendProxy > > fFriendProxies
proxying for friend TTrees
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.
void WarnIfFriendsHaveMoreEntries()
@ 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 DeregisterValueReader(ROOT::Internal::TTreeReaderValueBase *reader)
Remove a value reader for this tree.
@ kBitIsExternalTree
we do not own the tree
@ kBitHaveWarnedAboutEntryListAttachedToTTree
the tree had a TEntryList and we have warned about that
@ kBitIsChain
our tree is a chain
bool SetProxies()
Tell readers we now have a tree.
std::unique_ptr< ROOT::Internal::TBranchProxyDirector > fDirector
proxying director
Long64_t fEndEntry
The end of the entry loop.
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]
Long64_t GetCurrentEntry() const
Returns the index of the current entry being read.
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual Int_t StopCacheLearningPhase()
Stop the cache learning phase.
Definition TTree.cxx:9474
virtual Int_t AddBranchToCache(const char *bname, bool subbranches=false)
Add branch with name bname to the Tree cache.
Definition TTree.cxx:1059
TFile * GetCurrentFile() const
Return pointer to the current file.
Definition TTree.cxx:5479
TTreeCache * GetReadCache(TFile *file) const
Find and return the TTreeCache registered with the file and which may contain branches for us.
Definition TTree.cxx:6318
virtual TEntryList * GetEntryList()
Returns the entry list assigned to this tree.
Definition TTree.cxx:5854
virtual Long64_t GetEntries() const
Definition TTree.h:463
virtual TTree * GetTree() const
Definition TTree.h:517
virtual Long64_t LoadTree(Long64_t entry)
Set current entry.
Definition TTree.cxx:6473
virtual Long64_t GetEntriesFast() const
Definition TTree.h:465
TClass * IsA() const override
Definition TTree.h:665
virtual Int_t SetCacheEntryRange(Long64_t first, Long64_t last)
interface to TTreeCache to set the cache entry range
Definition TTree.cxx:8831
virtual TList * GetListOfFriends() const
Definition TTree.h:490
static constexpr Long64_t kMaxEntries
Definition TTree.h:229
std::vector< std::string > GetTreeFullPaths(const TTree &tree)