From 999c017d7f0dcf9779e64b50d4640c31cdfc52c7 Mon Sep 17 00:00:00 2001 From: martinunland Date: Wed, 10 Jan 2024 12:46:29 +0100 Subject: [PATCH] changing logger to spdlog --- CMakeLists.txt | 5 + .../Custom_Vitrovex_radioactivity.dat | 10 ++ common/framework/include/OMSim.hh | 1 + common/framework/include/OMSimInputData.hh | 66 ++++--- common/framework/include/OMSimLogger.hh | 164 ++---------------- common/framework/include/OMSimUIinterface.hh | 2 +- common/framework/src/OMSim.cc | 55 ++++-- common/framework/src/OMSimDataFileTypes.cc | 1 + common/framework/src/OMSimLogger.cc | 9 + common/framework/src/OMSimPMTResponse.cc | 1 - .../src/OMSimOpticalModule.cc | 6 +- .../src/OMSimPMTConstruction.cc | 2 +- .../src/abcDetectorComponent.cc | 23 ++- radioactive_decays/CMakeLists.txt | 2 +- .../OMSim_radioactive_decays.cc | 2 + radioactive_decays/include/OMSimDecaysGPS.hh | 17 +- radioactive_decays/src/OMSimDecaysGPS.cc | 57 +++--- .../src/OMSimG4RadioactiveDecay.cc | 3 +- 18 files changed, 203 insertions(+), 223 deletions(-) create mode 100644 common/framework/src/OMSimLogger.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index d0a1a0837c..2599394f7c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,11 @@ set(OPENSSL_ROOT_DIR /usr/lib/x86_64-linux-gnu) set(OPENSSL_LIBRARIES /usr/lib/x86_64-linux-gnu) find_package(OpenSSL REQUIRED) +# For logging with spdlog +find_package(spdlog REQUIRED) +find_package(fmt REQUIRED) # Find fmt library + + # Include OpenSSL's headers in the project include_directories(${OPENSSL_INCLUDE_DIR}) diff --git a/common/data/scintillation/Custom_Vitrovex_radioactivity.dat b/common/data/scintillation/Custom_Vitrovex_radioactivity.dat index 535ff74031..04427f978e 100644 --- a/common/data/scintillation/Custom_Vitrovex_radioactivity.dat +++ b/common/data/scintillation/Custom_Vitrovex_radioactivity.dat @@ -21,6 +21,16 @@ "jValue": 1.28, "jUnit": "kg", "jInvertUnit" : "" + }, + "Ra226_ACTIVITY": { + "jValue": 4.61, + "jUnit": "kg", + "jInvertUnit" : "" + }, + "Ra224_ACTIVITY": { + "jValue": 1.28, + "jUnit": "kg", + "jInvertUnit" : "" } } } diff --git a/common/framework/include/OMSim.hh b/common/framework/include/OMSim.hh index 61583660b5..50c24ec2f2 100644 --- a/common/framework/include/OMSim.hh +++ b/common/framework/include/OMSim.hh @@ -50,6 +50,7 @@ public: void ensureOutputDirectoryExists(const std::string &filepath); void initialiseSimulation(OMSimDetectorConstruction* pDetectorConstruction); void startVisualisation(); + void configureLogger(); //OMSimDetectorConstruction* getDetectorConstruction(); po::options_description mGeneralArgs; diff --git a/common/framework/include/OMSimInputData.hh b/common/framework/include/OMSimInputData.hh index 9a640d2ba5..7e650171b5 100644 --- a/common/framework/include/OMSimInputData.hh +++ b/common/framework/include/OMSimInputData.hh @@ -1,4 +1,4 @@ -/** @file +/** @file * @brief Definition of ParameterTable and InputDataManager. * @ingroup common */ @@ -6,6 +6,7 @@ #ifndef OMSimInputData_h #define OMSimInputData_h 1 +#include "OMSimLogger.hh" #include #include #include @@ -15,39 +16,39 @@ namespace pt = boost::property_tree; /** * @class ParameterTable * @brief A utility class for managing JSON-based data tables. - * + * * The ParameterTable class provides an interface for handling and querying JSON data * represented in the form of a property tree of the boost library. It facilitates the extraction of specific - * parameters from loaded JSON files while also supporting units and scales. The class is - * capable of loading multiple JSON datasets, each uniquely identified by a key, - * and can perform actions such as fetching a value, checking the presence of a key, + * parameters from loaded JSON files while also supporting units and scales. The class is + * capable of loading multiple JSON datasets, each uniquely identified by a key, + * and can perform actions such as fetching a value, checking the presence of a key, * and more. * - * Internally, this class leverages the `boost::property_tree::ptree` to represent and - * manage the JSON data structure, which makes it easy to traverse and fetch desired + * Internally, this class leverages the `boost::property_tree::ptree` to represent and + * manage the JSON data structure, which makes it easy to traverse and fetch desired * parameters. - * + * * Its main use is as base class of InputDataManager, but you may use it as needed (see @ref ExampleUsageParameterTable). - * + * * @ingroup common - * + * * @subsection ExampleUsageParameterTable Minimal example * @code * ParameterTable lTable; // Create an instance of the table * lTable.appendAndReturnTree("path/to/file.json"); // Load a JSON file into the table. The key of this file (in the following "SomeKey") is contained within the file under the variable "jName" * G4double lValue = lTable.getValue("SomeKey", "SomeParameter"); // Fetch a specific value using its key and parameter name - * + * * // Parsing array content from a JSON subtree into a vector using parseKeyContentToVector * std::vector lVector; * pt::ptree lSubtree = lTable.getJSONTree("SomeKey"); // Retrieving the subtree of the file * lTable.parseKeyContentToVector(lVector, lSubtree, "keyOfArray", 1.0, false); // parsing array into vector * @endcode - * - * @warning It's essential to ensure that the provided JSON files are formatted correctly - * and that the keys and parameters being queried exist within the loaded datasets + * + * @warning It's essential to ensure that the provided JSON files are formatted correctly + * and that the keys and parameters being queried exist within the loaded datasets * to avoid runtime errors or unexpected behavior. - * - * @note While the class provides type templating for fetching values, care must be taken + * + * @note While the class provides type templating for fetching values, care must be taken * to ensure the correctness of the types. */ class ParameterTable @@ -65,9 +66,17 @@ public: */ template T getValue(G4String pKey, G4String pParameter) - { - const T lValue = mTable.at(pKey).get(pParameter); - return lValue; + { log_trace("Fetching parameter {} in key {}", pParameter, pKey); + try + { + const T lValue = mTable.at(pKey).get(pParameter); + return lValue; + } + + catch (const std::exception &e) + { + log_error("Fetching parameter {} in key {} from table failed!", pParameter, pKey); + } } G4bool checkIfKeyInTable(G4String pKey); @@ -90,7 +99,7 @@ public: void parseKeyContentToVector(std::vector &pVector, pt::ptree pTree, std::basic_string pKey, G4double pScaling, bool pInverse) - { + { log_trace("Parsing content in key {} to a vector", pKey); for (pt::ptree::value_type &ridx : pTree.get_child( pKey)) { // get array from element with key "pKey" of the json @@ -124,6 +133,7 @@ public: std::basic_string pKey, G4double pScaling, bool pInverse) { + log_trace("Parsing content in key {} to a vector", pKey); for (pt::ptree::value_type &ridx : getJSONTree(pMapKey).get_child( pKey)) { // get array from element with key "pKey" of the json @@ -145,29 +155,29 @@ private: /** * @class InputDataManager * @brief Manages the input data, including parsing and storing material properties. - * + * * @details * The `InputDataManager` class extends the functionalities provided by the `ParameterTable` class. * It's dedicated to the specific needs of managing input data related to materials and optical properties * for the Geant4-based simulation. - * + * * You probably should have a single instance of this class (no need of loading everything twice...probably it also would break things...). * Normally it is loaded in the main DetectorConstruction and passed to the other construction classes. - * - * + * + * * Example usage (see also @ref ExampleUsageParameterTable): - * + * * @code * InputDataManager lManager; * lManager.searchFolders(); // Search for all recognized data files in the predefined directories * G4Material* lWater = manager.getMaterial("CustomWater"); // Retrieve a Geant4 material by name * G4OpticalSurface* lSurface = manager.getOpticalSurface("SomeSurfaceName"); // Retrieve an optical surface by name - * + * * auto lData = manager.loadtxt("path/to/data.txt"); // Load data from a text file into a 2D vector * @endcode - * + * * This class assumes certain conventions in naming and structuring the input files, which aids in automatically identifying and processing them. For example, files with names starting with "RiAbs" are treated as describing refractive and absorption properties. - * + * * @ingroup common */ class InputDataManager : public ParameterTable diff --git a/common/framework/include/OMSimLogger.hh b/common/framework/include/OMSimLogger.hh index 6f8398f62b..e25b834c59 100644 --- a/common/framework/include/OMSimLogger.hh +++ b/common/framework/include/OMSimLogger.hh @@ -1,154 +1,24 @@ -/* -I Took this from a github... but I can't find it right now for giving the credits :( -*/ -#define LOG_LEVEL INFO - #ifndef OMSimLogger_h #define OMSimLogger_h 1 -#include -#include - -/* Default level */ -#ifndef LOG_LEVEL - #define LOG_LEVEL WARNING -#endif - -/* Colour customization */ -#define DEBUG_COLOUR "" -#define INFO_COLOUR "\x1B[36m" -#define NOTICE_COLOUR "\x1B[32;1m" -#define WARNING_COLOUR "\x1B[33m" -#define ERROR_COLOUR "\x1B[31m" -#define CRITICAL_COLOUR "\x1B[41;1m" - -/* Do not change this. */ -#define RESET_COLOUR "\x1B[0m" - -/* Formatting prefs. */ -#define MSG_ENDING "\n" -#define TIME_FORMAT "%T" -#define BORDER "-" - -/* Enabler flags */ -#define DISPLAY_COLOUR 1 -#define DISPLAY_TIME 1 -#define DISPLAY_LEVEL 1 -#define DISPLAY_FUNC 1 -#define DISPLAY_FILE 1 -#define DISPLAY_LINE 1 -#define DISPLAY_BORDER 1 -#define DISPLAY_MESSAGE 1 -#define DISPLAY_ENDING 1 -#define DISPLAY_RESET 1 +#include +#include +#include +#include "spdlog/fmt/fmt.h" -/* Log to screen */ -#define emit_log(colour, level, file, func, line, ...) do { \ - \ - /* notate the time */ \ - time_t raw_time = time(NULL); \ - char time_buffer[80]; \ - strftime(time_buffer, 80, TIME_FORMAT, localtime(&raw_time)); \ - \ - /* enable colour */ \ - printf("%s", DISPLAY_COLOUR ? colour : ""); \ - \ - /* display the time */ \ - printf("%s%s", DISPLAY_TIME ? time_buffer : "", DISPLAY_TIME ? " " : ""); \ - \ - /* display the level */ \ - printf("%10s%s", DISPLAY_LEVEL ? level : "", DISPLAY_LEVEL ? " " : ""); \ - \ - /* display the function doing the logging */ \ - printf("%s%s", DISPLAY_FUNC ? func : "", DISPLAY_FUNC ? " " : ""); \ - \ - /* display the file and/or the line number */ \ - printf( \ - "%s%s%s%.d%s%s", \ - DISPLAY_FUNC && (DISPLAY_FILE || DISPLAY_LINE) ? "(" : "", \ - DISPLAY_FILE ? file : "", \ - DISPLAY_FILE && DISPLAY_LINE ? ":" : "", \ - DISPLAY_LINE ? line : 0, \ - DISPLAY_FUNC && (DISPLAY_FILE || DISPLAY_LINE) ? ") " : "", \ - !DISPLAY_FUNC && (DISPLAY_FILE || DISPLAY_LINE) ? " " : "" \ - ); \ - \ - /* display message border */ \ - printf("%s%s", DISPLAY_BORDER ? BORDER : "", DISPLAY_BORDER ? " " : ""); \ - \ - /* display the callee's message */ \ - if (DISPLAY_MESSAGE) printf(__VA_ARGS__); \ - \ - /* add the message ending (usually '\n') */ \ - printf("%s", DISPLAY_ENDING ? MSG_ENDING : ""); \ - \ - /* reset the colour */ \ - printf("%s", DISPLAY_RESET ? RESET_COLOUR : ""); \ - \ -} while (0) +// Global logger instance +extern std::shared_ptr global_logger; -/* Level enum */ -#define DEBUG 0 -#define INFO 1 -#define NOTICE 2 -#define WARNING 3 -#define ERROR 4 -#define CRITICAL 5 -#define SILENT 6 +// Custom logging function +void customLog(spdlog::level::level_enum log_level, const char* file, int line, const char* func, const std::string& message); -/* DEBUG LOG */ -#define log_debug(...) do { \ - if (LOG_LEVEL == DEBUG) { \ - emit_log( \ - DEBUG_COLOUR, "[DEBUG]", __FILE__, __func__, __LINE__, __VA_ARGS__ \ - ); \ - } \ -} while (0) +#define log_trace(...) customLog(spdlog::level::trace, __FILE__, __LINE__, __func__, fmt::format(__VA_ARGS__)) +#define log_debug(...) customLog(spdlog::level::debug, __FILE__, __LINE__, __func__, fmt::format(__VA_ARGS__)) +#define log_info(...) customLog(spdlog::level::info, __FILE__, __LINE__, __func__, fmt::format(__VA_ARGS__)) +#define log_notice(...) customLog(spdlog::level::info, __FILE__, __LINE__, __func__, fmt::format(__VA_ARGS__)) +#define log_warning(...) customLog(spdlog::level::warn, __FILE__, __LINE__, __func__, fmt::format(__VA_ARGS__)) +#define log_error(...) customLog(spdlog::level::err, __FILE__, __LINE__, __func__, fmt::format(__VA_ARGS__)) +#define log_critical(...) customLog(spdlog::level::critical, __FILE__, __LINE__, __func__, fmt::format(__VA_ARGS__)) -/* INFO LOG */ -#define log_info(...) do { \ - if (LOG_LEVEL <= INFO) { \ - emit_log( \ - INFO_COLOUR, "[INFO]", __FILE__, __func__, __LINE__, __VA_ARGS__ \ - ); \ - } \ -} while (0) - -/* NOTICE LOG */ -#define log_notice(...) do { \ - if (LOG_LEVEL <= NOTICE) { \ - emit_log( \ - NOTICE_COLOUR, "[NOTICE]", __FILE__, __func__, __LINE__, __VA_ARGS__ \ - ); \ - } \ -} while (0) - -/* WARNING LOG */ -#define log_warning(...) do { \ - if (LOG_LEVEL <= WARNING) { \ - emit_log( \ - WARNING_COLOUR, "[WARNING]", __FILE__, __func__, __LINE__, __VA_ARGS__ \ - ); \ - } \ -} while (0) - -/* ERROR LOG */ -#define log_error(...) do { \ - if (LOG_LEVEL <= ERROR) { \ - emit_log( \ - ERROR_COLOUR, "[ERROR]", __FILE__, __func__, __LINE__, __VA_ARGS__ \ - ); \ - } \ -} while (0) - -/* CRITICAL LOG */ -#define log_critical(...) do { \ - if (LOG_LEVEL <= CRITICAL) { \ - emit_log( \ - CRITICAL_COLOUR, "[CRITICAL]", __FILE__, __func__, __LINE__, __VA_ARGS__\ - ); \ - } \ -} while (0) - -#endif -// +#endif +// \ No newline at end of file diff --git a/common/framework/include/OMSimUIinterface.hh b/common/framework/include/OMSimUIinterface.hh index 68cba6565c..c1ae0614ff 100644 --- a/common/framework/include/OMSimUIinterface.hh +++ b/common/framework/include/OMSimUIinterface.hh @@ -45,7 +45,7 @@ public: std::stringstream stream; stream << command; appendToStream(stream, args...); - log_debug(stream.str().c_str()); + log_trace(stream.str().c_str()); UI->ApplyCommand(stream.str()); } diff --git a/common/framework/src/OMSim.cc b/common/framework/src/OMSim.cc index 42ee3b6ab0..29ef408ebc 100644 --- a/common/framework/src/OMSim.cc +++ b/common/framework/src/OMSim.cc @@ -9,9 +9,11 @@ */ #include "OMSim.hh" +#include "OMSimLogger.hh" #include namespace po = boost::program_options; +extern std::shared_ptr global_logger; /** * This constructor initializes the Geant4 run manager, visualization manager, @@ -25,6 +27,7 @@ OMSim::OMSim() : mGeneralArgs("General options") mNavigator = new G4Navigator(); mGeneralArgs.add_options()("help", "produce help message") + ("log_level", po::value()->default_value("info"), "Granularity of logger, defaults to info [trace, debug, info, warn, error, critical, off]") ("output_file,o", po::value()->default_value("output"), "filename for output") ("numevents,n", po::value()->default_value(0), "number of events") ("visual,v", po::bool_switch()->default_value(false), "shows visualization of module after run") @@ -44,10 +47,40 @@ OMSim::OMSim() : mGeneralArgs("General options") ("pmt_model", po::value()->default_value(0), "DEPRECATED. R15458 (mDOM) = 0, R7081 (DOM) = 1, 4inch (LOM) = 2, R5912_20_100 (D-Egg)= 3"); } +spdlog::level::level_enum getLogLevelFromString(const std::string &pLevelString) +{ + static const std::unordered_map lLevelMap = { + {"trace", spdlog::level::trace}, + {"debug", spdlog::level::debug}, + {"info", spdlog::level::info}, + {"warn", spdlog::level::warn}, + {"error", spdlog::level::err}, + {"critical", spdlog::level::critical}, + {"off", spdlog::level::off}}; + auto it = lLevelMap.find(pLevelString); + if (it != lLevelMap.end()) + { + return it->second; + } + // Default log level if string is not recognized + return spdlog::level::info; +} - /** - * @brief UIEx session is started for visualisation. - */ +void OMSim::configureLogger() +{ + G4cout << ":::::::::::::::::::" << G4endl; + global_logger = spdlog::stdout_color_mt("console"); + std::string lLogLevel = OMSimCommandArgsTable::getInstance().get("log_level"); + global_logger->set_level(getLogLevelFromString(lLogLevel)); // Set the desired log level + global_logger->set_pattern("%^[%Y-%m-%d %H:%M:%S.%e][%l][%s:%#]%$ %v"); + spdlog::set_default_logger(global_logger); + log_trace("Logger configured to level {}", lLogLevel); +} + + +/** + * @brief UIEx session is started for visualisation. + */ void OMSim::startVisualisation() { OMSimUIinterface &lUIinterface = OMSimUIinterface::getInstance(); @@ -57,13 +90,13 @@ void OMSim::startVisualisation() UIEx->SessionStart(); delete UIEx; } - /** - * @brief Ensure that the output directory for the simulation results exists. - * - * If the output directory does not exist, this function will create it. - * - * @param pFilePath The path to the output directory. - */ +/** + * @brief Ensure that the output directory for the simulation results exists. + * + * If the output directory does not exist, this function will create it. + * + * @param pFilePath The path to the output directory. + */ void OMSim::ensureOutputDirectoryExists(const std::string &pFilePath) { std::filesystem::path full_path(pFilePath); @@ -88,6 +121,8 @@ OMSimDetectorConstruction* OMSim::getDetectorConstruction() */ void OMSim::initialiseSimulation(OMSimDetectorConstruction* pDetectorConstruction) { + configureLogger(); + OMSimCommandArgsTable &lArgs = OMSimCommandArgsTable::getInstance(); ensureOutputDirectoryExists(lArgs.get("output_file")); diff --git a/common/framework/src/OMSimDataFileTypes.cc b/common/framework/src/OMSimDataFileTypes.cc index dcff81c80e..4856e7ecd9 100644 --- a/common/framework/src/OMSimDataFileTypes.cc +++ b/common/framework/src/OMSimDataFileTypes.cc @@ -628,6 +628,7 @@ void CustomProperties::extractConstProperties() G4String lKey = item.first; G4double lValue = mFileData->getValueWithUnit(mJsonTree.get("jName"), "ConstProperties." + lKey); mMPT->AddConstProperty(lKey, lValue, true); + G4String mssg = "Added " + lKey + " constant property to " + mJsonTree.get("jMaterialName"); log_debug(mssg); } diff --git a/common/framework/src/OMSimLogger.cc b/common/framework/src/OMSimLogger.cc new file mode 100644 index 0000000000..dcad3ad344 --- /dev/null +++ b/common/framework/src/OMSimLogger.cc @@ -0,0 +1,9 @@ +#include "OMSimLogger.hh" + + +// Definition of the customLog function +void customLog(spdlog::level::level_enum log_level, const char* file, int line, const char* func, const std::string& message) { + if (global_logger && global_logger->should_log(log_level)) { + global_logger->log(spdlog::source_loc{file, line, func}, log_level, message); + } +} diff --git a/common/framework/src/OMSimPMTResponse.cc b/common/framework/src/OMSimPMTResponse.cc index bb5b43b242..3a9c5b2d1a 100644 --- a/common/framework/src/OMSimPMTResponse.cc +++ b/common/framework/src/OMSimPMTResponse.cc @@ -317,7 +317,6 @@ mDOMPMTResponse::mDOMPMTResponse() for (const auto &lKey : getScannedWavelengths()) { - G4cout << lKey << G4endl; std::string lWv = std::to_string((int)(lKey / nm)); mGainG2Dmap[lKey] = createHistogramFromData(path + "Gain_PE_" + lWv + ".dat", ("Gain_PE_" + lWv).c_str()); mGainResolutionG2Dmap[lKey] = createHistogramFromData(path + "SPEresolution_" + lWv + ".dat", ("SPEresolution_" + lWv).c_str()); diff --git a/common/geometry_construction/src/OMSimOpticalModule.cc b/common/geometry_construction/src/OMSimOpticalModule.cc index 0e3565459a..f62b5c8066 100644 --- a/common/geometry_construction/src/OMSimOpticalModule.cc +++ b/common/geometry_construction/src/OMSimOpticalModule.cc @@ -8,16 +8,18 @@ OMSimOpticalModule::OMSimOpticalModule() } OMSimOpticalModule::~OMSimOpticalModule() -{ +{ if (mPMTManager != nullptr) { delete mPMTManager; mPMTManager = nullptr; } + } OMSimPMTConstruction *OMSimOpticalModule::getPMTmanager() -{ +{ + log_trace("Getting PMT instance used in optical module instance"); return mPMTManager; } diff --git a/common/geometry_construction/src/OMSimPMTConstruction.cc b/common/geometry_construction/src/OMSimPMTConstruction.cc index 6345412861..85f8d9c90f 100644 --- a/common/geometry_construction/src/OMSimPMTConstruction.cc +++ b/common/geometry_construction/src/OMSimPMTConstruction.cc @@ -537,7 +537,7 @@ void OMSimPMTConstruction::includeHAcoating() } G4double OMSimPMTConstruction::getPMTGlassWeight() -{ +{ log_trace("Getting PMT bulb weight"); try { return mData->getValue(mSelectedPMT, "jBulbWeight"); diff --git a/common/geometry_construction/src/abcDetectorComponent.cc b/common/geometry_construction/src/abcDetectorComponent.cc index 33b7a4e6a0..8c5a5ce49e 100644 --- a/common/geometry_construction/src/abcDetectorComponent.cc +++ b/common/geometry_construction/src/abcDetectorComponent.cc @@ -23,8 +23,7 @@ void abcDetectorComponent::appendComponent(G4VSolid *pSolid, G4LogicalVolume *pL { if (checkIfExists(pName)) { - G4String mssg = pName + " already exists in the Components map. I will expand with a suffix, but this is bad!"; - log_critical(mssg); + log_critical("{} already exists in the Components map. I will expand with a suffix, but this is bad!", pName); pName = pName + "_" + std::to_string(mComponents.size()); } mComponents[pName] = { @@ -45,6 +44,7 @@ G4bool abcDetectorComponent::checkIfExists(G4String pName) { if (mComponents.find(pName) == mComponents.end()) { + log_trace("Component {} is not in component dictionary", pName); return false; } return true; @@ -55,14 +55,14 @@ G4bool abcDetectorComponent::checkIfExists(G4String pName) */ void abcDetectorComponent::deleteComponent(G4String pName) { + log_trace("Deleting component {} from component dictionary", pName); if (checkIfExists(pName)) { mComponents.erase(pName); } else { - G4String mssg = "You are trying to delete " + pName + " from a Components dictionary, but it does not exist."; - log_critical(mssg); + log_critical("You are trying to delete {} from a Components dictionary, but it does not exist.", pName); } } /** @@ -72,8 +72,16 @@ void abcDetectorComponent::deleteComponent(G4String pName) */ abcDetectorComponent::Component abcDetectorComponent::getComponent(G4String pName) { - checkIfExists(pName); - return mComponents.at(pName); // It will always try to get the component, even if it does not exist, since we want to stop the program if it happens. + log_trace("Getting component {} from component dictionary", pName); + if (checkIfExists(pName)) + { + return mComponents.at(pName); + } + else + { + log_error("Getting component {} failed!, not found in component dictionary!", pName); + return mComponents.at(pName); // It will always try to get the component, even if it does not exist, since we want to stop the program if it happens. + } } /** @@ -124,8 +132,7 @@ void abcDetectorComponent::placeIt(G4Transform3D pTrans, G4LogicalVolume *&pMoth G4Transform3D lTrans; for (auto const &[key, Component] : mComponents) { - G4String mssg = "Placing " + key + " in " + pMother->GetName() + "."; - log_debug(mssg); + log_debug("Placing {} in {}.", key, pMother->GetName()); lTrans = getNewPosition(pTrans.getTranslation(), pTrans.getRotation(), Component.Position, Component.Rotation); mLastPhysicals[key] = new G4PVPlacement(lTrans, Component.VLogical, Component.Name + pNameExtension, pMother, false, 0, mCheckOverlaps); } diff --git a/radioactive_decays/CMakeLists.txt b/radioactive_decays/CMakeLists.txt index 65cab92f25..0d5342751a 100755 --- a/radioactive_decays/CMakeLists.txt +++ b/radioactive_decays/CMakeLists.txt @@ -12,4 +12,4 @@ target_include_directories(OMSim_radioactive_decays PUBLIC ) # Link the libraries -target_link_libraries(OMSim_radioactive_decays ${Geant4_LIBRARIES} ${ROOT_LIBRARIES} ${OPENSSL_LIBRARIES} /usr/lib/x86_64-linux-gnu/libargtable2.so.0 Boost::program_options $<$:ws2_32>) +target_link_libraries(OMSim_radioactive_decays ${Geant4_LIBRARIES} ${ROOT_LIBRARIES} ${OPENSSL_LIBRARIES} /usr/lib/x86_64-linux-gnu/libargtable2.so.0 Boost::program_options spdlog::spdlog fmt::fmt $<$:ws2_32>) diff --git a/radioactive_decays/OMSim_radioactive_decays.cc b/radioactive_decays/OMSim_radioactive_decays.cc index 48b450f00b..f5c4927fd7 100755 --- a/radioactive_decays/OMSim_radioactive_decays.cc +++ b/radioactive_decays/OMSim_radioactive_decays.cc @@ -12,6 +12,8 @@ #include "OMSimDecaysAnalysis.hh" #include "OMSimRadDecaysDetector.hh" +std::shared_ptr global_logger; + namespace po = boost::program_options; /** diff --git a/radioactive_decays/include/OMSimDecaysGPS.hh b/radioactive_decays/include/OMSimDecaysGPS.hh index ab1ad26408..3f7523dd99 100644 --- a/radioactive_decays/include/OMSimDecaysGPS.hh +++ b/radioactive_decays/include/OMSimDecaysGPS.hh @@ -35,14 +35,27 @@ public: G4String getDecayTerminationNuclide(); private: - // Define a map that maps isotopes to their commands + // Define a map that maps isotopes to their GPS commands std::map mIsotopeCommands = { {"U238", "/gps/ion 92 238 0"}, {"U235", "/gps/ion 92 235 0"}, + {"Ra226", "/gps/ion 88 226 0"}, + {"Ra224", "/gps/ion 88 224 0"}, {"Th232", "/gps/ion 90 232 0"}, {"K40", "/gps/ion 19 40 0"}}; + + // Define a map that maps isotopes to their termination isotope (Ra is gas state and chains are often not in secular equilibrium) + // Ra224 with a lifetime of ~4d breaks equilibrium far less than Ra226, with half life ~1600y, so activity of Th232 and Ra224 will probably be very similar + std::map mTerminationIsotopes = { + {"U238", "Ra226"}, + {"Th232", "Ra224"}, + {"Ra226", "none"}, + {"Ra224", "none"}, + {"U235", "none"}, + {"K40", "none"}}; + void generalGPS(); - void configureIsotopeGPS(G4String Isotope, G4String location, G4int optParam = -999); + void configureIsotopeGPS(G4String Isotope, G4String location); std::map calculateNumberOfDecays(G4MaterialPropertiesTable *pMPT, G4double pTimeWindow, G4double pMass); OMSimOpticalModule *mOM; G4double mProductionRadius; diff --git a/radioactive_decays/src/OMSimDecaysGPS.cc b/radioactive_decays/src/OMSimDecaysGPS.cc index c05ce065c0..3b6f26226e 100644 --- a/radioactive_decays/src/OMSimDecaysGPS.cc +++ b/radioactive_decays/src/OMSimDecaysGPS.cc @@ -1,4 +1,5 @@ #include "OMSimDecaysGPS.hh" +#include "OMSimLogger.hh" #include "OMSimUIinterface.hh" #include #include @@ -17,6 +18,7 @@ G4String OMSimDecaysGPS::getDecayTerminationNuclide() */ void OMSimDecaysGPS::generalGPS() { + log_debug("Configuring general GPS"); OMSimUIinterface &lUIinterface = OMSimUIinterface::getInstance(); OMSimCommandArgsTable &lArgs = OMSimCommandArgsTable::getInstance(); @@ -36,8 +38,17 @@ void OMSimDecaysGPS::generalGPS() lUIinterface.applyCommand("/gps/pos/radius ", mProductionRadius, " mm"); lUIinterface.applyCommand("/gps/ang/type iso"); - if(lArgs.get("scint_off")) lUIinterface.applyCommand("/process/inactivate Scintillation"); - if(lArgs.get("cherenkov_off")) lUIinterface.applyCommand("/process/inactivate Cerenkov"); + if (lArgs.get("scint_off")) + { + log_debug("Inactivating scintillation process"); + lUIinterface.applyCommand("/process/inactivate Scintillation"); + } + + if (lArgs.get("cherenkov_off")) + { + log_debug("Inactivating Cerenkov process"); + lUIinterface.applyCommand("/process/inactivate Cerenkov"); + } } /** @@ -47,29 +58,21 @@ void OMSimDecaysGPS::generalGPS() * * @param Isotope The isotope which is going to be produced. * @param pVolumeName The volume name where the isotope decays. - * @param optParam An optional parameter related to the location. For "PMT", use e.g. the PMT number. */ -void OMSimDecaysGPS::configureIsotopeGPS(G4String Isotope, G4String pVolumeName, G4int optParam) +void OMSimDecaysGPS::configureIsotopeGPS(G4String Isotope, G4String pVolumeName) { + log_debug("Configuring GPS for isotope {} in volume {}", Isotope, pVolumeName); OMSimUIinterface &lUIinterface = OMSimUIinterface::getInstance(); + generalGPS(); if (mIsotopeCommands.find(Isotope) != mIsotopeCommands.end()) { lUIinterface.applyCommand(mIsotopeCommands[Isotope]); } - - if(optParam != -999) - { - lUIinterface.applyCommand("/gps/pos/confine " + pVolumeName, optParam); - } - else - { - lUIinterface.applyCommand("/gps/pos/confine " + pVolumeName); - } + lUIinterface.applyCommand("/gps/pos/confine " + pVolumeName); } - /** * @brief Calculates the number of decays for isotopes. * @param pMPT Pointer to the material properties table. @@ -80,35 +83,44 @@ void OMSimDecaysGPS::configureIsotopeGPS(G4String Isotope, G4String pVolumeName, std::map OMSimDecaysGPS::calculateNumberOfDecays(G4MaterialPropertiesTable *pMPT, G4double pTimeWindow, G4double pMass) { std::map mNumberDecays; + log_debug("Calculating number of decays from material isotope activity..."); for (auto &pair : mIsotopeCommands) { G4String lIsotope = pair.first; G4double lActivity = pMPT->GetConstProperty(lIsotope + "_ACTIVITY"); mNumberDecays[pair.first] = G4int(G4Poisson(lActivity * pTimeWindow * pMass)); + G4String lLog = "Number of decays for Isotope " + lIsotope + " is " + std::to_string(mNumberDecays[pair.first]); + log_trace("Number of calculated decays for Isotope {} is {}", lIsotope, mNumberDecays[pair.first]); } return mNumberDecays; } - - /** * @brief Simulates the decays in the pressure vessel of the optical module. * @param pTimeWindow The livetime that should be simulated. */ void OMSimDecaysGPS::simulateDecaysInPressureVessel(G4double pTimeWindow) { + log_debug("Simulating radioactive decays in pressure vessel in a time window of {} seconds", pTimeWindow); + OMSimUIinterface &lUIinterface = OMSimUIinterface::getInstance(); G4double lMass = mOM->getPressureVesselWeight(); - G4LogicalVolume *lPVVolume = mOM->getComponent("PressureVessel").VLogical; + G4String lPressureVesselName = "PressureVessel_" + std::to_string(mOM->mIndex); + + G4LogicalVolume *lPVVolume = mOM->getComponent(lPressureVesselName).VLogical; G4MaterialPropertiesTable *lMPT = lPVVolume->GetMaterial()->GetMaterialPropertiesTable(); + std::map lNumberDecays = calculateNumberOfDecays(lMPT, pTimeWindow, lMass); for (auto &pair : lNumberDecays) { G4String lIsotope = pair.first; G4int lNrDecays = pair.second; - configureIsotopeGPS(lIsotope, "PressureVessel"); + mNuclideStopName = mTerminationIsotopes[pair.first]; + configureIsotopeGPS(lIsotope, lPressureVesselName); + + log_debug("Simulating {} decays of {} in pressure vessel", lNrDecays, lIsotope); lUIinterface.runBeamOn(lNrDecays); } } @@ -119,8 +131,8 @@ void OMSimDecaysGPS::simulateDecaysInPressureVessel(G4double pTimeWindow) */ void OMSimDecaysGPS::simulateDecaysInPMTs(G4double pTimeWindow) { + log_debug("Simulating radioactive decays in glass of PMTs in a time window of {} seconds", pTimeWindow); OMSimUIinterface &lUIinterface = OMSimUIinterface::getInstance(); - G4double lMass = mOM->getPMTmanager()->getPMTGlassWeight(); G4LogicalVolume *lPVVolume = mOM->getPMTmanager()->getLogicalVolume(); G4MaterialPropertiesTable *lMPT = lPVVolume->GetMaterial()->GetMaterialPropertiesTable(); @@ -133,9 +145,12 @@ void OMSimDecaysGPS::simulateDecaysInPMTs(G4double pTimeWindow) { G4String lIsotope = pair.first; G4int lNrDecays = pair.second; - configureIsotopeGPS(lIsotope, "PMT", pmt); + mNuclideStopName = mTerminationIsotopes[pair.first]; + + configureIsotopeGPS(lIsotope, "PMT"+std::to_string(pmt)); + + log_debug("Simulating {} decays of {} in PMT {}", lNrDecays, lIsotope, pmt); lUIinterface.runBeamOn(lNrDecays); } } - } diff --git a/radioactive_decays/src/OMSimG4RadioactiveDecay.cc b/radioactive_decays/src/OMSimG4RadioactiveDecay.cc index 8ec514f2c5..6f9f7be679 100644 --- a/radioactive_decays/src/OMSimG4RadioactiveDecay.cc +++ b/radioactive_decays/src/OMSimG4RadioactiveDecay.cc @@ -37,6 +37,7 @@ //////////////////////////////////////////////////////////////////////////////// #include "OMSimDecaysAnalysis.hh" +#include "OMSimLogger.hh" #include "OMSimCommandArgsTable.hh" #include "OMSimDecaysGPS.hh" @@ -1079,10 +1080,10 @@ G4RadioactiveDecay::DecayIt(const G4Track &theTrack, const G4Step &) #endif return TerminateDecay(); } - // Check if the current nucleus is the target stop nucleus if (theParticleDef->GetParticleName() == OMSimDecaysGPS::getInstance().getDecayTerminationNuclide()) { + log_trace("Stoping decay chain, as current isotope {} is the set termination isotope", theParticleDef->GetParticleName()); return TerminateDecay(); }