diff --git a/sim/response/CMakeLists.txt b/sim/response/CMakeLists.txt index 3594a5d75bf08c1e9e7de69f9fd4e3135f52582e..0b9ea5aff007cce5644210428a5fc2b2cc6384ec 100644 --- a/sim/response/CMakeLists.txt +++ b/sim/response/CMakeLists.txt @@ -1,3 +1,7 @@ +#subdirectories +add_subdirectory(app) +add_subdirectory(steer) + set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}/base ) diff --git a/sim/response/app/Application.cxx b/sim/response/app/Application.cxx new file mode 100644 index 0000000000000000000000000000000000000000..32cebeb9ee9830e28c61f9054bb1aa082f877f50 --- /dev/null +++ b/sim/response/app/Application.cxx @@ -0,0 +1,45 @@ +/* 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 09.01.2024 + **/ + +#include "Application.h" + +#include "Config.h" + +using std::string; + +namespace cbm::sim::digitization +{ + + // ----- Constructor ---------------------------------------------------- + Application::Application(ProgramOptions const& opt) : fOpt(opt) {} + // -------------------------------------------------------------------------- + + + // ----- Run the reconstruction ----------------------------------------- + void Application::Exec() + { + + // --- Use program options + fRun.SetOutput(fOpt.OutputFile().c_str()); + fRun.SetTraFiles(fOpt.TraFiles()); + fRun.SetParFile(fOpt.ParFile().c_str()); + fRun.SetGeoSetupTag(fOpt.SetupTag().c_str()); + if (fOpt.Overwrite()) fRun.AllowOverwrite(); + + // --- Read configuration from YAML file + cbm::sim::digitization::Config config; + config.LoadYaml(fOpt.ConfigFile()); + fRun.SetConfig(config); + + // --- Execute reconstruction run + fRun.Exec(); + } + // -------------------------------------------------------------------------- + +} // namespace cbm::sim::digitization diff --git a/sim/response/app/Application.h b/sim/response/app/Application.h new file mode 100644 index 0000000000000000000000000000000000000000..b9c47d48c4291ac56be3a83ac22eeda10cbd4832 --- /dev/null +++ b/sim/response/app/Application.h @@ -0,0 +1,55 @@ +/* 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 09.01.2024 + **/ + + +#ifndef CBMSIM_DIGITIZATION_APP_APPLICATION_H +#define CBMSIM_DIGITIZATION_APP_APPLICATION 1 + +#include "ProgramOptions.h" +#include "Run.h" + +namespace cbm::sim::digitization +{ + + 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::vector<std::string>& TraFile() const; + const std::string& ParFile() const; + const std::string& SetupTag() const; + const std::string& ConfigFile() const; + + + private: + ProgramOptions const& fOpt; ///< Program options object + Run fRun = {}; ///< Reconstruction run + }; + +} // namespace cbm::sim::digitization + +#endif /* CBMSIM_DIGITIZATION_APP_APPLICATION */ diff --git a/sim/response/app/CMakeLists.txt b/sim/response/app/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ce446741577b41f0fafb30b93b62bf235bcaadad --- /dev/null +++ b/sim/response/app/CMakeLists.txt @@ -0,0 +1,26 @@ +# CMakeList file for binary cbmatc +# F.Linz, 09. January 2024 + +set(SRCS + Application.cxx + ProgramOptions.cxx + main.cxx + ) + +set(HEADERS + Application.h + ProgramOptions.h + ) + + +add_executable(cbmsim_digitization ${SRCS} ${HEADERS}) + +target_link_libraries(cbmsim_digitization + PUBLIC + CbmSimDigitizationSteer + CbmSimResponse + PRIVATE + Boost::program_options + ) + +install(TARGETS cbmsim_digitization DESTINATION bin) diff --git a/sim/response/app/ProgramOptions.cxx b/sim/response/app/ProgramOptions.cxx new file mode 100644 index 0000000000000000000000000000000000000000..7ca5ee441c3a33ae09053f539a2f868b8dc6570f --- /dev/null +++ b/sim/response/app/ProgramOptions.cxx @@ -0,0 +1,84 @@ +/* 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 09.01.2024 + ** + ** 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; +using std::vector; + +namespace cbm::sim::digitization +{ + + // ----- 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 digi data"); + config_add("transport,t", po::value<vector<string>>(&fTra)->value_name("<file names>")->multitoken(), + "names of a transport input sources (ROOT files)"); + config_add("parameter,p", po::value<string>(&fPar)->value_name("<file name>"), + "name of a parameter ROOT file (FairRuntimeDb format)"); + 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("parameter") == 0u) { + throw std::runtime_error("no parameter file name specified"); + } + } + // -------------------------------------------------------------------------- + +} // namespace cbm::sim::digitization diff --git a/sim/response/app/ProgramOptions.h b/sim/response/app/ProgramOptions.h new file mode 100644 index 0000000000000000000000000000000000000000..8d3058afb8596cc493d9d457d19bf14edf05b547 --- /dev/null +++ b/sim/response/app/ProgramOptions.h @@ -0,0 +1,80 @@ +/* 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 09.01.2024 + ** + ** Code taken from reco/app/cbmreco_fairrun/ProgramOptions.h (J. de Cuveland) + **/ + +#ifndef CBMSIM_DIGITIZATION_APP_PROGRAMOPTIONS_H +#define CBMSIM_DIGITIZATION_APP_PROGRAMOPTIONS_H 1 + +#define DEFAULT_CONFIG "sim/response/config/DigiConfig_event_ideal.yaml" +#define DEFAULT_SETUP "sis100_electron" + + +#include <string> +#include <vector> + +namespace cbm::sim::digitization +{ + + /** @class ProgramOptions + ** @author Frederic Linz <f.linz@gsi.de> + ** @since 09 January 2024 + ** + ** 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::vector<std::string>& TraFiles() const { return fTra; } + + /** @brief Get parameter file name **/ + [[nodiscard]] const std::string& ParFile() const { return fPar; } + + /** @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::vector<std::string> fTra; ///< List of transport input sources (ROOT format) + std::string fPar = ""; ///< Parameter 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::sim::digitization + +#endif /* CBMSIM_DIGITIZATION_APP_PROGRAMOPTIONS_H */ diff --git a/sim/response/app/main.cxx b/sim/response/app/main.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ebec1cfc99593ca2c81c6a369fa485901179f298 --- /dev/null +++ b/sim/response/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 "Application.h" +#include "ProgramOptions.h" + +#include <Logger.h> + +using namespace cbm::sim::digitization; + +int main(int argc, char* argv[]) +{ + LOG(info) << "***** CBM Digitization *****"; + 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 Digitization: Program completed successfully; exiting."; + return EXIT_SUCCESS; +} diff --git a/sim/response/base/Defs.h b/sim/response/base/Defs.h index 0030057a5ba4c3b307b8d657f34d322f33afbcb8..21a8a7e9b36e3c977923d25091bd3f7ce4b645b7 100644 --- a/sim/response/base/Defs.h +++ b/sim/response/base/Defs.h @@ -20,14 +20,16 @@ namespace cbm::sim enum class Mode { Timebased, - EventByEvent + EventByEvent, + Undefined }; /** @enum Time distribution model **/ enum class TimeDist { Poisson, - Uniform + Uniform, + Undefined }; diff --git a/sim/response/config/DigiConfig_event.yaml b/sim/response/config/DigiConfig_event.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6829a650e5296e05edf87e4641bd4e4b7e52a76e --- /dev/null +++ b/sim/response/config/DigiConfig_event.yaml @@ -0,0 +1,20 @@ +global: + log_level: INFO + log_verbose: LOW + log_color: true + mode: event + nTimeslices: -1 + firstTimeslice: -1 +detectors: + deactivate: "" + deactivateAllBut: "" +timeslice: + timeslicelength: 1.e5 + storeAllTimeslices: false + startTime: 1000 + timeDist: poisson +background: + produceNoise: false +sources: + - { id: 0, rate: 1.e5, treeAccessMode: regular, embedToId: -1 } +#TODO: could be potential error to add input via -t file.tra.root in different order than list of sources here diff --git a/sim/response/config/DigiConfig_timeslice.yaml b/sim/response/config/DigiConfig_timeslice.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7989ccf5a0157cd38768677855b9cd1b9b572322 --- /dev/null +++ b/sim/response/config/DigiConfig_timeslice.yaml @@ -0,0 +1,21 @@ +global: + log_level: INFO + log_verbose: LOW + log_color: true + mode: timeslice + nTimeslices: -1 + firstTimeslice: -1 +detectors: + deactivate: "" + deactivateAllBut: "" +timeslice: + timeslicelength: 1.e13 + storeAllTimeslices: false + startTime: 1000 + timeDist: poisson +background: + produceNoise: false +sources: + - { id: 0, rate: 1.e5, treeAccessMode: regular, embedToId: -1 } + # - { id: 1, rate: 1.e7, treeAccessMode: regular, embedToId: -1 } +#TODO: could be potential error to add input via -t file.tra.root in different order than list of sources here diff --git a/sim/response/steer/CMakeLists.txt b/sim/response/steer/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..314b990001aabc1664c4c6d21f5b6b22a198f0df --- /dev/null +++ b/sim/response/steer/CMakeLists.txt @@ -0,0 +1,31 @@ +# CMakeList file for library libCbmSimDigitizationSteer +# F. Linz, 09 January 2024 + +set(SRCS + Config.cxx + Run.cxx + ) + +set(INCLUDE_DIRECTORIES ${CMAKE_CURRENT_SOURCE_DIR}) + +set(LIBRARY_NAME CbmSimDigitizationSteer) +set(LINKDEF RootLinkDef.h) +set(PUBLIC_DEPENDENCIES + CbmData + FairRoot::Base + ROOT::Core + external::yaml-cpp + ) + +set(PRIVATE_DEPENDENCIES + CbmBase + FairLogger::FairLogger + FairRoot::Online + ROOT::Hist + ROOT::RHTTP + CbmSimSteer + CbmSimResponse + Algo + ) + +generate_cbm_library() diff --git a/sim/response/steer/Config.cxx b/sim/response/steer/Config.cxx new file mode 100644 index 0000000000000000000000000000000000000000..6cd0076dceb48169515e970fb2295a5ac3fd1913 --- /dev/null +++ b/sim/response/steer/Config.cxx @@ -0,0 +1,244 @@ +/* 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 10.01.2024 + **/ + + +#include "Config.h" + +#include <Logger.h> + +#include <fstream> + +#include <yaml-cpp/yaml.h> + +using std::string; + +namespace cbm::sim::digitization +{ + + + // ----- 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_logColor = settings["global"]["log_color"].as<string>(); + f_glb_mode = ToCbmDigiMode(settings["global"]["mode"].as<string>()); + f_glb_numTs = settings["global"]["nTimeslices"].as<int>(); + f_glb_firstTs = settings["global"]["firstTimeslice"].as<int>(); + + // --- Detector choice + f_det_deactivateAllBut = ToECbmModuleId(settings["detectors"]["deactivateAllBut"].as<string>()); + f_det_deactivate = ToECbmModuleId(settings["detectors"]["deactivate"].as<string>()); + + // --- Timeslice settings + f_ts_tslength = settings["timeslice"]["timeslicelength"].as<float>(); + f_ts_storeAllTS = settings["timeslice"]["storeAllTimeslices"].as<bool>(); + f_ts_startTime = settings["timeslice"]["startTime"].as<float>(); + f_ts_timeDist = ToCbmSimTimeDist(settings["timeslice"]["timeDist"].as<string>()); + + // --- Background settings + f_bg_produceNoise = settings["background"]["produceNoise"].as<bool>(); + + // --- Input sources + YAML::Node sources = settings["sources"]; + + for (auto source : sources) { + f_src_id.push_back(source["id"].as<int>()); + f_src_rate.push_back(source["rate"].as<float>()); + f_src_treeAccessMode.push_back(ToECbmTreeAccess(source["treeAccessMode"].as<string>())); + f_src_embedToId.push_back(source["embedToId"].as<int>()); + } + } + // ---------------------------------------------------------------------------- + + + // ------ String to ECbmRecoMode ------------------------------------------ + cbm::sim::Mode Config::ToCbmDigiMode(string choice) + { + string temp = choice; + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return std::tolower(c); }); + if (temp == "timeslice") + return cbm::sim::Mode::Timebased; + else if (temp == "event") + return cbm::sim::Mode::EventByEvent; + else + return cbm::sim::Mode::Undefined; + } + // ---------------------------------------------------------------------------- + + + // ----- ECbmRecoMode to string ------------------------------------------- + string Config::ToString(cbm::sim::Mode mode) + { + if (mode == cbm::sim::Mode::Timebased) + return "timeslice"; + else if (mode == cbm::sim::Mode::EventByEvent) + return "event"; + else + return "undefined"; + } + // ---------------------------------------------------------------------------- + + + // ----- String to cbm::sim::TimeDist ------------------------------------- + cbm::sim::TimeDist Config::ToCbmSimTimeDist(string choice) + { + string temp = choice; + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return std::tolower(c); }); + if (temp == "poisson") + return cbm::sim::TimeDist::Poisson; + else if (temp == "uniform") + return cbm::sim::TimeDist::Uniform; + else + return cbm::sim::TimeDist::Undefined; + } + // ---------------------------------------------------------------------------- + + + // ----- cbm::sim::TimeDist to string ------------------------------------- + string Config::ToString(cbm::sim::TimeDist dist) + { + if (dist == cbm::sim::TimeDist::Poisson) + return "poisson"; + else if (dist == cbm::sim::TimeDist::Uniform) + return "uniform"; + else + return "undefined"; + } + // ---------------------------------------------------------------------------- + + + // ----- Convert std::string to ECbmModuleId -------------------------------- + ECbmModuleId Config::ToECbmModuleId(std::string moduleString) + { + std::string temp = moduleString; + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return std::tolower(c); }); + if (temp == "mvd") + return ECbmModuleId::kMvd; + else if (temp == "sts") + return ECbmModuleId::kSts; + else if (temp == "rich") + return ECbmModuleId::kRich; + else if (temp == "much") + return ECbmModuleId::kMuch; + else if (temp == "trd") + return ECbmModuleId::kTrd; + else if (temp == "tof") + return ECbmModuleId::kTof; + else if (temp == "psd") + return ECbmModuleId::kPsd; + else if (temp == "fsd") + return ECbmModuleId::kFsd; + else if (temp == "bmon") + return ECbmModuleId::kBmon; + else + return ECbmModuleId::kNotExist; + } + // ---------------------------------------------------------------------------- + + + // ----- Convert ECbmModuleId to std::string --------------------------------- + string Config::ToString(ECbmModuleId moduleId) + { + if (moduleId == ECbmModuleId::kMvd) + return "mvd"; + else if (moduleId == ECbmModuleId::kSts) + return "sts"; + else if (moduleId == ECbmModuleId::kRich) + return "rich"; + else if (moduleId == ECbmModuleId::kMuch) + return "much"; + else if (moduleId == ECbmModuleId::kTrd) + return "trd"; + else if (moduleId == ECbmModuleId::kTof) + return "tof"; + else if (moduleId == ECbmModuleId::kPsd) + return "psd"; + else if (moduleId == ECbmModuleId::kFsd) + return "fsd"; + else if (moduleId == ECbmModuleId::kBmon) + return "bmon"; + else + return ""; + } + // ---------------------------------------------------------------------------- + + + // ----- Convert std::string to ECbmTreeAccess ------------------------------ + ECbmTreeAccess Config::ToECbmTreeAccess(std::string treeAccessString) + { + std::string temp = treeAccessString; + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return std::tolower(c); }); + if (temp == "random") + return ECbmTreeAccess::kRandom; + else if (temp == "repeat") + return ECbmTreeAccess::kRepeat; + else + return ECbmTreeAccess::kRegular; + } + // ---------------------------------------------------------------------------- + + + // ----- Convert ECbmTreeAccess to std::string ------------------------------ + string Config::ToString(ECbmTreeAccess treeAccessString) + { + if (treeAccessString == ECbmTreeAccess::kRandom) + return "random"; + else if (treeAccessString == ECbmTreeAccess::kRepeat) + return "repeat"; + else + return "regular"; + } + // ---------------------------------------------------------------------------- + + + // ----- 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"]["log_color"] = f_glb_logColor; + settings["global"]["mode"] = ToString(f_glb_mode); + settings["global"]["nTimeslices"] = f_glb_numTs; + settings["global"]["firstTimeslice"] = f_glb_firstTs; + + // --- Detector choice + settings["detectors"]["deactivateAllBut"] = ToString(f_det_deactivateAllBut); + settings["detectors"]["deactivate"] = ToString(f_det_deactivate); + + // --- Timeslice settings + settings["timeslice"]["timeslicelength"] = f_ts_tslength; + settings["timeslice"]["storeAllTimeslices"] = f_ts_storeAllTS; + settings["timeslice"]["startTime"] = f_ts_startTime; + settings["timeslice"]["timeDist"] = ToString(f_ts_timeDist); + + // --- Background settings + settings["background"]["produceNoise"] = f_bg_produceNoise; + + // --- Input sources + for (int i = 0; i < (int) f_src_id.size(); ++i) { + settings["sources"][i]["id"] = f_src_id.at(i); + settings["sources"][i]["rate"] = f_src_rate.at(i); + settings["sources"][i]["treeAccessMode"] = ToString(f_src_treeAccessMode.at(i)); + settings["sources"][i]["embedToId"] = f_src_embedToId.at(i); + } + + return settings; + } + // ---------------------------------------------------------------------------- + +} // namespace cbm::sim::digitization diff --git a/sim/response/steer/Config.h b/sim/response/steer/Config.h new file mode 100644 index 0000000000000000000000000000000000000000..8d8c167b9fd10fb03fcd6306a2da7a60cefa05d9 --- /dev/null +++ b/sim/response/steer/Config.h @@ -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 Config.h + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 09.01.2024 + **/ + +#ifndef CBMSIM_DIGITIZATION_STEER_CONFIG_H +#define CBMSIM_DIGITIZATION_STEER_CONFIG_H 1 + +#include "CbmDefs.h" +#include "CbmDigitization.h" + +#include <array> +#include <fstream> +#include <sstream> +#include <string> +#include <vector> + +#include <yaml-cpp/yaml.h> + +namespace cbm::sim::digitization +{ + + /** @class Config + ** @author Frederic Linz <f.linz@gsi.de> + ** @date 09.01.2024 + ** + ** Configuration for the analysis tree converter, replacing run_digi_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: + cbm::sim::Mode ToCbmDigiMode(std::string tag); + std::string ToString(cbm::sim::Mode mode); + + cbm::sim::TimeDist ToCbmSimTimeDist(std::string tag); + std::string ToString(cbm::sim::TimeDist dist); + + ECbmModuleId ToECbmModuleId(std::string moduleString); + std::string ToString(ECbmModuleId moduleId); + + ECbmTreeAccess ToECbmTreeAccess(std::string treeAccessString); + std::string ToString(ECbmTreeAccess treeAccessString); + + /** @brief Save to YAML node **/ + YAML::Node ToYaml(); + + + public: + // --- Global settings + std::string f_glb_logLevel = "INFO"; + std::string f_glb_logVerbose = "LOW"; + std::string f_glb_logColor = "true"; + cbm::sim::Mode f_glb_mode = cbm::sim::Mode::Undefined; + int f_glb_numTs = -1; + int f_glb_firstTs = 0; + + // --- Detector selection + ECbmModuleId f_det_deactivateAllBut = ECbmModuleId::kNotExist; + ECbmModuleId f_det_deactivate = + ECbmModuleId::kNotExist; // TODO: option should be able to deal with several detectors + + // --- Timeslice settings + float f_ts_tslength = 1.e5; + float f_ts_startTime = 1000.; + bool f_ts_storeAllTS = false; + cbm::sim::TimeDist f_ts_timeDist = + cbm::sim::TimeDist::Undefined; // Event time distribution model: poisson or uniform + + // --- Background settings + bool f_bg_produceNoise = false; + + // --- Input sources settings + std::vector<int> f_src_id; + std::vector<float> f_src_rate; + std::vector<ECbmTreeAccess> f_src_treeAccessMode; + std::vector<int> f_src_embedToId; + }; + +} // namespace cbm::sim::digitization + + +#endif /* CBMSIM_DIGITIZATION_STEER_CONFIG_H */ diff --git a/sim/response/steer/RootLinkDef.h b/sim/response/steer/RootLinkDef.h new file mode 100644 index 0000000000000000000000000000000000000000..ba504d41a7aca47eb5d1c4aac8c27c729c5d1461 --- /dev/null +++ b/sim/response/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 digitizazion/task ===== + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +// --- Classes +#pragma link C++ class cbm::sim::digitization::Run + ; + + +#endif /* __CINT__ */ diff --git a/sim/response/steer/Run.cxx b/sim/response/steer/Run.cxx new file mode 100644 index 0000000000000000000000000000000000000000..bdab3b756d9daeb6b4ed6ed8a06033062c2c07cf --- /dev/null +++ b/sim/response/steer/Run.cxx @@ -0,0 +1,176 @@ +/* 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 "CbmDigitization.h" +#include "CbmSetup.h" + +#include <FairEventHeader.h> +#include <FairMonitor.h> +#include <Logger.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::sim::digitization +{ + + + // ----- Constructor ---------------------------------------------------- + Run::Run() : TNamed("Run", "CBM AnalysisTree Converter Run") {} + // -------------------------------------------------------------------------- + + + // ----- Destructor ----------------------------------------------------- + Run::~Run() { LOG(debug) << "Destructing " << fName; } + // -------------------------------------------------------------------------- + + + // ----- Check existence of a file -------------------------------------- + bool Run::CheckFile(const char* fileName) + { + struct stat buffer; + return (stat(fileName, &buffer) == 0); + } + // -------------------------------------------------------------------------- + + + // ----- Execute reconstruction run ------------------------------------- + void Run::Exec() + { + // --- Mirror options and configuration + LOG(info) << GetName() << ": Output file is " << fOutput; + if (CheckFile(fOutput.Data()) && !fOverwrite) throw std::runtime_error("Output file already exists"); + for (auto trafile : fTra) { + LOG(info) << GetName() << ": Transport input source is " << trafile; + if (!CheckFile(trafile.Data())) throw std::runtime_error("Transport file does not exist"); + } + LOG(info) << GetName() << ": Parameter file is " << fPar; + if (!CheckFile(fPar.Data())) throw std::runtime_error("Parameter file does not exist"); + LOG(info) << GetName() << ": Geometry setup is " << fSetupTag; + LOG(info) << "Configuration: \n" << fConfig.ToString() << "\n"; + + // --- Timer + TStopwatch timer; + timer.Start(); + + // --- Logger settings + FairLogger::GetLogger()->SetLogScreenLevel(fConfig.f_glb_logLevel.data()); + FairLogger::GetLogger()->SetLogVerbosityLevel(fConfig.f_glb_logVerbose.data()); + FairLogger::GetLogger()->SetColoredLog(fConfig.f_glb_logColor.data()); + + // --- Input sources + int sourceId = 0; + for (auto trafile : fTra) { + if (fConfig.f_src_embedToId.at(sourceId) > 0) { + LOG(info) << GetName() << ": Embeding input " << trafile << " (Rate will be ignored)"; + fRun.EmbedInput(fConfig.f_src_id.at(sourceId), trafile, fConfig.f_src_embedToId.at(sourceId)); + } + else { + if (fConfig.f_glb_mode == cbm::sim::Mode::EventByEvent && fConfig.f_src_id.size() > 1) + throw std::runtime_error("Event mixing is not possible in event-by-event mode!"); + + LOG(info) << GetName() << ": Adding input " << trafile; + fRun.AddInput(fConfig.f_src_id.at(sourceId), trafile, fConfig.f_ts_timeDist, fConfig.f_src_rate.at(sourceId), + fConfig.f_src_treeAccessMode.at(sourceId)); + } + } + fRun.SetParameterRootFile(fPar); + fRun.SetMonitorFile((GetFileName(fOutput) + ".moni_digi.root").c_str()); + fRun.SetOutputFile(fOutput, fOverwrite); + + // --- Set digitization parameters + fRun.SetMode(fConfig.f_glb_mode); + if (fConfig.f_glb_mode == cbm::sim::Mode::Timebased) { + fRun.SetTimeSliceLength(fConfig.f_ts_tslength); + fRun.SetStartTime(fConfig.f_ts_startTime); + fRun.StoreAllTimeSlices(fConfig.f_ts_storeAllTS); + } + fRun.SetProduceNoise(fConfig.f_bg_produceNoise); + + // --- Geometry setup + LOG(info) << GetName() << ": Loading setup " << fSetupTag; + fSetup = CbmSetup::Instance(); + fSetup->LoadSetup(fSetupTag); + + if (fConfig.f_det_deactivateAllBut != ECbmModuleId::kNotExist) + fRun.DeactivateAllBut(fConfig.f_det_deactivateAllBut); + if (fConfig.f_det_deactivate != ECbmModuleId::kNotExist) fRun.Deactivate(fConfig.f_det_deactivate); + + 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"; + for (auto trafile : fTra) + LOG(info) << GetName() << ": Transport file was " << trafile; + LOG(info) << GetName() << ": Parameter file was " << fPar; + LOG(info) << GetName() << ": Output file is " << fOutput; + LOG(info) << GetName() << ": Execution time: Init " << timeInit << " s, Exec " << timeExec << "s"; + } + // -------------------------------------------------------------------------- + + + // ----- Get file name without extension --------------------------------- + std::string Run::GetFileName(const TString file) + { + std::string temp(file.Data()); + size_t index = temp.find_last_of("."); + temp = temp.substr(0, index); + std::transform(temp.begin(), temp.end(), temp.begin(), [](unsigned char c) { return c; }); + return temp; + } + // -------------------------------------------------------------------------- + + + // ----- Read configuration from YAML file ------------------------------- + void Run::LoadConfig(const char* fileName) + { + TString file(fileName); + if (file.IsNull()) { + file = std::getenv("VMCWORKDIR"); + file += "/sim/response/config/DigiConfig_event.yaml"; + } + LOG(info) << GetName() << ": Loading configuration from " << file; + fConfig.LoadYaml(file.Data()); + } + // -------------------------------------------------------------------------- + + + // ---- Set input sources ------------------------------------------------- + void Run::SetTraFiles(const std::vector<std::string> files) + { + for (auto file : files) { + fTra.push_back(file.c_str()); + } + } + // -------------------------------------------------------------------------- + +} // namespace cbm::sim::digitization + +ClassImp(cbm::sim::digitization::Run) diff --git a/sim/response/steer/Run.h b/sim/response/steer/Run.h new file mode 100644 index 0000000000000000000000000000000000000000..08ff0a60ec1e3203c7fc664845bfa5b820494c72 --- /dev/null +++ b/sim/response/steer/Run.h @@ -0,0 +1,130 @@ +/* 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 09.01.2024 + **/ + +#ifndef CBMSIM_DIGITIZATION_STEER_RUN_H +#define CBMSIM_DIGITIZATION_STEER_RUN_H 1 + +#include "Config.h" + +#include <TNamed.h> +#include <TString.h> + +#include <string> +#include <vector> + +class CbmSetup; +class FairTask; +class CbmDigitization; +class TTree; + +namespace cbm::sim::digitization +{ + + class Run : public TNamed { + + public: + /** @brief Constructor **/ + Run(); + + + /** @brief Destructor **/ + virtual ~Run(); + + + /** @brief Allow overwriting if output file already exists **/ + void AllowOverwrite() { fOverwrite = true; } + + + /** @brief Run digitization **/ + void Exec(); + + + /** @brief Settings object **/ + const Config& GetConfig() const { return fConfig; } + + + /** @brief Get file name without ending + ** @param file full file name including ending **/ + std::string GetFileName(const TString file); + + + /** @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 files Transport input sources + **/ + void SetTraFiles(const std::vector<std::string> files); + + + /** @brief Set parameter file name + ** @param fileName Parameter file name + **/ + void SetParFile(const char* fileName) { fPar = 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); + + + private: + CbmDigitization fRun{}; + TString fOutput = ""; + std::vector<TString> fTra; + TString fPar = ""; + TString fSetupTag = ""; + CbmSetup* fSetup = nullptr; + bool fOverwrite = false; + + public: + Config fConfig = {}; + + + ClassDef(cbm::sim::digitization::Run, 1); + }; + +} // namespace cbm::sim::digitization + +#endif /* CBMSIM_DIGITIZATION_STEER_RUN_H */