From 0307c70bb90d214e5f742ffc6811fd23a8846001 Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Sun, 17 Aug 2025 23:34:04 +0200 Subject: [PATCH] [tutorials] Make ttree tutorials independent of test files Copy over some test files to the build and install tree to the tutorials directory, in order to enable some more TTree tutorials for testing. Closes #13548. --- CMakeLists.txt | 3 ++- tutorials/CMakeLists.txt | 11 ++++++++++- tutorials/io/tree/tree108_tree.C | 21 +++++++++++++++++--- tutorials/io/tree/tree110_copy.C | 33 ++++++++++++++++++++------------ tutorials/io/tree/tree111_copy.C | 33 ++++++++++++++++++++------------ tutorials/io/tree/tree112_copy.C | 32 ++++++++++++++++++++----------- 6 files changed, 93 insertions(+), 40 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index acf8a68fe3a3a..7f009d9ca00fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -424,7 +424,6 @@ if(roofit) endif() ROOT_ADD_TEST_SUBDIRECTORY(test) -ROOT_ADD_TEST_SUBDIRECTORY(tutorials) # Each subdirectory added above will register headers to be copied to the build tree. # Here, the copy targets are created: @@ -574,6 +573,8 @@ if(runtime_cxxmodules) set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "${library_output_dir}/modules.timestamp") endif() +ROOT_ADD_TEST_SUBDIRECTORY(tutorials) + #---hsimple.root---------(use the executable for clearer dependencies and proper return code)--- add_custom_target(hsimple ALL DEPENDS tutorials/hsimple.root) add_dependencies(hsimple onepcm) diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 2418f7612050a..600533d283035 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -20,9 +20,11 @@ if(DEFINED ROOT_SOURCE_DIR) # Testing using the binary tree set(ROOT_environ PATH=${CMAKE_BINARY_DIR}/bin:$ENV{PATH} ${ld_library_path}=${CMAKE_BINARY_DIR}/lib:$ENV{${ld_library_path}} ROOTSYS=${CMAKE_BINARY_DIR} + ROOT_INCLUDE_PATH=${CMAKE_BINARY_DIR}/tutorials/io/tree PYTHONPATH=${CMAKE_BINARY_DIR}/lib:$ENV{PYTHONPATH}) else() set(ROOT_environ ROOTSYS=${CMAKE_BINARY_DIR} + ROOT_INCLUDE_PATH=${CMAKE_BINARY_DIR}/tutorials/io/tree PYTHONPATH=${CMAKE_BINARY_DIR}/bin;$ENV{PYTHONPATH}) endif() else() # testing using an installation @@ -423,7 +425,6 @@ set(extra_veto io/tree/hsimpleProxy.C # A driver uses this macro which cannot be executed directly io/tree/tree103_tree.C io/tree/tree106_tree.C - io/tree/tree108_tree.C roofit/roostats/rs401d_FeldmanCousins.C # Takes too much time roofit/roostats/rs401d_FeldmanCousins.py roofit/histfactory/ModifyInterpolation.C @@ -437,6 +438,11 @@ set(extra_veto math/r/rootlogon.C roofit/roostats/StandardFrequentistDiscovery.C) +configure_file(${CMAKE_SOURCE_DIR}/test/Event.h ${CMAKE_BINARY_DIR}/tutorials/io/tree/Event.h COPYONLY) +configure_file(${CMAKE_SOURCE_DIR}/test/Event.cxx ${CMAKE_BINARY_DIR}/tutorials/io/tree/Event.cxx COPYONLY) +install(FILES ${CMAKE_SOURCE_DIR}/test/Event.h ${CMAKE_SOURCE_DIR}/test/Event.cxx + DESTINATION ${CMAKE_INSTALL_TUTDIR}/io/tree COMPONENT tests) + if(MSVC) # disable run_h1analysis.C because of Endpoint Security HTTP traffic scanning, # which is corrupting the data on Windows @@ -549,6 +555,9 @@ set(io-xml-xmlmodifyfile-depends tutorial-io-xml-xmlnewfile) set(io-xml-xmlreadfile-depends tutorial-io-xml-xmlnewfile) set(roofit-roofit-rf503_wspaceread-depends tutorial-roofit-roofit-rf502_wspacewrite) set(io-readCode-depends tutorial-io-importCode) +set(io-tree-tree110_copy-depends tutorial-io-tree-tree108_tree) +set(io-tree-tree111_copy-depends tutorial-io-tree-tree108_tree) +set(io-tree-tree112_copy-depends tutorial-io-tree-tree108_tree) set(math-fit-fit1-depends tutorial-hist-hist001_TH1_fillrandom) set(math-fit-myfit-depends tutorial-math-fit-fitslicesy) set(math-foam-foam_demopers-depends tutorial-math-foam-foam_demo) diff --git a/tutorials/io/tree/tree108_tree.C b/tutorials/io/tree/tree108_tree.C index 49c2f127f8384..35c96f604c3b4 100644 --- a/tutorials/io/tree/tree108_tree.C +++ b/tutorials/io/tree/tree108_tree.C @@ -49,7 +49,10 @@ /// /// \author Rene Brun -R__LOAD_LIBRARY($ROOTSYS/test/libEvent) + +#ifdef ACTUAL_RUN // -------- Second pass: dictionary already built -------- + +#include "./Event.h" // now safe to include Event, its dictionary is loaded #include "TFile.h" #include "TTree.h" @@ -59,7 +62,6 @@ R__LOAD_LIBRARY($ROOTSYS/test/libEvent) #include "TClassTable.h" #include "TSystem.h" #include "TROOT.h" -#include "../test/Event.h" void tree108_write() { @@ -168,10 +170,23 @@ void tree108_read() t4->StartViewer(); } -void tree108_tree() +void run() { Event::Reset(); // Allow for re-run this script by cleaning static variables. tree108_write(); Event::Reset(); // Allow for re-run this script by cleaning static variables. tree108_read(); } + +#else // -------- First pass: build dictionary + rerun macro -------- + +void tree108_tree() +{ + TString tutdir = gROOT->GetTutorialDir(); + gROOT->ProcessLine(".L " + tutdir + "/io/tree/Event.cxx+"); + gROOT->ProcessLine("#define ACTUAL_RUN yes"); + gROOT->ProcessLine("#include \"" __FILE__ "\""); + gROOT->ProcessLine("run()"); +} + +#endif diff --git a/tutorials/io/tree/tree110_copy.C b/tutorials/io/tree/tree110_copy.C index 97a8fdd7df7da..4a0ee31ffb20b 100644 --- a/tutorials/io/tree/tree110_copy.C +++ b/tutorials/io/tree/tree110_copy.C @@ -10,31 +10,40 @@ /// /// \author Rene Brun -// Load the library at macro parsing time: we need this to use its content in the code -R__LOAD_LIBRARY($ROOTSYS/test/libEvent) +#ifdef ACTUAL_RUN // -------- Second pass: dictionary already built -------- -void tree110_copy() -{ - - TString dir = "$ROOTSYS/test/Event.root"; - gSystem->ExpandPathName(dir); - const auto filename = gSystem->AccessPathName(dir) ? "./Event.root" : "$ROOTSYS/test/Event.root"; +#include "./Event.h" // now safe to include Event, its dictionary is loaded - TFile oldfile(filename); +void run() +{ + TFile oldfile("tree108.root"); TTree *oldtree; - oldfile.GetObject("T", oldtree); + oldfile.GetObject("t4", oldtree); // Deactivate all branches oldtree->SetBranchStatus("*", 0); // Activate only four of them - for (auto activeBranchName : {"event", "fNtrack", "fNseg", "fH"}) + for (auto activeBranchName : {"event_split", "fNtrack", "fNseg", "fH"}) oldtree->SetBranchStatus(activeBranchName, 1); // Create a new file + a clone of old tree in new file - TFile newfile("small.root", "recreate"); + TFile newfile("tree110.root", "recreate"); auto newtree = oldtree->CloneTree(); newtree->Print(); newfile.Write(); } + +#else // -------- First pass: build dictionary + rerun macro -------- + +void tree110_copy() +{ + TString tutdir = gROOT->GetTutorialDir(); + gROOT->ProcessLine(".L " + tutdir + "/io/tree/Event.cxx+"); + gROOT->ProcessLine("#define ACTUAL_RUN yes"); + gROOT->ProcessLine("#include \"" __FILE__ "\""); + gROOT->ProcessLine("run()"); +} + +#endif diff --git a/tutorials/io/tree/tree111_copy.C b/tutorials/io/tree/tree111_copy.C index 22c702f6035f9..5950a0575c6b8 100644 --- a/tutorials/io/tree/tree111_copy.C +++ b/tutorials/io/tree/tree111_copy.C @@ -11,27 +11,23 @@ /// /// \author Rene Brun -// Load the library at macro parsing time: we need this to use its content in the code -R__LOAD_LIBRARY($ROOTSYS/test/libEvent) +#ifdef ACTUAL_RUN // -------- Second pass: dictionary already built -------- -void tree111_copy() -{ - - TString dir = "$ROOTSYS/test/Event.root"; - gSystem->ExpandPathName(dir); - const auto filename = gSystem->AccessPathName(dir) ? "./Event.root" : "$ROOTSYS/test/Event.root"; +#include "./Event.h" // now safe to include Event, its dictionary is loaded - TFile oldfile(filename); +void run() +{ + TFile oldfile("tree108.root"); TTree *oldtree; - oldfile.GetObject("T", oldtree); + oldfile.GetObject("t4", oldtree); // Activate only four of them - for (auto activeBranchName : {"event", "fNtrack", "fNseg", "fH"}) { + for (auto activeBranchName : {"event_split", "fNtrack", "fNseg", "fH"}) { oldtree->SetBranchStatus(activeBranchName, 1); } // Create a new file + a clone of old tree header. Do not copy events - TFile newfile("small.root", "recreate"); + TFile newfile("tree111.root", "recreate"); auto newtree = oldtree->CloneTree(0); // Divert branch fH to a separate file and copy all events @@ -41,3 +37,16 @@ void tree111_copy() newtree->Print(); newfile.Write(); } + +#else // -------- First pass: build dictionary + rerun macro -------- + +void tree111_copy() +{ + TString tutdir = gROOT->GetTutorialDir(); + gROOT->ProcessLine(".L " + tutdir + "/io/tree/Event.cxx+"); + gROOT->ProcessLine("#define ACTUAL_RUN yes"); + gROOT->ProcessLine("#include \"" __FILE__ "\""); + gROOT->ProcessLine("run()"); +} + +#endif diff --git a/tutorials/io/tree/tree112_copy.C b/tutorials/io/tree/tree112_copy.C index 8b03a984dad5b..cff83d19ea346 100644 --- a/tutorials/io/tree/tree112_copy.C +++ b/tutorials/io/tree/tree112_copy.C @@ -11,26 +11,23 @@ /// /// \author Rene Brun -R__LOAD_LIBRARY($ROOTSYS/test/libEvent) +#ifdef ACTUAL_RUN // -------- Second pass: dictionary already built -------- -void tree112_copy() -{ - // Get old file, old tree and set top branch address - TString dir = "$ROOTSYS/test/Event.root"; - gSystem->ExpandPathName(dir); - const auto filename = gSystem->AccessPathName(dir) ? "./Event.root" : "$ROOTSYS/test/Event.root"; +#include "./Event.h" // now safe to include Event, its dictionary is loaded - TFile oldfile(filename); +void run() +{ + TFile oldfile("tree108.root"); TTree *oldtree; - oldfile.GetObject("T", oldtree); + oldfile.GetObject("t4", oldtree); const auto nentries = oldtree->GetEntries(); Event *event = nullptr; - oldtree->SetBranchAddress("event", &event); + oldtree->SetBranchAddress("event_split", &event); // Create a new file + a clone of old tree in new file - TFile newfile("small.root", "recreate"); + TFile newfile("tree112.root", "recreate"); auto newtree = oldtree->CloneTree(0); for (auto i : ROOT::TSeqI(nentries)) { @@ -43,3 +40,16 @@ void tree112_copy() newtree->Print(); newfile.Write(); } + +#else // -------- First pass: build dictionary + rerun macro -------- + +void tree112_copy() +{ + TString tutdir = gROOT->GetTutorialDir(); + gROOT->ProcessLine(".L " + tutdir + "/io/tree/Event.cxx+"); + gROOT->ProcessLine("#define ACTUAL_RUN yes"); + gROOT->ProcessLine("#include \"" __FILE__ "\""); + gROOT->ProcessLine("run()"); +} + +#endif