From 9b9eb8c4ec7f6e44ede296c28473f6a576a27ea1 Mon Sep 17 00:00:00 2001 From: Adrien Matta <matta@lpccaen.in2p3.fr> Date: Mon, 10 May 2021 17:46:31 +0200 Subject: [PATCH] * npanalysis now support splitting tree output - output one tree per detector in a folder with associated .tree file --- NPLib/CMakeLists.txt | 6 +- NPLib/Core/NPDetectorManager.cxx | 8 +- NPLib/Core/NPDetectorManager.h | 8 + NPLib/Core/NPOptionManager.cxx | 9 +- NPLib/Core/NPOptionManager.h | 14 +- NPLib/Core/RootInput.cxx | 4 +- NPLib/Core/RootInput.h | 4 +- NPLib/Core/RootOutput.cxx | 329 ++++++++++-------- NPLib/Core/RootOutput.h | 46 ++- NPLib/Detectors/Minos/TMinosPhysics.cxx | 2 +- NPLib/Detectors/Nebula/TNebulaPhysics.cxx | 2 +- .../Detectors/Samurai/TSamuraiFDC0Physics.cxx | 2 +- .../Detectors/Samurai/TSamuraiFDC2Physics.cxx | 2 +- .../Samurai/TSamuraiHodoscopePhysics.cxx | 2 +- NPLib/Utility/npanalysis.cxx | 11 +- NPSimulation/Simulation.cc | 3 +- 16 files changed, 265 insertions(+), 187 deletions(-) diff --git a/NPLib/CMakeLists.txt b/NPLib/CMakeLists.txt index dae59391e..6f39ad175 100644 --- a/NPLib/CMakeLists.txt +++ b/NPLib/CMakeLists.txt @@ -11,11 +11,11 @@ include("${CMAKE_BINARY_DIR}/ressources/CMake/NPTool_CMake_Preamble.cmake") # Major change in the Core/Physics (affecting the detector/analysis/simulation) -set(NPLIB_VERSION_MAJOR 2) +set(NPLIB_VERSION_MAJOR 3) # Minor change in the Core/Physics (not affecting any other part) -set(NPLIB_VERSION_MINOR 2) +set(NPLIB_VERSION_MINOR 0) # Change any of the detector in NPA -set(NPLIB_VERSION_DETA 45) +set(NPLIB_VERSION_DETA 0) #activate Multithreading (on by default) if(NOT DEFINED NPMULTITHREADING) diff --git a/NPLib/Core/NPDetectorManager.cxx b/NPLib/Core/NPDetectorManager.cxx index 490684d23..0b000bc0b 100644 --- a/NPLib/Core/NPDetectorManager.cxx +++ b/NPLib/Core/NPDetectorManager.cxx @@ -88,6 +88,7 @@ NPL::DetectorManager::DetectorManager(){ m_ShieldFrontRadius = 0 ; m_ShieldBackRadius = 0 ; m_ShieldMaterial = "" ; + m_RootOutput=RootOutput::getInstance(); } @@ -266,7 +267,6 @@ void NPL::DetectorManager::BuildPhysicalEvent(){ for (it =begin; it != end; ++it) { (it->second->*m_ClearEventPhysicsPtr)(); (it->second->*m_BuildPhysicalPtr)(); - if(m_FillSpectra){ (it->second->*m_FillSpectra)(); if(m_CheckSpectra) (it->second->*m_CheckSpectra)(); @@ -498,6 +498,12 @@ void NPL::DetectorManager::CheckSpectraServer(){ std::cout <<"WARNING: requesting to check spectra server, which is not started" << std::endl; } + +//////////////////////////////////////////////////////////////////////////////// +void NPL::DetectorManager::FillOutputTree(){ + m_RootOutput->Fill(); +} + //////////////////////////////////////////////////////////////////////////////// bool NPL::DetectorManager::IsCryogenic() const {return m_CryoTarget;}; double NPL::DetectorManager::GetTargetThickness() const {return m_TargetThickness;}; diff --git a/NPLib/Core/NPDetectorManager.h b/NPLib/Core/NPDetectorManager.h index 07e280bcc..f6f94d0c0 100644 --- a/NPLib/Core/NPDetectorManager.h +++ b/NPLib/Core/NPDetectorManager.h @@ -23,6 +23,7 @@ // NPL #include "NPVDetector.h" #include "NPSpectraServer.h" +#include "RootOutput.h" // ROOT #include "TH1.h" @@ -67,6 +68,13 @@ namespace NPL{ private : NPL::SpectraServer* m_SpectraServer; + + private:// root outpu + RootOutput* m_RootOutput; + + public: + void FillOutputTree(); + private: // The std::map containning all detectors // Using a Map one can access to any detector using its name diff --git a/NPLib/Core/NPOptionManager.cxx b/NPLib/Core/NPOptionManager.cxx index a38c8569e..450c4ddf7 100644 --- a/NPLib/Core/NPOptionManager.cxx +++ b/NPLib/Core/NPOptionManager.cxx @@ -106,6 +106,8 @@ void NPOptionManager::ReadTheInputArgument(int argc, char** argv){ fLastPhyFile = false; fLastResFile = false; fLastAnyFile = false; + fIsAnalysis = false; + fIsSimulation= false; fVerboseLevel = 1; fNumberOfEntryToAnalyse = -1; fFirstEntryToAnalyse = 0; @@ -114,7 +116,6 @@ void NPOptionManager::ReadTheInputArgument(int argc, char** argv){ fDisableAllBranchOption = false; fInputPhysicalTreeOption = false; fGenerateHistoOption = false ; - fPROOFMode = false; fCircularTree = false; fOnline = false; fG4BatchMode = false; @@ -158,6 +159,8 @@ void NPOptionManager::ReadTheInputArgument(int argc, char** argv){ else if (argument == "-T" && argc >= i + 2) { std::string file = argv[++i] ; std::string tree = argv[++i]; CreateRunToTreatFile(file,tree);} else if (argument == "--cal" && argc >= i + 1) fCalibrationFileName = argv[++i] ; + + else if (argument == "-S" && argc >= i + 1) fIsSplit=true; else if (argument == "-C" && argc >= i + 1) fCalibrationFileName = argv[++i] ; @@ -185,8 +188,6 @@ void NPOptionManager::ReadTheInputArgument(int argc, char** argv){ else if (argument == "--generate-histo") fGenerateHistoOption = true ; - else if (argument == "--proof") fPROOFMode = true ; - else if (argument == "-L") fNumberOfEntryToAnalyse = atoi(argv[++i]) ; else if (argument == "--random-seed") fRandomSeed = atoi(argv[++i]) ; @@ -444,12 +445,12 @@ void NPOptionManager::DisplayHelp(){ std::cout << "\t--output -O <arg>\t\tSet arg as the Output File Name (output tree)" << std::endl ; std::cout << "\t--tree-name <arg>\t\tSet arg as the Output Tree Name " << std::endl ; std::cout << "\t--definition <definition> \tAdd <definition> to the list of definition" << std::endl ; + std::cout << "\t-S \t\t\t\tOne tree output per detector" << std::endl ; std::cout << "\t--verbose -V <arg>\t\tSet the verbose level, 0 for nothing, 1 for normal printout."<<std::endl; std::cout << "\t\t\t\t\tError and warning are not affected" << std::endl ; std::cout << std::endl << "NPAnalysis only:"<<std::endl; std::cout << "\t--run -R <arg>\t\t\tSet arg as the run to read file list" << std::endl ; std::cout << "\t-T <name> <file>\t\tTree <name> from root file <file>" << std::endl ; - std::cout << "\t--cal -C <arg>\t\t\tSet arg as the calibration file list" << std::endl ; std::cout << "\t--disable-branch\t\tDisable of branch of Input tree except the one of the detector (faster)" << std::endl ; std::cout << "\t--generate-histo -GH\t\tInstantiate the T*Spectra class of each detector" << std::endl ; diff --git a/NPLib/Core/NPOptionManager.h b/NPLib/Core/NPOptionManager.h index a793188b7..8268a4ba9 100644 --- a/NPLib/Core/NPOptionManager.h +++ b/NPLib/Core/NPOptionManager.h @@ -103,9 +103,12 @@ class NPOptionManager{ bool GetGenerateHistoOption() {return fGenerateHistoOption;} bool GetCheckHistoOption() {return fCheckHistoOption;} bool GetOnline() {return fOnline;} - bool GetPROOF() {return fPROOFMode;} bool GetG4BatchMode() {return fG4BatchMode;} - bool GetCircularTree() {return fCircularTree;} + bool GetCircularTree() {return fCircularTree;} + bool IsAnalysis() {return fIsAnalysis;}; + bool IsSimulation() {return fIsSimulation;} + bool IsSplit() {return fIsSplit;} + int GetVerboseLevel() {return fVerboseLevel;} int GetNumberOfEntryToAnalyse() {return fNumberOfEntryToAnalyse;} int GetFirstEntryToAnalyse() {return fFirstEntryToAnalyse;} @@ -121,7 +124,8 @@ class NPOptionManager{ void SetDetectorFile(const std::string& name) {fDetectorFileName = name;CheckDetectorConfiguration();} void SetRunToReadFile(const std::string& name) {fRunToReadFileName = name;} void SetVerboseLevel(int VerboseLevel) {fVerboseLevel = VerboseLevel;} - + void SetIsAnalysis(bool val=true){fIsAnalysis=val;}; + void SetIsSimulation(bool val=true){fIsSimulation=val;} public: // user definition bool HasDefinition(std::string def) {return(fDefinition.find(def)!=fDefinition.end());} @@ -143,17 +147,19 @@ class NPOptionManager{ std::string fCalibrationFileName; std::string fOutputFileName; std::string fOutputTreeName; + bool fIsSplit; // One tree per detector bool fDisableAllBranchOption; bool fInputPhysicalTreeOption; bool fGenerateHistoOption; bool fCheckHistoOption; bool fOnline; // true if spectra server is started - bool fPROOFMode; // if true, the system run in a pROOF environment bool fLastSimFile; bool fLastPhyFile; bool fLastResFile; bool fLastAnyFile; bool fCircularTree; + bool fIsAnalysis; + bool fIsSimulation; int fVerboseLevel; // 0 for not talk, 1 for talking int fNumberOfEntryToAnalyse; // use to limit the number of analysed in NPA int fFirstEntryToAnalyse; // use to set the first event analysed in NPA (total: fFirstEntryToAnalyse -> fFirstEntryToAnalyse + fNumberOfEntryToAnalyse) diff --git a/NPLib/Core/RootInput.cxx b/NPLib/Core/RootInput.cxx index e14e60357..b92a4f766 100644 --- a/NPLib/Core/RootInput.cxx +++ b/NPLib/Core/RootInput.cxx @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * Copyright (C) 2009-2021 this file is part of the NPTool Project * * * * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * * For the list of contributors see $NPTOOL/Licence/Contributors * @@ -9,7 +9,7 @@ * Original Author: N. de Sereville contact address: deserevi@ipno.in2p3.fr * * * * Creation Date : 21/07/09 * - * Last update : * + * Last update : 10/05/21 Add support for Split tree input (A. Matta) * *---------------------------------------------------------------------------* * Decription: This class is a singleton class which deals with the ROOT * * input file and tree both for NPSimulation and NPAnalysis. * diff --git a/NPLib/Core/RootInput.h b/NPLib/Core/RootInput.h index 51c479956..ab64a9a73 100644 --- a/NPLib/Core/RootInput.h +++ b/NPLib/Core/RootInput.h @@ -1,7 +1,7 @@ #ifndef ROOTINPUT_HH #define ROOTINPUT_HH /***************************************************************************** - * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * Copyright (C) 2009-2021 this file is part of the NPTool Project * * * * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * * For the list of contributors see $NPTOOL/Licence/Contributors * @@ -11,7 +11,7 @@ * Original Author: N. de Sereville contact address: deserevi@ipno.in2p3.fr * * * * Creation Date : 21/07/09 * - * Last update : * + * Last update : 10/05/21 Add support for Split tree input (A. Matta) * *---------------------------------------------------------------------------* * Decription: This class is a singleton class which deals with the ROOT * * input file and tree both for NPSimulation and NPAnalysis. * diff --git a/NPLib/Core/RootOutput.cxx b/NPLib/Core/RootOutput.cxx index 80400e84f..023353dd8 100644 --- a/NPLib/Core/RootOutput.cxx +++ b/NPLib/Core/RootOutput.cxx @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * Copyright (C) 2009-2021 this file is part of the NPTool Project * * * * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * * For the list of contributors see $NPTOOL/Licence/Contributors * @@ -9,13 +9,14 @@ * Original Author: N. de Sereville contact address: deserevi@ipno.in2p3.fr * * * * Creation Date : 21/07/09 * - * Last update : 03/02/11 * + * Last update : 10/05/21 * *---------------------------------------------------------------------------* * Decription: This class is a singleton class which deals with the ROOT * * output file and tree both for NPSimulation and NPAnalysis. * *---------------------------------------------------------------------------* * Comment: * * + 03/02/11: Add support for TAsciiFile objects (N. de Sereville) * + * + 10/05/21: Add support for split tree output (A. Matta) * * * * * *****************************************************************************/ @@ -31,10 +32,10 @@ using namespace std; RootOutput* RootOutput::instance = 0; //////////////////////////////////////////////////////////////////////////////// -RootOutput* RootOutput::getInstance(std::string fileNameBase, std::string treeNameBase){ +RootOutput* RootOutput::getInstance(std::string fileNameBase, std::string treeNameBase,bool split){ // A new instance of RootOutput is created if it does not exist: if (instance == 0) { - instance = new RootOutput(fileNameBase.c_str(), treeNameBase.c_str()); + instance = new RootOutput(fileNameBase.c_str(), treeNameBase.c_str(),split); } // The instance of RootOutput is returned: @@ -50,103 +51,159 @@ void RootOutput::Destroy(){ } //////////////////////////////////////////////////////////////////////////////// -RootOutput::RootOutput(std::string fileNameBase, std::string treeNameBase){ - TDirectory* currentPath= gDirectory; +RootOutput::RootOutput(std::string fileNameBase, std::string treeNameBase,bool split){ + pSplit = (split || NPOptionManager::getInstance()->IsSplit()); + cout << endl << "/////////// ROOT Output files ///////////" << endl; + cout << "Initializing ouput trees and files "; + if(pSplit) + cout << "in split mode (one tree per detector)" << endl; + + pTreeName=treeNameBase; + pCurrentDirectory= gDirectory; bool analysis=false; bool simulation=false; - if(fileNameBase.find("Analysis/")!=std::string::npos){ + + if(NPOptionManager::getInstance()->IsAnalysis()){ analysis = true; - fileNameBase.erase(0,8); } - else if(fileNameBase.find("Simulation/")!=std::string::npos){ + else if(NPOptionManager::getInstance()->IsAnalysis()){ simulation= true; - fileNameBase.erase(0,10); } - // The ROOT file is created - if(!NPOptionManager::getInstance()->GetPROOF()){ - std::string fileName; - if(analysis) - fileName = NPOptionManager::getInstance()->GetAnalysisOutputPath(); - else if(simulation) - fileName = NPOptionManager::getInstance()->GetSimulationOutputPath(); - else - fileName="./"; - - if (fileNameBase.find("root")!=std::string::npos) fileName += fileNameBase; - else fileName += fileNameBase + ".root"; - - pRootFile = new TFile(fileName.c_str(), "RECREATE"); - - if(treeNameBase=="SimulatedTree"){ - string path = getenv("NPTOOL"); - path+="/.last_sim_file"; - ofstream last_sim_file(path.c_str()); - last_sim_file << "TTreeName" << endl - << " " << treeNameBase <<endl - << "RootFileName" <<endl - << " " << fileName<<endl; - last_sim_file.close(); + // Setup the base name + if(analysis) + pBaseName = NPOptionManager::getInstance()->GetAnalysisOutputPath(); + else if(simulation) + pBaseName = NPOptionManager::getInstance()->GetSimulationOutputPath(); + else + pBaseName="./"; + + pBaseName += "/"+fileNameBase; + + if (fileNameBase.find("root")==std::string::npos) + pBaseName += ".root"; + + if(pSplit){ + // Create a folder for all the trees + string stripname = pBaseName; + stripname.erase(stripname.find(".root"),5); + string path = stripname.substr(0,stripname.rfind("/")); + string filebase = stripname.substr(stripname.rfind("/")+1); + string command = "mkdir -p "+stripname; + int res = system(command.c_str()); + if(res!=0){ + std::cout << "Error creating folder " << stripname << std::endl; + exit(1); } + // create the master file + pMasterFile=stripname+"/"+filebase+".tree"; + ofstream master(pMasterFile.c_str(),std::ofstream::trunc); + master.close(); + } + else{ + CreateTreeAndFile("global"); + } + ///// + // Create the last file + if(treeNameBase=="SimulatedTree"){ + string path = getenv("NPTOOL"); + path+="/.last_sim_file"; + ofstream last_sim_file(path.c_str()); + last_sim_file << "Tree "<< pTreeName <<endl + << " " << pBaseName<<endl; + last_sim_file.close(); + } - else if(treeNameBase=="PhysicsTree"){ - string path = getenv("NPTOOL"); - path+="/.last_phy_file"; - ofstream last_phy_file(path.c_str()); - last_phy_file << "TTreeName" << endl - << " " << treeNameBase <<endl - << "RootFileName" <<endl - << " " << fileName<<endl; - last_phy_file.close(); - } + else if(treeNameBase=="PhysicsTree"){ + string path = getenv("NPTOOL"); + path+="/.last_phy_file"; + ofstream last_phy_file(path.c_str()); + last_phy_file << "Tree "<< pTreeName<<endl + << " " << pBaseName <<endl; + last_phy_file.close(); + } + else if(treeNameBase=="ResultTree"){ + string path = getenv("NPTOOL"); + path+="/.last_res_file"; + ofstream last_res_file(path.c_str()); + last_res_file << "Tree " << pTreeName << endl + << " " << pBaseName<<endl; + last_res_file.close(); + } - else if(treeNameBase=="ResultTree"){ - string path = getenv("NPTOOL"); - path+="/.last_res_file"; - ofstream last_res_file(path.c_str()); - last_res_file << "TTreeName" << endl - << " " << treeNameBase <<endl - << "RootFileName" <<endl - << " " << fileName<<endl; - last_res_file.close(); - } - - else{ - string path = getenv("NPTOOL"); - path+="/.last_any_file"; - ofstream last_any_file(path.c_str()); - last_any_file << "TTreeName" << endl - << " " << treeNameBase <<endl - << "RootFileName" <<endl - << " " << fileName << endl; - last_any_file.close(); - } + else{ + string path = getenv("NPTOOL"); + path+="/.last_any_file"; + ofstream last_any_file(path.c_str()); + last_any_file << "Tree " << pTreeName <<endl + << " " << pBaseName<< endl; + last_any_file.close(); + } + InitAsciiFiles(); +} +//////////////////////////////////////////////////////////////////////////////// +void RootOutput::CreateTreeAndFile(std::string name){ + // Create the tree only if does not exist already + string file_name=pBaseName; + if(name!="global"){ + string strip= pBaseName.substr(pBaseName.rfind("/")); + strip = strip.substr(0,strip.rfind(".root")); + string insertion= "_"+name; + file_name.insert(file_name.rfind(".root"),insertion); + file_name.insert(file_name.rfind("/"),strip); } - else{ // the file path must be the current directory - // Does not create the Output file at instantiation - pRootFile = 0 ; - } + if(pRootFiles.find(name)==pRootFiles.end()){ + cout << " - Creating output file " << file_name.c_str() << endl; + pRootFiles[name] = new TFile(file_name.c_str(), "RECREATE"); + pRootTrees[name] = new TTree(pTreeName.c_str(), "Data created / analysed with the nptool package"); + pRootFiles[name]->SetCompressionLevel(1); - pRootTree = new TTree(treeNameBase.c_str(), "Data created / analysed with the NPTool package"); - pRootFile->SetCompressionLevel(1); - pRootList = new TList(); + // Init TAsciiFile objects + gDirectory->cd(pCurrentDirectory->GetPath()); - // Init TAsciiFile objects - InitAsciiFiles(); - gDirectory->cd(currentPath->GetPath()); + if(NPOptionManager::getInstance()->GetCircularTree()){ + cout << "Information: Output tree is set to circular mode" << endl; + pRootTrees[name]->SetCircular(1000); + } - if(NPOptionManager::getInstance()->GetCircularTree()){ - cout << "Information: Output tree is set to circular mode" << endl; - pRootTree->SetCircular(1000); - } + if(pSplit){// Add the tree to the .tree file + ofstream master(pMasterFile.c_str(),std::ofstream::app); + file_name = file_name.substr(file_name.rfind("/")+1); + master << file_name.c_str() << endl; + master.close(); + } + } + // + /* + for(auto it = m_DetectorMap.begin() ; it!=m_DetectorMap.end() ;++it){ + string insertion = "_"+it->first; + master << filebase << insertion << ".root" << std::endl; + string filename=path+"/"+filebase+"/"+filebase+insertion+".root"; + auto file = new TFile(filename.c_str(),"RECREATE"); + string treename = "RawTree_"+it->first; + auto tree = new TTree("RawTree",treename.c_str()); + m_TreeMap[it->first]=tree; + m_FileMap[it->first]=file; + tree->SetDirectory(file); + std::cout << "Splitting tree: " << filename << std::endl; + it->second->InitBranch(tree); + } + master.close(); + +*/ +} +//////////////////////////////////////////////////////////////////////////////// +void RootOutput::Fill(){ + for(auto it = pRootTrees.begin();it!=pRootTrees.end();it++){ + it->second->Fill(); + } } - //////////////////////////////////////////////////////////////////////////////// void RootOutput::InitAsciiFiles(){ @@ -159,15 +216,15 @@ void RootOutput::InitAsciiFiles(){ pEventGenerator = new TAsciiFile(); pEventGenerator->SetNameTitle("EventGenerator", fileNameEG.c_str()); pEventGenerator->Append(fileNameEG.c_str()); - pEventGenerator->Write(0,TAsciiFile::kOverwrite); - + //pEventGenerator->Write(0,TAsciiFile::kOverwrite); + // Detector configuration // Get file name from NPOptionManager std::string fileNameDC = OptionManager->GetDetectorFile(); pDetectorConfiguration = new TAsciiFile(); pDetectorConfiguration->SetNameTitle("DetectorConfiguration", fileNameDC.c_str()); pDetectorConfiguration->Append(fileNameDC.c_str()); - pDetectorConfiguration->Write(0,TAsciiFile::kOverwrite); + //pDetectorConfiguration->Write(0,TAsciiFile::kOverwrite); // Run to treat file // Get file name from NPOptionManager @@ -176,7 +233,7 @@ void RootOutput::InitAsciiFiles(){ std::string fileNameRT = OptionManager->GetRunToReadFile(); pRunToTreatFile->SetNameTitle("RunToTreat", fileNameRT.c_str()); pRunToTreatFile->Append(fileNameRT.c_str()); - pRunToTreatFile->Write(0,TAsciiFile::kOverwrite); + //pRunToTreatFile->Write(0,TAsciiFile::kOverwrite); } // Calibration files @@ -184,61 +241,44 @@ void RootOutput::InitAsciiFiles(){ if (!OptionManager->IsDefault("Calibration")) { std::string fileNameCal = OptionManager->GetCalibrationFile(); pCalibrationFile->SetNameTitle("Calibration", fileNameCal.c_str()); - pCalibrationFile->Write(0,TAsciiFile::kOverwrite); + //pCalibrationFile->Write(0,TAsciiFile::kOverwrite); } // Analysis configuration files pAnalysisConfigFile = new TAsciiFile(); pAnalysisConfigFile->SetNameTitle("AnalysisConfig", "AnalysisConfig"); - pAnalysisConfigFile->Write(0,TAsciiFile::kOverwrite); + //pAnalysisConfigFile->Write(0,TAsciiFile::kOverwrite); } - - //////////////////////////////////////////////////////////////////////////////// RootOutput::~RootOutput(){ // The data is written to the file and the tree is closed: - if (pRootFile && !NPOptionManager::getInstance()->GetPROOF()) { - TDirectory* currentPath= gDirectory; - gDirectory->cd(pRootFile->GetPath()); - - // write TAsciiFile if used - // EventGenerator - if (!pEventGenerator->IsEmpty()) pEventGenerator->Write(0,TAsciiFile::kOverwrite); - // DetectorConfiguration - if (!pDetectorConfiguration->IsEmpty()) pDetectorConfiguration->Write(0,TAsciiFile::kOverwrite); - // CalibrationFile - if (!pCalibrationFile->IsEmpty()) pCalibrationFile->Write(0,TAsciiFile::kOverwrite); - // RunToTreatFile - if (!pRunToTreatFile->IsEmpty()) pRunToTreatFile->Write(0,TAsciiFile::kOverwrite); - // Analysis ConfigFile - if (!pAnalysisConfigFile->IsEmpty()) pAnalysisConfigFile->Write(0,TAsciiFile::kOverwrite); - - cout << endl; - cout << endl << "Root Output summary" << endl; - cout << " - Number of entries in the Tree: " << pRootTree->GetEntries() << endl; - cout << " - Number of bites written to file: " << pRootTree->Write(0, TObject::kOverwrite) << endl; - pRootFile->Flush(); - pRootFile->Purge(1); - - gDirectory->cd(currentPath->GetPath()); - pRootFile->Close(); - } - - else if (pRootFile && NPOptionManager::getInstance()->GetPROOF()){ - if (!pEventGenerator->IsEmpty()) pEventGenerator->Write(0,TAsciiFile::kOverwrite); - // DetectorConfiguration - if (!pDetectorConfiguration->IsEmpty()) pDetectorConfiguration->Write(0,TAsciiFile::kOverwrite); - // CalibrationFile - if (!pCalibrationFile->IsEmpty()) pCalibrationFile->Write(0,TAsciiFile::kOverwrite); - // RunToTreatFile - if (!pRunToTreatFile->IsEmpty()) pRunToTreatFile->Write(0,TAsciiFile::kOverwrite); - // Analysis ConfigFile - if (!pAnalysisConfigFile->IsEmpty()) pAnalysisConfigFile->Write(0,TAsciiFile::kOverwrite); - } - - else if(!pRootFile && NPOptionManager::getInstance()->GetPROOF()){ - + if (pRootFiles.size()>0) { + cout << endl << endl << "Root Output summary" << endl; + TDirectory* pCurrentDirectory= gDirectory; + for(auto it = pRootFiles.begin(); it!=pRootFiles.end();it++){ + cout << " - " <<it->first << " tree and file " << endl; + gDirectory->cd(it->second->GetPath()); + // write TAsciiFile if used + // EventGenerator + if (!pEventGenerator->IsEmpty()) pEventGenerator->Write(0,TAsciiFile::kOverwrite); + // DetectorConfiguration + if (!pDetectorConfiguration->IsEmpty()) pDetectorConfiguration->Write(0,TAsciiFile::kOverwrite); + // CalibrationFile + if (!pCalibrationFile->IsEmpty()) pCalibrationFile->Write(0,TAsciiFile::kOverwrite); + // RunToTreatFile + if (!pRunToTreatFile->IsEmpty()) pRunToTreatFile->Write(0,TAsciiFile::kOverwrite); + // Analysis ConfigFile + if (!pAnalysisConfigFile->IsEmpty()) pAnalysisConfigFile->Write(0,TAsciiFile::kOverwrite); + + cout << " -> Number of entries in the " << it->first << " Tree: " << pRootTrees[it->first]->GetEntries() << endl; + cout << " -> Number of bites written to file: " << pRootTrees[it->first]->Write(0, TObject::kOverwrite) << endl; + it->second->Flush(); + it->second->Purge(1); + + gDirectory->cd(pCurrentDirectory->GetPath()); + it->second->Close(); + } } else { @@ -247,20 +287,27 @@ RootOutput::~RootOutput(){ } //////////////////////////////////////////////////////////////////////////////// -TFile* RootOutput::InitFile(std::string fileNameBase){ - - if(NPOptionManager::getInstance()->GetPROOF()){ - std::string GlobalPath = getenv("NPTOOL"); - std::string fileName = GlobalPath + "/Outputs/Analysis/"; - if (fileNameBase.find("root")!=std::string::npos) fileName += fileNameBase; - else fileName += fileNameBase + ".root"; - pRootFile = new TFile(fileName.c_str(), "RECREATE"); - pRootFile->Flush(); - return pRootFile; - } +TFile* RootOutput::GetFile(std::string name) { + if(!pSplit) + name="global"; + if(pRootFiles.find(name)!=pRootFiles.end()) + return pRootFiles[name]; else{ - cout << "ERROR: Do not use RootOutput::InitFile without a proof environment (use --proof option to NPTool)" << endl ; + std::cout << "Error: Requested file for detector " << name << " does not exist" << std::endl; exit(1); } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +TTree* RootOutput::GetTree(std::string name) { + if(!pSplit) + name="global"; + + if(pRootTrees.find(name)==pRootTrees.end()) + CreateTreeAndFile(name); + + return pRootTrees[name]; } + diff --git a/NPLib/Core/RootOutput.h b/NPLib/Core/RootOutput.h index 2ac1db601..d2605aa0f 100644 --- a/NPLib/Core/RootOutput.h +++ b/NPLib/Core/RootOutput.h @@ -1,7 +1,7 @@ #ifndef ROOTOUTPUT_HH #define ROOTOUTPUT_HH /***************************************************************************** - * Copyright (C) 2009-2016 this file is part of the NPTool Project * + * Copyright (C) 2009-2021 this file is part of the NPTool Project * * * * For the licensing terms see $NPTOOL/Licence/NPTool_Licence * * For the list of contributors see $NPTOOL/Licence/Contributors * @@ -11,18 +11,20 @@ * Original Author: N. de Sereville contact address: deserevi@ipno.in2p3.fr * * * * Creation Date : 21/07/09 * - * Last update : 03/02/11 * + * Last update : 10/05/21 * *---------------------------------------------------------------------------* * Decription: This class is a singleton class which deals with the ROOT * * output file and tree both for NPSimulation and NPAnalysis. * *---------------------------------------------------------------------------* * Comment: * * + 03/02/11: Add support for TAsciiFile objects (N. de Sereville) * + * + 10/05/21: Add support for split tree output (A. Matta) * * * * * *****************************************************************************/ - +// STL +#include <map> // NPL headers #include "TAsciiFile.h" @@ -41,7 +43,8 @@ public: // it does not yet exist: // (see the constructor for an explanation of the arguments) static RootOutput* getInstance(std::string fileNameBase = "Simulation", - std::string treeNameBase = "SimulatedTree"); + std::string treeNameBase = "SimulatedTree", + bool split = false); // The analysis class instance can be deleted by calling the Destroy // method (NOTE: The class destructor is protected, and can thus not be @@ -50,8 +53,8 @@ public: protected: // Constructor (protected) - RootOutput(std::string fileNameBase, std::string treeNameBase); - + RootOutput(std::string fileNameBase, std::string treeNameBase, bool split=false); + // Destructor (protected) virtual ~RootOutput(); @@ -65,27 +68,32 @@ private: private: void InitAsciiFiles(); - + void CreateTreeAndFile(std::string name); public: - TFile* GetFile() {return pRootFile;} - TTree* GetTree() {return pRootTree;} - TList* GetList() {return pRootList;} + TFile* GetFile(std::string name="global") ; + TTree* GetTree(std::string name="global") ; + TList* GetList(std::string name="global") ; TAsciiFile* GetAsciiFileEventGenerator() {return pEventGenerator;} TAsciiFile* GetAsciiFileDetectorConfiguration() {return pDetectorConfiguration;} TAsciiFile* GetAsciiFileCalibration() {return pCalibrationFile;} TAsciiFile* GetAsciiFileRunToTreat() {return pRunToTreatFile;} TAsciiFile* GetAsciiFileAnalysisConfig() {return pAnalysisConfigFile;} - TFile* InitFile(std::string fileNameBase); // use only for proof environment + void Fill(); private: - TFile *pRootFile; - TTree *pRootTree; - TList *pRootList; - TAsciiFile *pEventGenerator; - TAsciiFile *pDetectorConfiguration; - TAsciiFile *pCalibrationFile; - TAsciiFile *pRunToTreatFile; - TAsciiFile *pAnalysisConfigFile; + std::string pBaseName; + std::string pTreeName; + std::string pMasterFile; + TDirectory* pCurrentDirectory; + bool pSplit; + std::map<std::string, TFile*> pRootFiles; + std::map<std::string, TTree*> pRootTrees; + std::map<std::string, TList*> pRootLists; + TAsciiFile* pEventGenerator; + TAsciiFile* pDetectorConfiguration; + TAsciiFile* pCalibrationFile; + TAsciiFile* pRunToTreatFile; + TAsciiFile* pAnalysisConfigFile; }; diff --git a/NPLib/Detectors/Minos/TMinosPhysics.cxx b/NPLib/Detectors/Minos/TMinosPhysics.cxx index d23cedc5d..3fa3a22a1 100644 --- a/NPLib/Detectors/Minos/TMinosPhysics.cxx +++ b/NPLib/Detectors/Minos/TMinosPhysics.cxx @@ -306,7 +306,7 @@ void TMinosPhysics::InitializeRootInputPhysics() { /////////////////////////////////////////////////////////////////////////// void TMinosPhysics::InitializeRootOutput() { - TTree* outputTree = RootOutput::getInstance()->GetTree(); + TTree* outputTree = RootOutput::getInstance()->GetTree("Minos"); outputTree->Branch("Minos", "TMinosPhysics", &m_EventPhysics); } diff --git a/NPLib/Detectors/Nebula/TNebulaPhysics.cxx b/NPLib/Detectors/Nebula/TNebulaPhysics.cxx index 0035728f3..7a74ce45a 100644 --- a/NPLib/Detectors/Nebula/TNebulaPhysics.cxx +++ b/NPLib/Detectors/Nebula/TNebulaPhysics.cxx @@ -313,7 +313,7 @@ void TNebulaPhysics::InitializeRootInputPhysics() { /////////////////////////////////////////////////////////////////////////// void TNebulaPhysics::InitializeRootOutput() { - TTree* outputTree = RootOutput::getInstance()->GetTree(); + TTree* outputTree = RootOutput::getInstance()->GetTree("Nebula"); outputTree->Branch("Nebula", "TNebulaPhysics", &m_EventPhysics); } diff --git a/NPLib/Detectors/Samurai/TSamuraiFDC0Physics.cxx b/NPLib/Detectors/Samurai/TSamuraiFDC0Physics.cxx index 9c049f7d3..d06456908 100644 --- a/NPLib/Detectors/Samurai/TSamuraiFDC0Physics.cxx +++ b/NPLib/Detectors/Samurai/TSamuraiFDC0Physics.cxx @@ -447,7 +447,7 @@ void TSamuraiFDC0Physics::InitializeRootInputPhysics(){ /////////////////////////////////////////////////////////////////////////// void TSamuraiFDC0Physics::InitializeRootOutput(){ - TTree* outputTree = RootOutput::getInstance()->GetTree(); + TTree* outputTree = RootOutput::getInstance()->GetTree("SamuraiFDC0"); outputTree->Branch( "SamuraiFDC0" , "TSamuraiFDC0Physics" , &m_EventPhysics ); } diff --git a/NPLib/Detectors/Samurai/TSamuraiFDC2Physics.cxx b/NPLib/Detectors/Samurai/TSamuraiFDC2Physics.cxx index cd72f64f4..a443bad1a 100644 --- a/NPLib/Detectors/Samurai/TSamuraiFDC2Physics.cxx +++ b/NPLib/Detectors/Samurai/TSamuraiFDC2Physics.cxx @@ -471,7 +471,7 @@ void TSamuraiFDC2Physics::InitializeRootInputPhysics(){ /////////////////////////////////////////////////////////////////////////// void TSamuraiFDC2Physics::InitializeRootOutput(){ - TTree* outputTree = RootOutput::getInstance()->GetTree(); + TTree* outputTree = RootOutput::getInstance()->GetTree("SamuraiFDC2"); outputTree->Branch( "SamuraiFDC2" , "TSamuraiFDC2Physics" , &m_EventPhysics ); } diff --git a/NPLib/Detectors/Samurai/TSamuraiHodoscopePhysics.cxx b/NPLib/Detectors/Samurai/TSamuraiHodoscopePhysics.cxx index 52de6e132..12741636a 100644 --- a/NPLib/Detectors/Samurai/TSamuraiHodoscopePhysics.cxx +++ b/NPLib/Detectors/Samurai/TSamuraiHodoscopePhysics.cxx @@ -313,7 +313,7 @@ void TSamuraiHodoscopePhysics::InitializeRootInputPhysics() { /////////////////////////////////////////////////////////////////////////// void TSamuraiHodoscopePhysics::InitializeRootOutput() { - TTree* outputTree = RootOutput::getInstance()->GetTree(); + TTree* outputTree = RootOutput::getInstance()->GetTree("SamuraiHodoscope"); outputTree->Branch("SamuraiHodoscope", "TSamuraiHodoscopePhysics", &m_EventPhysics); } diff --git a/NPLib/Utility/npanalysis.cxx b/NPLib/Utility/npanalysis.cxx index 9ad671f30..c33c82ffe 100644 --- a/NPLib/Utility/npanalysis.cxx +++ b/NPLib/Utility/npanalysis.cxx @@ -24,6 +24,7 @@ void ProgressDisplay(struct timeval& begin, struct timeval& end, unsigned long& int main(int argc , char** argv){ // command line parsing NPOptionManager* myOptionManager = NPOptionManager::getInstance(argc,argv); + myOptionManager->SetIsAnalysis(); std::string inputfilename = myOptionManager->GetRunToReadFile(); // if input files are not given, use those from TAsciiFile if (myOptionManager->IsDefault("DetectorConfiguration")) { @@ -68,8 +69,8 @@ int main(int argc , char** argv){ OutputfileName="ResultTree"; } - RootOutput::getInstance("Analysis/"+OutputfileName,TreeName); - TTree* tree= RootOutput::getInstance()->GetTree(); + RootOutput::getInstance(OutputfileName,TreeName); + //TTree* tree= RootOutput::getInstance()->GetTree(); // Instantiate the detector using a file NPL::DetectorManager* myDetector = new NPL::DetectorManager(); @@ -137,7 +138,7 @@ int main(int argc , char** argv){ // Build the current event myDetector->BuildPhysicalEvent(); // Fill the tree - tree->Fill(); + myDetector->FillOutputTree(); current_tree = Chain->GetTreeNumber()+1; //ProgressDisplay(begin,end,treated,inter,nentries,mean_rate,displayed,current_tree,total_tree); @@ -182,7 +183,7 @@ int main(int argc , char** argv){ // User Analysis UserAnalysis->TreatEvent(); // Fill the tree - tree->Fill(); + myDetector->FillOutputTree(); current_tree = Chain->GetTreeNumber()+1; //ProgressDisplay(begin,end,treated,inter,nentries,mean_rate,displayed,current_tree,total_tree); @@ -216,7 +217,7 @@ int main(int argc , char** argv){ // User Analysis UserAnalysis->TreatEvent(); // Fill the tree - tree->Fill(); + myDetector->FillOutputTree(); current_tree = Chain->GetTreeNumber()+1; //ProgressDisplay(begin,end,treated,inter,nentries,mean_rate,displayed,current_tree,total_tree); diff --git a/NPSimulation/Simulation.cc b/NPSimulation/Simulation.cc index ebf11bc19..76bb70d9d 100644 --- a/NPSimulation/Simulation.cc +++ b/NPSimulation/Simulation.cc @@ -39,6 +39,7 @@ int main(int argc, char** argv){ // Initialize NPOptionManager object NPOptionManager* OptionManager = NPOptionManager::getInstance(argc, argv); + OptionManager->SetIsSimulation(); if(OptionManager->GetVerboseLevel() > 0){ string line; line.resize(80,'*'); @@ -76,7 +77,7 @@ int main(int argc, char** argv){ /////////////////////////////////////////////////////////////// ///////////////// Initializing the Root Output //////////////// /////////////////////////////////////////////////////////////// - RootOutput::getInstance("Simulation/" + OptionManager->GetOutputFile()); + RootOutput::getInstance(OptionManager->GetOutputFile()); // Construct the default run manager G4RunManager* runManager = new G4RunManager; -- GitLab