diff --git a/analysis/common/analysis_tree_converter/CMakeLists.txt b/analysis/common/analysis_tree_converter/CMakeLists.txt index 3ea7fc00293c3d9ecf4f9394baa738cf97345086..273ea100fa33509187536cb574e21584be157ce6 100644 --- a/analysis/common/analysis_tree_converter/CMakeLists.txt +++ b/analysis/common/analysis_tree_converter/CMakeLists.txt @@ -2,6 +2,10 @@ set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR} ) +#subdirectories +add_subdirectory(app) +add_subdirectory(steer) + set(SRCS CbmConverterManager.cxx CbmConverterTask.cxx diff --git a/analysis/common/analysis_tree_converter/app/Application.cxx b/analysis/common/analysis_tree_converter/app/Application.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2a0a647eb818c75bb84e41e3fe9bfe5f7a0f91ee --- /dev/null +++ b/analysis/common/analysis_tree_converter/app/Application.cxx @@ -0,0 +1,47 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese */ + +/** @file Application.cxx + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 27.10.2023 + **/ + +#include "Application.h" + +#include "Config.h" + +using std::string; + +namespace cbm::atconverter +{ + + // ----- Constructor ---------------------------------------------------- + Application::Application(ProgramOptions const& opt) : fOpt(opt) {} + // -------------------------------------------------------------------------- + + + // ----- Run the reconstruction ----------------------------------------- + void Application::Exec() + { + + // --- Use program options + fRun.SetOutput(fOpt.OutputFile().c_str()); + fRun.SetTraFile(fOpt.TraFile().c_str()); + fRun.SetRawFile(fOpt.RawFile().c_str()); + fRun.SetParFile(fOpt.ParFile().c_str()); + fRun.SetRecoFile(fOpt.RecoFile().c_str()); + fRun.SetGeoSetupTag(fOpt.SetupTag().c_str()); + if (fOpt.Overwrite()) fRun.AllowOverwrite(); + + // --- Read configuration from YAML file + cbm::atconverter::Config config; + config.LoadYaml(fOpt.ConfigFile()); + fRun.SetConfig(config); + + // --- Execute reconstruction run + fRun.Exec(); + } + // -------------------------------------------------------------------------- + +} // namespace cbm::atconverter diff --git a/analysis/common/analysis_tree_converter/app/Application.h b/analysis/common/analysis_tree_converter/app/Application.h new file mode 100644 index 0000000000000000000000000000000000000000..bd762dd7faa601b4234f106496a7c5468ce2b0a3 --- /dev/null +++ b/analysis/common/analysis_tree_converter/app/Application.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese */ + +/** @file Application.h + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 27.10.2023 + **/ + + +#ifndef CBM_ATCONVERTER_APP_APPLICATION_H +#define CBM_ATCONVERTER_APP_APPLICATION 1 + +#include "ProgramOptions.h" +#include "Run.h" + +namespace cbm::atconverter +{ + + class Application { + + + public: + /** @brief Standard constructor, initialises the application + ** @param opt **/ + explicit Application(ProgramOptions const& opt); + + /** @brief Copy constructor forbidden **/ + Application(const Application&) = delete; + + /** @brief Assignment operator forbidden **/ + void operator=(const Application&) = delete; + + /** @brief Destructor **/ + ~Application() = default; + + /** @brief Run the application **/ + void Exec(); + + private: + const std::string& OutputFile() const; + const std::string& TraFile() const; + const std::string& rawFile() const; + const std::string& ParamFile() const; + const std::string& recoFile() const; + const std::string& SetupTag() const; + const std::string& ConfigFile() const; + + + private: + ProgramOptions const& fOpt; ///< Program options object + Run fRun = {}; ///< Reconstruction run + }; + +} // namespace cbm::atconverter + +#endif /* CBM_ATCONVERTER_APP_APPLICATION */ diff --git a/analysis/common/analysis_tree_converter/app/CMakeLists.txt b/analysis/common/analysis_tree_converter/app/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..5c3f2d052300266ef0dd8f1c6ae1a6a7de6a40b6 --- /dev/null +++ b/analysis/common/analysis_tree_converter/app/CMakeLists.txt @@ -0,0 +1,25 @@ +# CMakeList file for binary cbmatc +# F.Linz, 27. October 2023 + +set(SRCS + Application.cxx + ProgramOptions.cxx + main.cxx + ) + +set(HEADERS + Application.h + ProgramOptions.h + ) + + +add_executable(cbm_atconverter ${SRCS} ${HEADERS}) + +target_link_libraries(cbm_atconverter + PUBLIC + CbmAtConverterSteer + PRIVATE + Boost::program_options + ) + +install(TARGETS cbm_atconverter DESTINATION bin) diff --git a/analysis/common/analysis_tree_converter/app/ProgramOptions.cxx b/analysis/common/analysis_tree_converter/app/ProgramOptions.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6f5741b7ad76d3fa8f1fca2df273a7cee075f3a6 --- /dev/null +++ b/analysis/common/analysis_tree_converter/app/ProgramOptions.cxx @@ -0,0 +1,83 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese */ + +/** @file ProgramOptions.cxx + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 27.10.2023 + ** + ** Code taken from reco/app/cbmreco_fairrun/ProgramOptions.cxx (J. de Cuveland) + **/ + +#include "ProgramOptions.h" + +#include <Logger.h> + +#include <boost/program_options.hpp> + +#include <iostream> + +namespace po = boost::program_options; + +using std::string; + +namespace cbm::atconverter +{ + + // ----- Parse command line --------------------------------------------- + void ProgramOptions::ParseOptions(int argc, char* argv[]) + { + + // --- Define generic options + po::options_description generic("Generic options"); + auto generic_add = generic.add_options(); + generic_add("help,h", "display this help and exit"); + + // --- Define configuration options + string defconfig = std::getenv("VMCWORKDIR"); + defconfig.append("/"); + defconfig.append(DEFAULT_CONFIG); + po::options_description config("Configuration"); + auto config_add = config.add_options(); + config_add("output,o", po::value<string>(&fOutput)->value_name("<file name>"), + "name of the output ROOT file with analysistree data"); + config_add("transport,t", po::value<string>(&fTra)->value_name("<file nams>"), + "name of a transport ROOT file (containing MC data)"); + config_add("digitization,d", po::value<string>(&fRaw)->value_name("<file name>"), + "name of the raw ROOT file containing digi data"); + config_add("parameter,p", po::value<string>(&fPar)->value_name("<file name>"), + "name of a parameter ROOT file (FairRuntimeDb format)"); + config_add("reconstruction,r", po::value<string>(&fReco)->value_name("<file nams>"), + "name of a reconstruction ROOT file"); + config_add("config,c", po::value<string>(&fConfig)->value_name("<file name>")->default_value(defconfig), + "name of a YAML file describing the configuration of reconstruction"); + config_add("setup,s", po::value<string>(&fSetup)->value_name("<tag>")->default_value(DEFAULT_SETUP), + "geometry setup tag"); + config_add("overwrite,w", po::bool_switch(&fOverwrite)->default_value(false), + "allow to overwite an existing output file"); + + // --- Allowed options + po::options_description cmdline_options("Allowed options"); + cmdline_options.add(generic).add(config); + + // --- Parse command line + po::variables_map vars; + po::store(po::parse_command_line(argc, argv, cmdline_options), vars); + po::notify(vars); + + // --- Help: print help information and exit program + if (vars.count("help") != 0u) { + std::cout << cmdline_options << std::endl; + exit(EXIT_SUCCESS); + } + + // --- Catch mandatory parameters not being specified + if (vars.count("output") == 0u) { throw std::runtime_error("no output file name specified"); } + if (vars.count("transport") == 0u) { throw std::runtime_error("no transport file name specified"); } + if (vars.count("digitization") == 0u) { throw std::runtime_error("no digitization (raw) file name specified"); } + if (vars.count("parameter") == 0u) { throw std::runtime_error("no parameter file name specified"); } + if (vars.count("reconstruction") == 0u) { throw std::runtime_error("no reconstruction file name specified"); } + } + // -------------------------------------------------------------------------- + +} // namespace cbm::atconverter diff --git a/analysis/common/analysis_tree_converter/app/ProgramOptions.h b/analysis/common/analysis_tree_converter/app/ProgramOptions.h new file mode 100644 index 0000000000000000000000000000000000000000..5c128eb3a8cd66cd71de4359926469b6e39d8b07 --- /dev/null +++ b/analysis/common/analysis_tree_converter/app/ProgramOptions.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese, Jan de Cuveland */ + +/** @file ProgramOptions.h + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 27.10.2023 + ** + ** Code taken from reco/app/cbmreco_fairrun/ProgramOptions.h (J. de Cuveland) + **/ + +#ifndef CBM_ATCONVERTER_APP_PROGRAMOPTIONS_H +#define CBM_ATCONVERTER_APP_PROGRAMOPTIONS_H 1 + +#define DEFAULT_CONFIG "analysis/common/analysistree_converter/config/ATConfig_event_ideal.yaml" +#define DEFAULT_SETUP "sis100_electron" + + +#include <string> + +namespace cbm::atconverter +{ + + /** @class ProgramOptions + ** @author Frederic Linz <f.linz@gsi.de> + ** @since 27 October 2023 + ** + ** Program option class for the application cbmatc + **/ + class ProgramOptions { + public: + /** @brief Standard constructor with command line arguments **/ + ProgramOptions(int argc, char* argv[]) { ParseOptions(argc, argv); } + + /** @brief Copy constructor forbidden **/ + ProgramOptions(const ProgramOptions&) = delete; + + /** @brief Assignment operator forbidden **/ + ProgramOptions& operator=(const ProgramOptions&) = delete; + + /** @brief Destructor **/ + ~ProgramOptions() = default; + + /** @brief Get output file name (.root format) **/ + [[nodiscard]] const std::string& OutputFile() const { return fOutput; } + + /** @brief Get transport file name **/ + [[nodiscard]] const std::string& TraFile() const { return fTra; } + + /** @brief Get digitization file name **/ + [[nodiscard]] const std::string& RawFile() const { return fRaw; } + + /** @brief Get parameter file name **/ + [[nodiscard]] const std::string& ParFile() const { return fPar; } + + /** @brief Get reconstruction file name **/ + [[nodiscard]] const std::string& RecoFile() const { return fReco; } + + /** @brief Get configuration file name (YAML format) **/ + [[nodiscard]] const std::string& ConfigFile() const { return fConfig; } + + /** @brief Get geometry setup tag **/ + [[nodiscard]] const std::string& SetupTag() const { return fSetup; } + + /** @brief Get overwrite option **/ + [[nodiscard]] bool Overwrite() const { return fOverwrite; } + + + private: + /** @brief Parse command line arguments using boost program_options **/ + void ParseOptions(int argc, char* argv[]); + + + private: // members + std::string fOutput = ""; ///< Output file name (ROOT format) + std::string fTra = ""; ///< Transport file name (ROOT format) + std::string fRaw = ""; ///< Digitization file name (ROOT format) + std::string fPar = ""; ///< Parameter file name (ROOT format) + std::string fReco = ""; ///< Reconstruction file name (ROOT format) + std::string fConfig = ""; ///< Configuration file name (YAML format) + std::string fSetup = ""; ///< Geometry setup tag + bool fOverwrite = false; ///< Enable overwriting of existing output file + }; + +} // namespace cbm::atconverter + +#endif /* CBM_ATCONVERTER_APP_PROGRAMOPTIONS_H */ diff --git a/analysis/common/analysis_tree_converter/app/main.cxx b/analysis/common/analysis_tree_converter/app/main.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3f385be540ca4eff2fde2e3d3c896827c3a052fa --- /dev/null +++ b/analysis/common/analysis_tree_converter/app/main.cxx @@ -0,0 +1,26 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese, Jan de Cuveland */ +#include <Logger.h> + +#include "Application.h" +#include "ProgramOptions.h" + +using namespace cbm::atconverter; + +int main(int argc, char* argv[]) +{ + LOG(info) << "***** CBM AnalysisTree Converter *****"; + try { + ProgramOptions opt(argc, argv); + Application app(opt); + app.Exec(); + } + catch (std::exception const& e) { + LOG(error) << e.what() << "; terminating."; + return EXIT_FAILURE; + } + + LOG(info) << "CBM AnalysisTree Converter: Program completed successfully; exiting."; + return EXIT_SUCCESS; +} diff --git a/analysis/common/analysis_tree_converter/config/ATConfig_event_ideal.yaml b/analysis/common/analysis_tree_converter/config/ATConfig_event_ideal.yaml new file mode 100644 index 0000000000000000000000000000000000000000..16b6c3683df17446675aa3a2a95263122c0ab5c9 --- /dev/null +++ b/analysis/common/analysis_tree_converter/config/ATConfig_event_ideal.yaml @@ -0,0 +1,9 @@ +global: + log_level: INFO + log_verbose: LOW + mode: event + nTimeslices: -1 + firstTimeslice: 0 + timeslicelength: 1.e5 + collisionSystem: "Au+Au" + beamMomentum: 12. diff --git a/analysis/common/analysis_tree_converter/config/ATConfig_timeslice.yaml b/analysis/common/analysis_tree_converter/config/ATConfig_timeslice.yaml new file mode 100644 index 0000000000000000000000000000000000000000..64e981d91dbda9cf51ca9fdade5859f8263445dc --- /dev/null +++ b/analysis/common/analysis_tree_converter/config/ATConfig_timeslice.yaml @@ -0,0 +1,9 @@ +global: + log_level: INFO + log_verbose: LOW + mode: timeslice + nTimeslices: -1 + firstTimeslice: 0 + timeslicelength: 1.e5 + collisionSystem: "Au+Au" + beamMomentum: 12. diff --git a/analysis/common/analysis_tree_converter/steer/CMakeLists.txt b/analysis/common/analysis_tree_converter/steer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d417be3123a27a2470683b47324d899cb0cb6bd7 --- /dev/null +++ b/analysis/common/analysis_tree_converter/steer/CMakeLists.txt @@ -0,0 +1,36 @@ +# CMakeList file for library libCbmAtcOfflineSteer +# F. Linz, 27 October 2023 + +set(SRCS + Config.cxx + Run.cxx + TaskFactory.cxx + ) + +set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) + +set(LIBRARY_NAME CbmAtConverterSteer) +set(LINKDEF RootLinkDef.h) +set(PUBLIC_DEPENDENCIES + CbmData + FairRoot::Base + ROOT::Core + external::yaml-cpp + CbmAnalysisTreeInterface + ) + +set(PRIVATE_DEPENDENCIES + CbmBase + CbmTrdBase + CbmTrdReco + FairLogger::FairLogger + FairRoot::Online + ROOT::Hist + ROOT::RHTTP + CbmSimSteer + L1 + KF + Algo + ) + +generate_cbm_library() diff --git a/analysis/common/analysis_tree_converter/steer/Config.cxx b/analysis/common/analysis_tree_converter/steer/Config.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f8f12b666479bed75116170a9d7c35ba27b0a396 --- /dev/null +++ b/analysis/common/analysis_tree_converter/steer/Config.cxx @@ -0,0 +1,90 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese */ + +/** @file .cxx + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 30.10.2023 + **/ + + +#include "Config.h" + +#include <Logger.h> + +#include <fstream> + +#include <yaml-cpp/yaml.h> + +using std::string; + +namespace cbm::atconverter +{ + + + // ----- Load settings from YAML file ------------------------------------- + void Config::LoadYaml(const string& fileName) + { + + LOG(info) << "Config: Reading configuration from " << fileName; + YAML::Node settings = YAML::LoadFile(fileName); + + // --- Global settings + f_glb_logLevel = settings["global"]["log_level"].as<string>(); + f_glb_logVerbose = settings["global"]["log_verbose"].as<string>(); + f_glb_mode = ToCbmRecoMode(settings["global"]["mode"].as<string>()); + f_glb_numTs = settings["global"]["nTimeslices"].as<int>(); + f_glb_firstTs = settings["global"]["firstTimeslice"].as<int>(); + f_glb_tslength = settings["global"]["timeslicelength"].as<float>(); + f_glb_system = settings["global"]["collisionSystem"].as<string>(); + f_glb_beamMom = settings["global"]["beamMomentum"].as<float>(); + } + // ---------------------------------------------------------------------------- + + + // ------ String to ECbmRecoMode ------------------------------------------ + ECbmRecoMode Config::ToCbmRecoMode(string choice) + { + string temp = choice; + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return std::tolower(c); }); + if (temp == "timeslice") return ECbmRecoMode::Timeslice; + else if (temp == "event") + return ECbmRecoMode::EventByEvent; + else + return ECbmRecoMode::Undefined; + } + // ---------------------------------------------------------------------------- + + + // ----- ECbmRecoMode to string ------------------------------------------- + string Config::ToString(ECbmRecoMode mode) + { + if (mode == ECbmRecoMode::Timeslice) return "timeslice"; + else if (mode == ECbmRecoMode::EventByEvent) + return "event"; + else + return "undefined"; + } + // ---------------------------------------------------------------------------- + + + // ----- Save settings to YAML node --------------------------------------- + YAML::Node Config::ToYaml() + { + YAML::Node settings; + + // --- Global settings + settings["global"]["log_level"] = f_glb_logLevel; + settings["global"]["log_verbose"] = f_glb_logVerbose; + settings["global"]["mode"] = ToString(f_glb_mode); + settings["global"]["nTimeslices"] = f_glb_numTs; + settings["global"]["firstTimeslice"] = f_glb_firstTs; + settings["global"]["timeslicelength"] = f_glb_tslength; + settings["global"]["collisionSystem"] = f_glb_system; + settings["global"]["beamMomentum"] = f_glb_beamMom; + + return settings; + } + // ---------------------------------------------------------------------------- + +} // namespace cbm::atconverter diff --git a/analysis/common/analysis_tree_converter/steer/Config.h b/analysis/common/analysis_tree_converter/steer/Config.h new file mode 100644 index 0000000000000000000000000000000000000000..640653323667e021863b90945875d74994c3544b --- /dev/null +++ b/analysis/common/analysis_tree_converter/steer/Config.h @@ -0,0 +1,102 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese */ + +/** @file Config.h + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 30.10.2023 + **/ + +#ifndef CBM_ATCONVERTER_STEER_CONFIG_H +#define CBM_ATCONVERTER_STEER_CONFIG_H 1 + +#include "CbmDefs.h" + +#include <array> +#include <fstream> +#include <sstream> +#include <string> + +#include <yaml-cpp/yaml.h> + +namespace cbm::atconverter +{ + + enum class ECbmEvbuildType + { + Ideal, + Real, + Undefined + }; + + + /** @class Config + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 30.10.2023 + ** + ** Configuration for the analysis tree converter, replacing run_analysis_tree_maker_json_config.C. + ** With interfaces to YAML. + **/ + class Config { + public: + /** @brief Constructor **/ + Config() = default; + + + /** @brief Destructor **/ + virtual ~Config() = default; + + + /** @brief Load from YAML file + ** @param filename Name of input YAML file + **/ + void LoadYaml(const std::string& filename); + + + /** @brief String output (YAML format) **/ + std::string ToString() + { + std::stringstream out; + out << ToYaml(); + return out.str(); + } + + + /** @brief Save to YAML file + ** @param filename Name of output YAML file + **/ + void SaveYaml(const std::string& filename) + { + std::ofstream fout(filename); + fout << ToYaml(); + } + + + private: + ECbmRecoMode ToCbmRecoMode(std::string tag); + std::string ToString(ECbmRecoMode mode); + + /** @brief Save to YAML node **/ + YAML::Node ToYaml(); + + + public: + // --- Global settings + std::string f_glb_logLevel = "INFO"; + std::string f_glb_logVerbose = "LOW"; + ECbmRecoMode f_glb_mode = ECbmRecoMode::Undefined; + int f_glb_numTs = -1; + int f_glb_firstTs = 0; + float f_glb_tslength = 1.e5; + + std::string f_glb_system = ""; + float f_glb_beamMom = 12.; + + // --- Event builder + ECbmEvbuildType f_evbuild_type = ECbmEvbuildType::Undefined; + }; + +} // namespace cbm::atconverter + + +#endif /* CBM_ATCONVERTER_STEER_CONFIG_H */ diff --git a/analysis/common/analysis_tree_converter/steer/RootLinkDef.h b/analysis/common/analysis_tree_converter/steer/RootLinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..5820bebb1d4071572f27e4e315b8648e20a00604 --- /dev/null +++ b/analysis/common/analysis_tree_converter/steer/RootLinkDef.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese */ + +// ===== LinkDef for atconverter/task ===== + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +// --- Classes +#pragma link C++ class cbm::atconverter::Run + ; + + +#endif /* __CINT__ */ diff --git a/analysis/common/analysis_tree_converter/steer/Run.cxx b/analysis/common/analysis_tree_converter/steer/Run.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2b300e7f360f23698dc1258a3a27ff636a8ceae4 --- /dev/null +++ b/analysis/common/analysis_tree_converter/steer/Run.cxx @@ -0,0 +1,182 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese, Florian Uhlig */ + +/** @file Run.cxx + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 27.10.2023 + **/ + +#include "Run.h" + +#include "CbmSetup.h" + +#include <FairEventHeader.h> +#include <FairFileSource.h> +#include <FairMonitor.h> +#include <FairParRootFileIo.h> +#include <FairRootFileSink.h> +#include <FairRunAna.h> +#include <FairRuntimeDb.h> +#include <FairTask.h> +#include <Logger.h> + +#include "TaskFactory.h" +#include <TFile.h> +#include <TGeoManager.h> +#include <TStopwatch.h> +#include <TString.h> +#include <TTree.h> + +#include <cassert> +#include <iostream> + +#include <sys/stat.h> + +namespace cbm::atconverter +{ + + + // ----- Constructor ---------------------------------------------------- + Run::Run() : TNamed("Run", "CBM AnalysisTree Converter Run") {} + // -------------------------------------------------------------------------- + + + // ----- Destructor ----------------------------------------------------- + Run::~Run() { LOG(debug) << "Destructing " << fName; } + // -------------------------------------------------------------------------- + + + // ----- Add a reconstruction task -------------------------------------- + void Run::AddTask(FairTask* task) + { + fRun.AddTask(task); + LOG(info) << GetName() << ": Added task " << task->GetName(); + } + // -------------------------------------------------------------------------- + + + // ----- Check existence of a file -------------------------------------- + bool Run::CheckFile(const char* fileName) + { + struct stat buffer; + return (stat(fileName, &buffer) == 0); + } + // -------------------------------------------------------------------------- + + + // ----- Create the topology -------------------------------------------- + void Run::CreateTopology() + { + + TaskFactory fact(this); + + fact.RegisterMCDataManager(fTra); + fact.RegisterCaTracking(); + fact.RegisterTrdPid(); + fact.RegisterConverterManager(fOutput); + } + // -------------------------------------------------------------------------- + + + // ----- Execute reconstruction run ------------------------------------- + void Run::Exec() + { + + // --- Mirror options and configuration + LOG(info) << GetName() << ": Output file is " << fOutput; + LOG(info) << GetName() << ": Transport file is " << fTra; + LOG(info) << GetName() << ": Digitization file is " << fRaw; + LOG(info) << GetName() << ": Parameter file is " << fPar; + LOG(info) << GetName() << ": Reconstruction file is " << fReco; + LOG(info) << GetName() << ": Geometry setup is " << fSetupTag; + LOG(info) << "Configuration: \n" << fConfig.ToString() << "\n"; + + // --- Timer + TStopwatch timer; + timer.Start(); + + // --- Run info + fRun.SetGenerateRunInfo(true); + + // --- Check input, output and parameter files + if (CheckFile(fOutput.Data()) && !fOverwrite) throw std::runtime_error("Output file already exists"); + if (!CheckFile(fTra.Data())) throw std::runtime_error("Transport file does not exist"); + if (!CheckFile(fRaw.Data())) throw std::runtime_error("Digitizazion (raw) file does not exist"); + if (!CheckFile(fPar.Data())) throw std::runtime_error("Parameter file does not exist"); + if (!CheckFile(fReco.Data())) throw std::runtime_error("Reconstruction file does not exist"); + + // --- Input and output + FairFileSource* source = new FairFileSource(fReco); + source->AddFriend(fTra); + source->AddFriend(fRaw); + fRun.SetSource(source); + fRun.SetSink(new FairRootFileSink(fOutput)); + + // --- Geometry setup + LOG(info) << GetName() << ": Loading setup " << fSetupTag; + fSetup = CbmSetup::Instance(); + fSetup->LoadSetup(fSetupTag); + // TODO: This CbmSetup business with singleton is not nice. Should be replaced eventually. + + // --- Topology + LOG(info) << GetName() << ": Creating topology..."; + CreateTopology(); + + // --- Parameter database + LOG(info) << GetName() << ": Set runtime DB..."; + FairRuntimeDb* rtdb = fRun.GetRuntimeDb(); + FairParRootFileIo* parIo1 = new FairParRootFileIo(); + parIo1->open(fPar.Data(), "UPDATE"); + rtdb->setFirstInput(parIo1); + + // --- Initialisation + LOG(info) << GetName() << ": Initialise FairRun..." << std::endl; + fRun.Init(); + rtdb->setOutput(parIo1); + rtdb->saveOutput(); + rtdb->print(); + timer.Stop(); + double timeInit = timer.RealTime(); + timer.Start(); + + // --- Execute run + std::cout << std::endl << std::endl; + LOG(info) << GetName() << ": Starting run" << std::endl; + fRun.Run(fConfig.f_glb_firstTs, fConfig.f_glb_numTs); + + // --- Finish + timer.Stop(); + double timeExec = timer.RealTime(); + FairMonitor::GetMonitor()->Print(); + std::cout << std::endl << std::endl; + LOG(info) << GetName() << ": Execution successful"; + LOG(info) << GetName() << ": Reconstruction file was " << fReco; + LOG(info) << GetName() << ": Transport file file is " << fTra; + ; + LOG(info) << GetName() << ": Parameter file is " << fPar; + LOG(info) << GetName() << ": Digitization file file is " << fRaw; + LOG(info) << GetName() << ": Output file is " << fOutput; + LOG(info) << GetName() << ": Execution time: Init " << timeInit << " s, Exec " << timeExec << "s"; + } + // -------------------------------------------------------------------------- + + + // ----- Read configuration from YAML file ------------------------------- + void Run::LoadConfig(const char* fileName) + { + + TString file(fileName); + if (file.IsNull()) { + file = std::getenv("VMCWORKDIR"); + file += "/reco/offline/config/RecoConfig_event_ideal.yaml"; + } + LOG(info) << GetName() << ": Loading configuration from " << file; + fConfig.LoadYaml(file.Data()); + } + // -------------------------------------------------------------------------- + + +} // namespace cbm::atconverter + +ClassImp(cbm::atconverter::Run) diff --git a/analysis/common/analysis_tree_converter/steer/Run.h b/analysis/common/analysis_tree_converter/steer/Run.h new file mode 100644 index 0000000000000000000000000000000000000000..a9f95a19c426d921c6b0e8689304ae2bf01464bf --- /dev/null +++ b/analysis/common/analysis_tree_converter/steer/Run.h @@ -0,0 +1,156 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese */ + +/** @file Run.h + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 27.10.2023 + **/ + +#ifndef CBM_ATCONVERTER_STEER_RUN_H +#define CBM_ATCONVERTER_STEER_RUN_H 1 + +#include "CbmDefs.h" + +#include <FairRunAna.h> + +#include <TNamed.h> +#include <TString.h> + +#include <string> + +#include "Config.h" + +class CbmSetup; +class FairTask; + +namespace cbm::atconverter +{ + + class Run : public TNamed { + + public: + /** @brief Constructor **/ + Run(); + + + /** @brief Destructor **/ + virtual ~Run(); + + + /** @brief Add a task to the run **/ + void AddTask(FairTask* task); + + + /** @brief Allow overwriting if output file already exists **/ + void AllowOverwrite() { fOverwrite = true; } + + + /** @brief Run reconstruction **/ + void Exec(); + + + /** @brief Settings object **/ + const Config& GetConfig() const { return fConfig; } + + + /** @brief Presence of input digi data + ** @param detector Detector data to check + ** @return true if data present, else false + **/ + bool IsDataPresent(ECbmModuleId detector) const { return (fDataPresent.count(detector) == 0 ? false : true); } + + + /** @brief Set configuration file name + ** @param fileName Configuration file name + ** + ** Legacy interface for running from ROOT prompt. In the executable, the config is read in + ** by the application. + **/ + void LoadConfig(const char* fileName); + + + /** @brief Set configuration + ** @param fileName Configuration object + **/ + void SetConfig(const Config& config) { fConfig = config; } + + + /** @brief Set geometry setup tag + ** @param tag Geometry setup tag + **/ + void SetGeoSetupTag(const char* tag) { fSetupTag = tag; } + + + /** @brief Set output file name + ** @param fileName Output file name + **/ + void SetOutput(const char* fileName) { fOutput = fileName; } + + + /** @brief Set transport file name + ** @param fileName Transport file name + **/ + void SetTraFile(const char* fileName) { fTra = fileName; } + + + /** @brief Set digitizazion (raw) file name + ** @param fileName Digitization file name + **/ + void SetRawFile(const char* fileName) { fRaw = fileName; } + + + /** @brief Set parameter file name + ** @param fileName Parameter file name + **/ + void SetParFile(const char* fileName) { fPar = fileName; } + + + /** @brief Set reconstruction file name + ** @param fileName Reconstruction file name + **/ + void SetRecoFile(const char* fileName) { fReco = fileName; } + + + private: + /** @brief Copy constructor forbidden **/ + Run(const Run&) = delete; + + + /** @brief Assignment operator forbidden **/ + Run operator=(const Run&) = delete; + + + /** @brief Check existence of a file + ** @param fileName File name (absolute or relative to current directory) + ** @return true if file exists + **/ + bool CheckFile(const char* fileName); + + + /** @brief Create the reconstruction task topology (chain) **/ + void CreateTopology(); + + + private: + FairRunAna fRun {}; + TString fOutput = ""; + TString fTra = ""; + TString fRaw = ""; + TString fPar = ""; + TString fReco = ""; + TString fSetupTag = ""; + CbmSetup* fSetup = nullptr; + bool fOverwrite = false; + + public: + Config fConfig = {}; + std::set<ECbmModuleId> fDataPresent = {}; + + + ClassDef(cbm::atconverter::Run, 1); + }; + +} // namespace cbm::atconverter + +#endif /* CBM_ATCONVERTER_STEER_RUN_H */ diff --git a/analysis/common/analysis_tree_converter/steer/TaskFactory.cxx b/analysis/common/analysis_tree_converter/steer/TaskFactory.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1ccc65e2fedc19078a167a0ace80597ab8e84cb9 --- /dev/null +++ b/analysis/common/analysis_tree_converter/steer/TaskFactory.cxx @@ -0,0 +1,120 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese */ + +/** @file TaskFactory.cxx + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 30.10.2023 + **/ + +#include "TaskFactory.h" + +#include "CbmConverterManager.h" +#include "CbmKF.h" +#include "CbmL1.h" +#include "CbmMCDataManager.h" +#include "CbmMatchEvents.h" +#include "CbmPsdModulesConverter.h" +#include "CbmRecEventHeaderConverter.h" +#include "CbmRichRingsConverter.h" +#include "CbmSetup.h" +#include "CbmSimEventHeaderConverter.h" +#include "CbmSimTracksConverter.h" +#include "CbmStsTracksConverter.h" +#include "CbmTofHitsConverter.h" +#include "CbmTrackingDetectorInterfaceInit.h" +#include "CbmTrdSetTracksPidLike.h" +#include "CbmTrdTracksConverter.h" + +#include <TSystem.h> + + +namespace cbm::atconverter +{ + + + // ----- Constructor ---------------------------------------------------- + TaskFactory::TaskFactory(Run* run) : fRun(run) {} + // -------------------------------------------------------------------------- + + + // ----- CA tracking ---------------------------------------------------- + void TaskFactory::RegisterCaTracking() + { + assert(fRun); + + // --- Tracking geometry interface + auto interface = new CbmTrackingDetectorInterfaceInit(); + fRun->AddTask(interface); + + // --- Kalman Filter // Move after L1 task? + auto kf = new CbmKF(); + fRun->AddTask(kf); + + // --- CA Track Finder + auto ca = new CbmL1("CA Track Finder", 1, 3); + fRun->AddTask(ca); + } + // -------------------------------------------------------------------------- + + + // ----- Converter Manager ---------------------------------------------- + void TaskFactory::RegisterConverterManager(const TString& outputFile) + { + assert(fRun); + + // AnalysisTree converter + auto* man = new CbmConverterManager(); + + man->SetSystem(fRun->fConfig.f_glb_system); + man->SetBeamMomentum(fRun->fConfig.f_glb_beamMom); + man->SetTimeSliceLength(fRun->fConfig.f_glb_tslength); + man->SetOutputName(outputFile.Data(), "rTree"); + + if (fRun->fConfig.f_glb_mode == ECbmRecoMode::Timeslice) { man->AddTask(new CbmMatchEvents()); } + + // --- Converter for different branches + man->AddTask(new CbmSimEventHeaderConverter("SimEventHeader")); + man->AddTask(new CbmRecEventHeaderConverter("RecEventHeader")); + man->AddTask(new CbmSimTracksConverter("SimParticles")); + + auto* ststracksconverter = new CbmStsTracksConverter("VtxTracks", "SimParticles"); + ststracksconverter->SetIsWriteKFInfo(); + ststracksconverter->SetIsReproduceCbmKFPF(); + man->AddTask(ststracksconverter); + + man->AddTask(new CbmRichRingsConverter("RichRings", "VtxTracks")); + man->AddTask(new CbmTofHitsConverter("TofHits", "VtxTracks")); + man->AddTask(new CbmTrdTracksConverter("TrdTracks", "VtxTracks")); + man->AddTask(new CbmPsdModulesConverter("PsdModules")); + + fRun->AddTask(man); + } + // -------------------------------------------------------------------------- + + + // ----- MC data manager ------------------------------------------------ + void TaskFactory::RegisterMCDataManager(const TString& traFile) + { + assert(fRun); + CbmMCDataManager* mcManager = new CbmMCDataManager("MCDataManager", 0); + mcManager->AddFile(traFile); + fRun->AddTask(mcManager); + } + // -------------------------------------------------------------------------- + + + // ----- TID PID -------------------------------------------------------- + void TaskFactory::RegisterTrdPid() + { + assert(fRun); + if (!fRun->IsDataPresent(ECbmModuleId::kTrd)) return; + + CbmTrdSetTracksPidLike* trdPid = new CbmTrdSetTracksPidLike("TRDLikelihood", "TRDLikelihood"); + trdPid->SetUseMCInfo(kTRUE); + trdPid->SetUseMomDependence(kTRUE); + fRun->AddTask(trdPid); + } + // -------------------------------------------------------------------------- + +} // namespace cbm::atconverter diff --git a/analysis/common/analysis_tree_converter/steer/TaskFactory.h b/analysis/common/analysis_tree_converter/steer/TaskFactory.h new file mode 100644 index 0000000000000000000000000000000000000000..41472a38580b93166396aca9e16598ca403cf8ea --- /dev/null +++ b/analysis/common/analysis_tree_converter/steer/TaskFactory.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Frederic Linz [committer], Volker Friese */ + +/** @file TaskFactory.h + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 30.10.2023 + **/ + +#ifndef CBM_ATCONVERTER_STEER_TASKFACTORY_H +#define CBM_ATCONVERTER_STEER_TASKFACTORY_H 1 + +#include "Run.h" + +namespace cbm::atconverter +{ + + /** @class TaskFactory + ** @brief Factory class for the instantiation of CBM analysis tree converter tasks + ** @author Frederic Linz <f.linz@gsi.de> + ** @since 30 October 2023 + **/ + class TaskFactory { + public: + /** @brief Constructor **/ + TaskFactory(Run* steer = nullptr); + + /** @brief Destructor **/ + virtual ~TaskFactory() {}; + + /** @brief MC data manager for matching + ** @param traFile name of transport file + **/ + void RegisterMCDataManager(const TString& traFile); + + /** @brief AnalysisTree Converter Manager + ** @param outputFile name of AT file + **/ + void RegisterConverterManager(const TString& outputFile); + + void RegisterCaTracking(); /// CA track finding + void RegisterTrdPid(); /// PID with TRD + + private: //members + Run* fRun = nullptr; + bool hitMatching = false; + }; + +} // namespace cbm::atconverter + +#endif /* CBM_ATCONVERTER_STEER_TASKFACTORY_H */