180 ClassImp(TTreeReader);
182 using namespace ROOT::Internal;
185 constexpr
const char *
const TTreeReader::fgEntryStatusText[TTreeReader::kEntryBeyondEnd + 1];
190 TTreeReader::TTreeReader() : fNotify(this) {}
195 TTreeReader::TTreeReader(TTree* tree, TEntryList* entryList ):
197 fEntryList(entryList),
201 ::Error(
"TTreeReader::TTreeReader",
"TTree is NULL!");
212 TTreeReader::TTreeReader(
const char* keyname, TDirectory* dir, TEntryList* entryList ):
213 fEntryList(entryList),
216 if (!dir) dir = gDirectory;
217 dir->GetObject(keyname, fTree);
219 std::string msg =
"No TTree called ";
221 msg +=
" was found in the selected TDirectory.";
222 Error(
"TTreeReader",
"%s", msg.c_str());
230 TTreeReader::~TTreeReader()
232 for (std::deque<ROOT::Internal::TTreeReaderValueBase*>::const_iterator
233 i = fValues.begin(), e = fValues.end(); i != e; ++i) {
234 (*i)->MarkTreeReaderUnavailable();
236 if (fTree && fNotify.IsLinked())
237 fNotify.RemoveLink(*fTree);
243 for (
auto feproxy: fFriendProxies) {
246 fFriendProxies.clear();
254 void TTreeReader::Initialize()
258 fEntryStatus = kEntryNoTree;
259 fLoadTreeStatus = kNoTree;
263 fLoadTreeStatus = kLoadTreeNone;
264 if (fTree->InheritsFrom(TChain::Class())) {
268 fDirector =
new ROOT::Internal::TBranchProxyDirector(fTree, -1);
270 if (!fNotify.IsLinked()) {
271 fNotify.PrependLink(*fTree);
273 if (fTree->GetTree()) {
275 fSetEntryBaseCallingLoadTree = kTRUE;
277 fSetEntryBaseCallingLoadTree = kFALSE;
285 Bool_t TTreeReader::Notify()
288 if (fSetEntryBaseCallingLoadTree) {
289 if (fLoadTreeStatus == kExternalLoadTree) {
294 Warning(
"SetEntryBase()",
295 "The current tree in the TChain %s has changed (e.g. by TTree::Process) "
296 "even though TTreeReader::SetEntry() was called, which switched the tree "
297 "again. Did you mean to call TTreeReader::SetLocalEntry()?",
300 fLoadTreeStatus = kInternalLoadTree;
302 fLoadTreeStatus = kExternalLoadTree;
305 if (!fEntryList && fTree->GetEntryList() && !TestBit(kBitHaveWarnedAboutEntryListAttachedToTTree)) {
306 Warning(
"SetEntryBase()",
307 "The TTree / TChain has an associated TEntryList. "
308 "TTreeReader ignores TEntryLists unless you construct the TTreeReader passing a TEntryList.");
309 SetBit(kBitHaveWarnedAboutEntryListAttachedToTTree);
312 if (!fDirector->Notify()) {
313 Error(
"SetEntryBase()",
"There was an error while notifying the proxies.");
318 for (
auto value: fValues) {
319 value->NotifyNewTree(fTree->GetTree());
331 Bool_t TTreeReader::SetProxies() {
333 for (
size_t i = 0; i < fValues.size(); ++i) {
334 ROOT::Internal::TTreeReaderValueBase* reader = fValues[i];
335 reader->CreateProxy();
336 if (!reader->GetProxy()){
342 fProxiesSet = !fValues.empty();
351 const auto curFile = fTree->GetCurrentFile();
352 if (curFile && fTree->GetTree()->GetReadCache(curFile,
true)) {
353 if (!(-1LL == fEndEntry && 0ULL == fBeginEntry)) {
355 const auto lastEntry = (-1LL == fEndEntry) ? fTree->GetEntriesFast() : fEndEntry;
356 fTree->SetCacheEntryRange(fBeginEntry, lastEntry);
358 for (
auto value: fValues) {
359 fTree->AddBranchToCache(value->GetProxy()->GetBranchName(),
true);
361 fTree->StopCacheLearningPhase();
384 TTreeReader::EEntryStatus TTreeReader::SetEntriesRange(Long64_t beginEntry, Long64_t endEntry)
387 return kEntryNotFound;
391 if (beginEntry >= GetEntries(
false) && !(IsChain() && GetEntries(
false) == TTree::kMaxEntries)) {
392 Error(
"SetEntriesRange()",
"first entry out of range 0..%lld", GetEntries(
false));
393 return kEntryNotFound;
396 if (endEntry > beginEntry)
397 fEndEntry = endEntry;
400 if (beginEntry - 1 < 0)
403 EEntryStatus es = SetEntry(beginEntry - 1);
404 if (es != kEntryValid) {
405 Error(
"SetEntriesRange()",
"Error setting first entry %lld: %s",
406 beginEntry, fgEntryStatusText[(
int)es]);
411 fBeginEntry = beginEntry;
416 void TTreeReader::Restart() {
417 fDirector->SetReadEntry(-1);
420 if (
const auto curFile = fTree->GetCurrentFile()) {
421 if (
auto tc = fTree->GetTree()->GetReadCache(curFile,
true)) {
422 tc->DropBranch(
"*",
true);
434 Long64_t TTreeReader::GetEntries()
const {
436 return fEntryList->GetN();
439 return fTree->GetEntriesFast();
451 Long64_t TTreeReader::GetEntries(Bool_t force) {
453 return fEntryList->GetN();
457 fSetEntryBaseCallingLoadTree = kTRUE;
458 auto res = fTree->GetEntries();
460 fTree->LoadTree(GetCurrentEntry());
461 fSetEntryBaseCallingLoadTree = kFALSE;
464 return fTree->GetEntriesFast();
475 TTreeReader::EEntryStatus TTreeReader::SetEntryBase(Long64_t entry, Bool_t local)
478 fEntryStatus = kEntryNoTree;
485 Long64_t entryAfterList = entry;
487 if (entry >= fEntryList->GetN()) {
492 fEntryStatus = kEntryNotFound;
495 if (entry >= 0) entryAfterList = fEntryList->GetEntry(entry);
496 if (local && IsChain()) {
502 TTree* treeToCallLoadOn = local ? fTree->GetTree() : fTree;
504 fSetEntryBaseCallingLoadTree = kTRUE;
505 const Long64_t loadResult = treeToCallLoadOn->LoadTree(entryAfterList);
506 fSetEntryBaseCallingLoadTree = kFALSE;
508 if (loadResult < 0) {
515 if (loadResult == -3 && TestBit(kBitIsChain) && !fTree->GetTree()) {
518 for (
auto value: fValues) {
519 value->NotifyNewTree(fTree->GetTree());
522 Warning(
"SetEntryBase()",
523 "There was an issue opening the last file associated to the TChain "
525 fEntryStatus = kEntryChainFileError;
529 if (loadResult == -2) {
532 for (
auto value: fValues) {
533 value->NotifyNewTree(fTree->GetTree());
536 fEntryStatus = kEntryNotFound;
540 if (loadResult == -1) {
542 fEntryStatus = kEntryNotFound;
546 if (loadResult == -4) {
551 for (
auto value: fValues) {
552 value->NotifyNewTree(fTree->GetTree());
555 fEntryStatus = kEntryNotFound;
559 Warning(
"SetEntryBase()",
560 "Unexpected error '%lld' in %s::LoadTree", loadResult,
561 treeToCallLoadOn->IsA()->GetName());
563 fEntryStatus = kEntryUnknownError;
569 fEntryStatus = kEntryDictionaryError;
574 if (fEndEntry >= 0 && entry >= fEndEntry) {
575 fEntryStatus = kEntryBeyondEnd;
578 fDirector->SetReadEntry(loadResult);
579 fEntryStatus = kEntryValid;
587 void TTreeReader::SetTree(TTree* tree, TEntryList* entryList )
590 fEntryList = entryList;
594 fLoadTreeStatus = kLoadTreeNone;
595 SetBit(kBitIsChain, fTree->InheritsFrom(TChain::Class()));
597 fLoadTreeStatus = kNoTree;
604 fDirector->SetTree(fTree);
605 fDirector->SetReadEntry(-1);
617 void TTreeReader::SetTree(
const char* keyname, TDirectory* dir, TEntryList* entryList )
619 TTree* tree =
nullptr;
622 dir->GetObject(keyname, tree);
623 SetTree(tree, entryList);
629 Bool_t TTreeReader::RegisterValueReader(ROOT::Internal::TTreeReaderValueBase* reader)
632 Error(
"RegisterValueReader",
633 "Error registering reader for %s: TTreeReaderValue/Array objects must be created before the call to Next() / SetEntry() / SetLocalEntry(), or after TTreeReader::Restart()!",
634 reader->GetBranchName());
637 fValues.push_back(reader);
644 void TTreeReader::DeregisterValueReader(ROOT::Internal::TTreeReaderValueBase* reader)
646 std::deque<ROOT::Internal::TTreeReaderValueBase*>::iterator iReader
647 = std::find(fValues.begin(), fValues.end(), reader);
648 if (iReader == fValues.end()) {
649 Error(
"DeregisterValueReader",
"Cannot find reader of type %s for branch %s", reader->GetDerivedTypeName(), reader->fBranchName.Data());
652 fValues.erase(iReader);