From e75e769328781fa6f2b76be1c86a0622312d5fc6 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Wed, 8 Jul 2026 18:01:02 +0200 Subject: [PATCH 01/10] [core] Provide interface for selecting ROOT auto-registration defaults. Among setting defaults using .rootrc or using environment variables, users also requested a way to set default programmatically. Here, this functionality is added via: ROOT::Experimental::SetObjectAutoRegistrationDefault() --- core/base/inc/TROOT.h | 1 + core/base/src/TROOT.cxx | 58 +++++++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 16 deletions(-) diff --git a/core/base/inc/TROOT.h b/core/base/inc/TROOT.h index db22582c668cd..4ae127619837e 100644 --- a/core/base/inc/TROOT.h +++ b/core/base/inc/TROOT.h @@ -101,6 +101,7 @@ namespace ROOT { void EnableObjectAutoRegistration(); void DisableObjectAutoRegistration(); bool ObjectAutoRegistrationEnabled(); + void SetObjectAutoRegistrationDefault(bool enabled); } // namespace Experimental } diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index 9ee7e332ca2b3..877188d43740b 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -295,24 +295,29 @@ namespace { return moduleHeaderInfoBuffer; } + /// State helper for object auto registration. enum class AutoReg : unsigned char { kNotInitialised = 0, kOn, kOff, }; - //////////////////////////////////////////////////////////////////////////////// - /// \brief Test if various objects (such as TH1-derived classes) should automatically register - /// themselves (ROOT 6 mode) or not (ROOT 7 mode). - /// A default can be set in a .rootrc using e.g. "Root.ObjectAutoRegistration: 1" or setting - /// the environment variable "ROOT_OBJECT_AUTO_REGISTRATION=0". - AutoReg &ObjectAutoRegistrationEnabledImpl() + /// Set or read the default state for object auto registration. This state is used to initialise the + /// auto-registration state for each thread that starts. + AutoReg ObjectAutoRegistrationDefault(AutoReg defaultState) { static constexpr auto rcName = "Root.ObjectAutoRegistration"; // Update the docs if this is changed static constexpr auto envName = "ROOT_OBJECT_AUTO_REGISTRATION"; // Update the docs if this is changed - thread_local static AutoReg tlsState = AutoReg::kNotInitialised; + static std::atomic defaultFromAPI = AutoReg::kNotInitialised; - static const AutoReg defaultState = []() { + if (defaultState != AutoReg::kNotInitialised) { + defaultFromAPI = defaultState; + } + if (const auto apiDefault = defaultFromAPI.load(); apiDefault != AutoReg::kNotInitialised) { + return apiDefault; + } + + static const AutoReg defaultFromEnvironment = []() { AutoReg autoReg = AutoReg::kOn; // ROOT 6 default std::stringstream infoMessage; @@ -356,10 +361,18 @@ namespace { return autoReg; }(); - if (tlsState == AutoReg::kNotInitialised) { - assert(defaultState != AutoReg::kNotInitialised); - tlsState = defaultState; - } + return defaultFromEnvironment; + } + + //////////////////////////////////////////////////////////////////////////////// + /// \brief Test if various objects (such as TH1-derived classes) should automatically register + /// themselves (ROOT 6 mode) or not (ROOT 7 mode). + /// A default can be set in a .rootrc using e.g. "Root.ObjectAutoRegistration: 1" or setting + /// the environment variable "ROOT_OBJECT_AUTO_REGISTRATION=0". + AutoReg &ObjectAutoRegistrationEnabledImpl() + { + thread_local static AutoReg tlsState = ObjectAutoRegistrationDefault(AutoReg::kNotInitialised); + assert(tlsState != AutoReg::kNotInitialised); return tlsState; } @@ -733,10 +746,13 @@ namespace Internal { /// /// ## Setting defaults /// - /// A default can be set in a .rootrc using e.g. `Root.ObjectAutoRegistration: 1` or setting - /// the environment variable `ROOT_OBJECT_AUTO_REGISTRATION=0`. Note that this default affects - /// all the threads that get started. - /// When a default is set using one of these methods, ROOT will notify with an Info message. + /// A default can be set (in order of precedence): + /// 1. Using ROOT::SetObjectAutoRegistrationDefault(). + /// 2. Setting the environment variable `ROOT_OBJECT_AUTO_REGISTRATION=0` + /// 3. Setting `Root.ObjectAutoRegistration: 1` in a .rootrc file. + /// + /// Note that this default affects all the threads that get started, but once a thread runs, + /// the mode can only be changed thread-local using Enable/DisableObjectAutoRegistration(). /// /// ## Difference to TH1::AddDirectoryStatus() /// @@ -765,6 +781,16 @@ namespace Internal { assert(state != AutoReg::kNotInitialised); return state == AutoReg::kOn; } + + //////////////////////////////////////////////////////////////////////////////// + /// Set default for object auto registration when a thread starts up. + /// Threads that are already running are *not* affected by this call, including + /// the calling thread. + /// \copydetails ROOT::Experimental::EnableObjectAutoRegistration() + void SetObjectAutoRegistrationDefault(bool enabled) + { + ObjectAutoRegistrationDefault(enabled ? AutoReg::kOn : AutoReg::kOff); + } } // namespace Experimental } // end of ROOT namespace From 4f4fc6122e600a5b4dac2ccca6ebeb58c256e974 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Wed, 8 Jul 2026 18:02:05 +0200 Subject: [PATCH 02/10] [core] Extend tests for ROOT auto-registration defaults. --- core/base/test/TROOTTests.cxx | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/base/test/TROOTTests.cxx b/core/base/test/TROOTTests.cxx index a1ccc0ad87fb9..1aa1239454f29 100644 --- a/core/base/test/TROOTTests.cxx +++ b/core/base/test/TROOTTests.cxx @@ -87,7 +87,26 @@ TEST(TROOT, AutoRegistrationTLS) EnableObjectAutoRegistration(); EXPECT_EQ(ObjectAutoRegistrationEnabled(), true); - for (auto thread : {&t1, &t2, &t3, &t4}) { + const bool stateBeforeJoin = ObjectAutoRegistrationEnabled(); + + for (auto *thread : {&t1, &t2, &t3, &t4}) { thread->join(); } + + auto testAPIDefault = [](bool expectedState){ + EXPECT_EQ(ObjectAutoRegistrationEnabled(), expectedState); + }; + SetObjectAutoRegistrationDefault(true); + std::thread t5{testAPIDefault, true}; + + EXPECT_EQ(ObjectAutoRegistrationEnabled(), stateBeforeJoin); + + t5.join(); + + SetObjectAutoRegistrationDefault(false); + std::thread t6{testAPIDefault, false}; + + EXPECT_EQ(ObjectAutoRegistrationEnabled(), stateBeforeJoin); + + t6.join(); } From 7c554ccc83468a35143a82e0e133cd5c64fc9087 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 13:42:14 +0200 Subject: [PATCH 03/10] fixup! [core] Provide interface for selecting ROOT auto-registration defaults. --- core/base/src/TROOT.cxx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index 877188d43740b..0b96b4e065372 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -747,12 +747,13 @@ namespace Internal { /// ## Setting defaults /// /// A default can be set (in order of precedence): - /// 1. Using ROOT::SetObjectAutoRegistrationDefault(). - /// 2. Setting the environment variable `ROOT_OBJECT_AUTO_REGISTRATION=0` - /// 3. Setting `Root.ObjectAutoRegistration: 1` in a .rootrc file. + /// 1. Using \ref SetObjectAutoRegistrationDefault(). + /// 2. Setting the environment variable `ROOT_OBJECT_AUTO_REGISTRATION=[01]` + /// 3. Setting `Root.ObjectAutoRegistration: [01]` in a .rootrc file. /// - /// Note that this default affects all the threads that get started, but once a thread runs, - /// the mode can only be changed thread-local using Enable/DisableObjectAutoRegistration(). + /// Note that this default affects all the threads that get started, but a running thread's behaviour + /// can only be changed using Enable/DisableObjectAutoRegistration(). + /// When the default state is changed using the environment or .rootrc, ROOT issues a reminder. /// /// ## Difference to TH1::AddDirectoryStatus() /// From bd5e9e5d89e3a6aac5c5bd0def100445d5787d45 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 13:52:58 +0200 Subject: [PATCH 04/10] [tree] Honour ObjectAutoRegistrationEnabled() in TEventList. --- tree/tree/src/TEventList.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tree/tree/src/TEventList.cxx b/tree/tree/src/TEventList.cxx index 735db20b22930..c70b0a44982a1 100644 --- a/tree/tree/src/TEventList.cxx +++ b/tree/tree/src/TEventList.cxx @@ -54,6 +54,7 @@ the TEventList object created in the above commands: #include "TMath.h" #include "strlcpy.h" #include "snprintf.h" +#include "TROOT.h" //////////////////////////////////////////////////////////////////////////////// @@ -83,8 +84,10 @@ TEventList::TEventList(const char *name, const char *title, Int_t initsize, Int_ if (delta > 100) fDelta = delta; else fDelta = 100; fList = nullptr; - fDirectory = gDirectory; - if (fDirectory) fDirectory->Append(this); + if (ROOT::Experimental::ObjectAutoRegistrationEnabled()) { + fDirectory = gDirectory; + if (fDirectory) fDirectory->Append(this); + } } //////////////////////////////////////////////////////////////////////////////// From ea8b342b273ebc4e286194a78b84e2fafd481506 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 13:54:36 +0200 Subject: [PATCH 05/10] [tree] Small cleanup in TEventList. - Remove unused headers. - Use member initialisers to clean up constructors. --- tree/tree/inc/TEventList.h | 14 +++++++------- tree/tree/src/TEventList.cxx | 28 ++++------------------------ 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/tree/tree/inc/TEventList.h b/tree/tree/inc/TEventList.h index cf2a7a616fa65..2bbc1fc85876c 100644 --- a/tree/tree/inc/TEventList.h +++ b/tree/tree/inc/TEventList.h @@ -31,15 +31,15 @@ class TCollection; class TEventList : public TNamed { protected: - Int_t fN; ///< Number of elements in the list - Int_t fSize; ///< Size of array - Int_t fDelta; ///< Increment size - bool fReapply; ///< If true, TTree::Draw will 'reapply' the original cut - Long64_t *fList; ///<[fN]Array of elements - TDirectory *fDirectory; /// 100) fSize = initsize; else fSize = 100; if (delta > 100) fDelta = delta; @@ -110,9 +90,9 @@ TEventList::TEventList(const TEventList &list) : TNamed(list) TEventList::~TEventList() { - delete [] fList; fList = nullptr; - if (fDirectory) fDirectory->Remove(this); - fDirectory = nullptr; + delete[] fList; + if (fDirectory) + fDirectory->Remove(this); } //////////////////////////////////////////////////////////////////////////////// From 031ef08db94df6b67bb2c96ba7132ef294a02670 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 15:08:42 +0200 Subject: [PATCH 06/10] [math/tmva] Clean up unnecessary includes of TEventList. Also remove further includes that were unused. --- math/mlp/inc/TMultiLayerPerceptron.h | 2 +- math/mlp/src/TMultiLayerPerceptron.cxx | 1 + tmva/tmva/src/Classification.cxx | 1 - tmva/tmva/src/DataInputHandler.cxx | 3 --- tmva/tmva/src/DataSetFactory.cxx | 9 --------- tmva/tmva/src/DataSetInfo.cxx | 8 ++------ tmva/tmva/src/Factory.cxx | 13 +++++-------- tmva/tmva/src/MethodTMlpANN.cxx | 3 --- tree/tree/src/TEventList.cxx | 1 + 9 files changed, 10 insertions(+), 31 deletions(-) diff --git a/math/mlp/inc/TMultiLayerPerceptron.h b/math/mlp/inc/TMultiLayerPerceptron.h index 36d5d01d34aab..1c423321091da 100644 --- a/math/mlp/inc/TMultiLayerPerceptron.h +++ b/math/mlp/inc/TMultiLayerPerceptron.h @@ -15,8 +15,8 @@ #include "TObject.h" #include "TString.h" #include "TObjArray.h" -#include "TMatrixD.h" #include "TNeuron.h" +#include "TMatrixDfwd.h" class TTree; class TEventList; diff --git a/math/mlp/src/TMultiLayerPerceptron.cxx b/math/mlp/src/TMultiLayerPerceptron.cxx index 87a6068a1c348..4683272659768 100644 --- a/math/mlp/src/TMultiLayerPerceptron.cxx +++ b/math/mlp/src/TMultiLayerPerceptron.cxx @@ -242,6 +242,7 @@ neurons, hidden layers and inputs/outputs that does not apply to TMultiLayerPerc #include "TH2.h" #include "TGraph.h" #include "TLegend.h" +#include "TMatrixD.h" #include "TMultiGraph.h" #include "TDirectory.h" #include "TSystem.h" diff --git a/tmva/tmva/src/Classification.cxx b/tmva/tmva/src/Classification.cxx index 58b21238dc63a..8a8ec50f03280 100644 --- a/tmva/tmva/src/Classification.cxx +++ b/tmva/tmva/src/Classification.cxx @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/tmva/tmva/src/DataInputHandler.cxx b/tmva/tmva/src/DataInputHandler.cxx index bde79ed57e965..2c725b85aa03f 100644 --- a/tmva/tmva/src/DataInputHandler.cxx +++ b/tmva/tmva/src/DataInputHandler.cxx @@ -36,12 +36,9 @@ Class that contains all the data information. #include "TMVA/DataLoader.h" #include "TMVA/MsgLogger.h" #include "TMVA/Types.h" -#include "TEventList.h" #include "TCut.h" #include "TTree.h" -#include "TMVA/Configurable.h" - #include #include diff --git a/tmva/tmva/src/DataSetFactory.cxx b/tmva/tmva/src/DataSetFactory.cxx index 8b09d1bb9eb14..96d9b2e85d334 100644 --- a/tmva/tmva/src/DataSetFactory.cxx +++ b/tmva/tmva/src/DataSetFactory.cxx @@ -41,26 +41,17 @@ Class that contains all the data information #include #include -#include -#include -#include #include "TMVA/DataSetFactory.h" -#include "TEventList.h" #include "TFile.h" #include "TRandom3.h" -#include "TMatrixF.h" -#include "TVectorF.h" #include "TMath.h" #include "TTree.h" #include "TBranch.h" #include "TMVA/MsgLogger.h" #include "TMVA/Configurable.h" -#include "TMVA/VariableIdentityTransform.h" -#include "TMVA/VariableDecorrTransform.h" -#include "TMVA/VariablePCATransform.h" #include "TMVA/DataSet.h" #include "TMVA/DataSetInfo.h" #include "TMVA/DataInputHandler.h" diff --git a/tmva/tmva/src/DataSetInfo.cxx b/tmva/tmva/src/DataSetInfo.cxx index 651f1e6b9b99d..6edf91cde5076 100644 --- a/tmva/tmva/src/DataSetInfo.cxx +++ b/tmva/tmva/src/DataSetInfo.cxx @@ -31,14 +31,8 @@ Class that contains all the data information. */ -#include - -#include "TEventList.h" #include "TH2.h" -#include "TRandom3.h" #include "TMatrixF.h" -#include "TVectorF.h" -#include "TROOT.h" #include "TMVA/MsgLogger.h" #include "TMVA/Tools.h" @@ -50,6 +44,8 @@ Class that contains all the data information. #include "TMVA/Types.h" #include "TMVA/VariableInfo.h" +#include + //////////////////////////////////////////////////////////////////////////////// /// constructor diff --git a/tmva/tmva/src/Factory.cxx b/tmva/tmva/src/Factory.cxx index 278730bbef214..42f3081621be6 100644 --- a/tmva/tmva/src/Factory.cxx +++ b/tmva/tmva/src/Factory.cxx @@ -71,26 +71,23 @@ evaluation phases. #include "TMVA/ResultsClassification.h" #include "TMVA/ResultsRegression.h" #include "TMVA/ResultsMulticlass.h" -#include -#include -#include #include "TMVA/Types.h" #include "TROOT.h" #include "TFile.h" -#include "TLeaf.h" -#include "TEventList.h" #include "TH2.h" #include "TGraph.h" #include "TStyle.h" -#include "TMatrixF.h" -#include "TMatrixDSym.h" -#include "TMultiGraph.h" #include "TPrincipal.h" #include "TMath.h" #include "TSystem.h" #include "TCanvas.h" +#include "TMultiGraph.h" + +#include +#include +#include const Int_t MinNoTrainingEvents = 10; // const Int_t MinNoTestEvents = 1; diff --git a/tmva/tmva/src/MethodTMlpANN.cxx b/tmva/tmva/src/MethodTMlpANN.cxx index f67da9507ba78..39b6b8abf2dad 100644 --- a/tmva/tmva/src/MethodTMlpANN.cxx +++ b/tmva/tmva/src/MethodTMlpANN.cxx @@ -46,7 +46,6 @@ for details on this ANN. #include "TMVA/MethodTMlpANN.h" #include "TMVA/Config.h" -#include "TMVA/Configurable.h" #include "TMVA/DataSet.h" #include "TMVA/DataSetInfo.h" #include "TMVA/IMethod.h" @@ -58,8 +57,6 @@ for details on this ANN. #include "TMVA/ClassifierFactory.h" #include "TMVA/Tools.h" -#include "TLeaf.h" -#include "TEventList.h" #include "TROOT.h" #include "TMultiLayerPerceptron.h" #include "ThreadLocalStorage.h" diff --git a/tree/tree/src/TEventList.cxx b/tree/tree/src/TEventList.cxx index 700358f16bb8b..fbdcbd833d2cf 100644 --- a/tree/tree/src/TEventList.cxx +++ b/tree/tree/src/TEventList.cxx @@ -50,6 +50,7 @@ the TEventList object created in the above commands: #include "TBuffer.h" #include "TCut.h" #include "TDirectory.h" +#include "TMathBase.h" #include "TROOT.h" //////////////////////////////////////////////////////////////////////////////// From 6e32b35eb012628febb972d9e0e4c2484c38c6f4 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 15:12:07 +0200 Subject: [PATCH 07/10] [NFC] Remove dead mentions of TEventList. --- roottest/root/tree/cache/variableCluster.C | 19 +++---------------- tree/treeplayer/src/TTreePlayer.cxx | 2 -- tree/treeviewer/src/TSpider.cxx | 2 -- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/roottest/root/tree/cache/variableCluster.C b/roottest/root/tree/cache/variableCluster.C index a712392e5feb6..de107e8a40324 100644 --- a/roottest/root/tree/cache/variableCluster.C +++ b/roottest/root/tree/cache/variableCluster.C @@ -220,26 +220,13 @@ Long64_t checkBoundary(TTree *tree, Long64_t entry) TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry); fEntryCurrent = clusterIter(); fEntryNext = clusterIter.GetNextEntry(); - + // fprintf(stdout,"finds = %lld %lld\n",fEntryCurrent,fEntryNext); - + if (fEntryCurrent < fEntryMin) fEntryCurrent = fEntryMin; if (fEntryMax <= 0) fEntryMax = tree->GetEntries(); if (fEntryNext > fEntryMax) fEntryNext = fEntryMax; - - // Check if owner has a TEventList set. If yes we optimize for this - // Special case reading only the baskets containing entries in the - // list. -// TEventList *elist = fOwner->GetEventList(); -// Long64_t chainOffset = 0; -// if (elist) { -// if (fOwner->IsA() ==TChain::Class()) { -// TChain *chain = (TChain*)fOwner; -// Int_t t = chain->GetTreeNumber(); -// chainOffset = chain->GetTreeOffset()[t]; -// } -// } - + Int_t flushIntervals = 0; Long64_t minEntry = fEntryCurrent; Long64_t prevNtot; diff --git a/tree/treeplayer/src/TTreePlayer.cxx b/tree/treeplayer/src/TTreePlayer.cxx index 4065337e4d956..6decc11d535fb 100644 --- a/tree/treeplayer/src/TTreePlayer.cxx +++ b/tree/treeplayer/src/TTreePlayer.cxx @@ -622,8 +622,6 @@ Long64_t TTreePlayer::GetEntriesToProcess(Long64_t firstentry, Long64_t nentries lastentry = fTree->GetEntriesFriend() - 1; nentries = lastentry - firstentry + 1; } - //TEventList *elist = fTree->GetEventList(); - //if (elist && elist->GetN() < nentries) nentries = elist->GetN(); TEntryList *elist = fTree->GetEntryList(); if (elist && elist->GetN() < nentries) nentries = elist->GetN(); return nentries; diff --git a/tree/treeviewer/src/TSpider.cxx b/tree/treeviewer/src/TSpider.cxx index 4b8bd6b06c7c9..205939bb3bd3d 100644 --- a/tree/treeviewer/src/TSpider.cxx +++ b/tree/treeviewer/src/TSpider.cxx @@ -730,8 +730,6 @@ Long64_t TSpider::GetEntriesToProcess(Long64_t firstentry, Long64_t nentries) co lastentry = fTree->GetEntriesFriend() - 1; nentries = lastentry - firstentry + 1; } - //TEventList *elist = fTree->GetEventList(); - //if (elist && elist->GetN() < nentries) nentries = elist->GetN(); TEntryList *elist = fTree->GetEntryList(); if (elist && elist->GetN() < nentries) nentries = elist->GetN(); return nentries; From ff0843cd3ea596cab0ad7769b4ba4eaf8ad5ef52 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 15:24:41 +0200 Subject: [PATCH 08/10] [treeplayer] Explicitly add TEventList/TEntryList to gDirectory. The TTree::Draw documentation states that entry lists and event lists are added to gDirectory. To make this fact independent of ROOT 7 mode, explicitly add instances of these classes to gDirectory. --- tree/treeplayer/src/TSelectorDraw.cxx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tree/treeplayer/src/TSelectorDraw.cxx b/tree/treeplayer/src/TSelectorDraw.cxx index 8aa71aec11512..01f09336ee59d 100644 --- a/tree/treeplayer/src/TSelectorDraw.cxx +++ b/tree/treeplayer/src/TSelectorDraw.cxx @@ -410,6 +410,7 @@ void TSelectorDraw::Begin(TTree *tree) } else { enlist = new TEntryList(hname, realSelection.GetTitle()); } + enlist->SetDirectory(gDirectory); // TTree::Draw documentation promises it shows up in gDirectory } if (enlist) { if (!hnameplus) { @@ -421,6 +422,7 @@ void TSelectorDraw::Begin(TTree *tree) } else { inElist = new TEntryList(*enlist); } + inElist->SetDirectory(gDirectory); // TTree::Draw documentation promises it shows up in gDirectory fCleanElist = true; fTree->SetEntryList(inElist); } @@ -445,6 +447,7 @@ void TSelectorDraw::Begin(TTree *tree) } if (!evlist) { evlist = new TEventList(hname, realSelection.GetTitle(), 1000, 0); + evlist->SetDirectory(gDirectory); // TTree::Draw documentation promises it shows up in gDirectory } if (evlist) { if (!hnameplus) { From 978ee50b9667df96b4afb588a57e5e1ba084f536 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 15:26:36 +0200 Subject: [PATCH 09/10] [mlp] Prepare mlp for working with TEventList without auto registration. When TEventLists don't register themselves to gDirectory, TTree::Draw expressions can't fill them. Therefore, a few lists need to be added to gDirectory manually. Once their Draw expressions have run, they can be removed again. --- math/mlp/src/TMLPAnalyzer.cxx | 2 ++ math/mlp/src/TMultiLayerPerceptron.cxx | 22 +++++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/math/mlp/src/TMLPAnalyzer.cxx b/math/mlp/src/TMLPAnalyzer.cxx index 39271c1e00c7f..3827fea8b1612 100644 --- a/math/mlp/src/TMLPAnalyzer.cxx +++ b/math/mlp/src/TMLPAnalyzer.cxx @@ -349,7 +349,9 @@ void TMLPAnalyzer::DrawNetwork(Int_t neuron, const char* signal, const char* bg) Int_t j=0; // build event lists for signal and background TEventList* signal_list = new TEventList("__tmpSig_MLPA"); + signal_list->SetDirectory(gDirectory); TEventList* bg_list = new TEventList("__tmpBkg_MLPA"); + bg_list->SetDirectory(gDirectory); data->Draw(">>__tmpSig_MLPA",signal,"goff"); data->Draw(">>__tmpBkg_MLPA",bg,"goff"); diff --git a/math/mlp/src/TMultiLayerPerceptron.cxx b/math/mlp/src/TMultiLayerPerceptron.cxx index 4683272659768..24309428c5179 100644 --- a/math/mlp/src/TMultiLayerPerceptron.cxx +++ b/math/mlp/src/TMultiLayerPerceptron.cxx @@ -459,12 +459,12 @@ TMultiLayerPerceptron::TMultiLayerPerceptron(const char * layout, TTree * data, fCurrentTree = -1; fCurrentTreeWeight = 1; { - TDirectory::TContext ctxt; + TDirectory::TContext ctxt{nullptr}; fTraining = new TEventList(Form("fTrainingList_%zu",(size_t)this)); } fTrainingOwner = true; { - TDirectory::TContext ctxt; + TDirectory::TContext ctxt{nullptr}; fTest = new TEventList(Form("fTestList_%zu",(size_t)this)); } fTestOwner = true; @@ -479,8 +479,12 @@ TMultiLayerPerceptron::TMultiLayerPerceptron(const char * layout, TTree * data, fManager = nullptr; if (data) { BuildNetwork(); + fTraining->SetDirectory(gDirectory); + fTest->SetDirectory(gDirectory); data->Draw(Form(">>fTrainingList_%zu",(size_t)this),training,"goff"); data->Draw(Form(">>fTestList_%zu",(size_t)this),(const char *)testcut,"goff"); + fTraining->SetDirectory(nullptr); + fTest->SetDirectory(nullptr); AttachData(); } else { @@ -538,12 +542,12 @@ TMultiLayerPerceptron::TMultiLayerPerceptron(const char * layout, fCurrentTree = -1; fCurrentTreeWeight = 1; { - TDirectory::TContext ctxt; + TDirectory::TContext ctxt{nullptr}; fTraining = new TEventList(Form("fTrainingList_%zu",(size_t)this)); } fTrainingOwner = true; { - TDirectory::TContext ctxt; + TDirectory::TContext ctxt{nullptr}; fTest = new TEventList(Form("fTestList_%zu",(size_t)this)); } fTestOwner = true; @@ -558,8 +562,12 @@ TMultiLayerPerceptron::TMultiLayerPerceptron(const char * layout, fManager = nullptr; if (data) { BuildNetwork(); + fTraining->SetDirectory(gDirectory); + fTest->SetDirectory(gDirectory); data->Draw(Form(">>fTrainingList_%zu",(size_t)this),training,"goff"); data->Draw(Form(">>fTestList_%zu",(size_t)this),(const char *)testcut,"goff"); + fTraining->SetDirectory(nullptr); + fTest->SetDirectory(nullptr); AttachData(); } else { @@ -646,12 +654,14 @@ void TMultiLayerPerceptron::SetTrainingDataSet(const char * train) { if(fTraining && fTrainingOwner) delete fTraining; { - TDirectory::TContext ctxt; + TDirectory::TContext ctxt{nullptr}; fTraining = new TEventList(Form("fTrainingList_%zu",(size_t)this)); } fTrainingOwner = true; if (fData) { + fTraining->SetDirectory(gDirectory); fData->Draw(Form(">>fTrainingList_%zu",(size_t)this),train,"goff"); + fTraining->SetDirectory(nullptr); } else { Warning("TMultiLayerPerceptron::TMultiLayerPerceptron","Data not set. Cannot define datasets"); @@ -673,7 +683,9 @@ void TMultiLayerPerceptron::SetTestDataSet(const char * test) } fTestOwner = true; if (fData) { + fTraining->SetDirectory(gDirectory); fData->Draw(Form(">>fTestList_%zu",(size_t)this),test,"goff"); + fTraining->SetDirectory(nullptr); } else { Warning("TMultiLayerPerceptron::TMultiLayerPerceptron","Data not set. Cannot define datasets"); From ee711eeb9918fd64872e7420b367e36b6d3ab015 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 14 Jul 2026 15:29:51 +0200 Subject: [PATCH 10/10] fixup! [mlp] Prepare mlp for working with TEventList without auto registration. --- math/mlp/src/TMLPAnalyzer.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/math/mlp/src/TMLPAnalyzer.cxx b/math/mlp/src/TMLPAnalyzer.cxx index 3827fea8b1612..afe7851f69062 100644 --- a/math/mlp/src/TMLPAnalyzer.cxx +++ b/math/mlp/src/TMLPAnalyzer.cxx @@ -349,8 +349,8 @@ void TMLPAnalyzer::DrawNetwork(Int_t neuron, const char* signal, const char* bg) Int_t j=0; // build event lists for signal and background TEventList* signal_list = new TEventList("__tmpSig_MLPA"); - signal_list->SetDirectory(gDirectory); TEventList* bg_list = new TEventList("__tmpBkg_MLPA"); + signal_list->SetDirectory(gDirectory); bg_list->SetDirectory(gDirectory); data->Draw(">>__tmpSig_MLPA",signal,"goff"); data->Draw(">>__tmpBkg_MLPA",bg,"goff");