diff --git a/tree/tree/src/TChain.cxx b/tree/tree/src/TChain.cxx index 3cdae7fd8ceeb..bad3c3f229e78 100644 --- a/tree/tree/src/TChain.cxx +++ b/tree/tree/src/TChain.cxx @@ -30,6 +30,7 @@ the trees in the chain. #include #include #include +#include #include "TBranch.h" #include "TBrowser.h" @@ -66,6 +67,26 @@ the trees in the chain. ClassImp(TChain); +/** + * @brief Helper function getting a map between treeNumber (key) defined in an entryList, and the position of the latter + * in the collection (value). Only those entry lists that are active (treeNumber != -1) are used to fill the map. + * @param elist the TChain's TEntryList + * @return map of int to int + */ +std::map GetEntryListMap(const TEntryList *elist) +{ + const auto *elists = elist->GetLists(); + const auto ne = elists->GetEntries(); + std::map map_elists; + for (Int_t e = 0; e < ne; ++e) { + auto el = static_cast(elists->At(e)); + if (el && el->GetTreeNumber() >= 0) { + map_elists[el->GetTreeNumber()] = e; + } + } + return map_elists; +} + //////////////////////////////////////////////////////////////////////////////// /// Default constructor. @@ -1169,12 +1190,30 @@ TObjArray* TChain::GetListOfLeaves() Double_t TChain::GetMaximum(const char* columname) { Double_t theMax = -DBL_MAX; - for (Int_t file = 0; file < fNtrees; file++) { - Long64_t first = fTreeOffset[file]; - LoadTree(first); - Double_t curmax = fTree->GetMaximum(columname); - if (curmax > theMax) { - theMax = curmax; + auto elist = GetEntryList(); + if (!elist || !elist->GetLists()) { + for (Int_t file = 0; file < fNtrees; file++) { + Long64_t first = fTreeOffset[file]; + LoadTree(first); + Double_t curmax = fTree->GetMaximum(columname); + if (curmax > theMax) { + theMax = curmax; + } + } + } else { + auto map_elists = GetEntryListMap(elist); + for (Int_t file = 0; file < fNtrees; file++) { + Long64_t first = fTreeOffset[file]; + LoadTree(first); + const auto prev = fTree->GetEntryList(); + if (map_elists.find(file) != map_elists.end()) { + fTree->SetEntryList(static_cast(elist->GetLists()->At(map_elists[file]))); + } + Double_t curmax = fTree->GetMaximum(columname); + fTree->SetEntryList(prev); + if (curmax > theMax) { + theMax = curmax; + } } } return theMax; @@ -1186,12 +1225,30 @@ Double_t TChain::GetMaximum(const char* columname) Double_t TChain::GetMinimum(const char* columname) { Double_t theMin = DBL_MAX; - for (Int_t file = 0; file < fNtrees; file++) { - Long64_t first = fTreeOffset[file]; - LoadTree(first); - Double_t curmin = fTree->GetMinimum(columname); - if (curmin < theMin) { - theMin = curmin; + auto elist = GetEntryList(); + if (!elist || !elist->GetLists()) { + for (Int_t file = 0; file < fNtrees; file++) { + Long64_t first = fTreeOffset[file]; + LoadTree(first); + Double_t curmin = fTree->GetMinimum(columname); + if (curmin < theMin) { + theMin = curmin; + } + } + } else { + auto map_elists = GetEntryListMap(elist); + for (Int_t file = 0; file < fNtrees; file++) { + Long64_t first = fTreeOffset[file]; + LoadTree(first); + const auto prev = fTree->GetEntryList(); + if (map_elists.find(file) != map_elists.end()) { + fTree->SetEntryList(static_cast(elist->GetLists()->At(map_elists[file]))); + } + Double_t curmin = fTree->GetMinimum(columname); + fTree->SetEntryList(prev); + if (curmin < theMin) { + theMin = curmin; + } } } return theMin; diff --git a/tree/tree/test/TChainRegressions.cxx b/tree/tree/test/TChainRegressions.cxx index 7af610f6ad722..9c051183d05e2 100644 --- a/tree/tree/test/TChainRegressions.cxx +++ b/tree/tree/test/TChainRegressions.cxx @@ -2,7 +2,9 @@ #include #include #include - +#include +#include + #include "gtest/gtest.h" class TTreeCache; @@ -30,3 +32,48 @@ TEST(TChain, GetReadCacheBug) gSystem->Unlink(filename); } + +// ROOT-7097, ROOT-8505 +TEST(TChain, GetMinMaxEntryList) +{ + std::unique_ptr file1(TFile::Open("t1_7067.root", "RECREATE")); + TTree t1("t", ""); + int value; + t1.Branch("value", &value); + value = 0; + t1.Fill(); + value = 1; + t1.Fill(); + value = 2; + t1.Fill(); + value = 3; + t1.Fill(); + file1->Write(); + file1->Close(); + + std::unique_ptr file2(TFile::Open("t2_7067.root", "RECREATE")); + TTree t2("t", ""); + // int value; + t2.Branch("value", &value); + value = 10; + t2.Fill(); + value = 11; + t2.Fill(); + value = 12; + t2.Fill(); + value = 13; + t2.Fill(); + file2->Write(); + file2->Close(); + + TChain ch("t"); + ch.AddFile("t1_7067.root"); + ch.AddFile("t2_7067.root"); + EXPECT_FLOAT_EQ(ch.GetMinimum("value"), 0.); + EXPECT_FLOAT_EQ(ch.GetMaximum("value"), 13.); + ch.Draw(">>myList", "value<11 && value >1", "entrylist"); + TEntryList *myList = static_cast(gDirectory->Get("myList")); + ch.SetEntryList(myList); + EXPECT_FLOAT_EQ(ch.GetMinimum("value"), 2.); + EXPECT_FLOAT_EQ(ch.GetMaximum("value"), 10.); +} \ No newline at end of file