From 55dba5451fa913502662491dee8b6a504b1d09d8 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Wed, 23 Oct 2024 23:48:58 -0400 Subject: [PATCH 1/4] feat: set algorithm log levels from config `yaml` files --- src/iguana/algorithms/Algorithm.cc | 20 +++++++++++++++++++- src/iguana/algorithms/Algorithm.h | 3 +-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/iguana/algorithms/Algorithm.cc b/src/iguana/algorithms/Algorithm.cc index 0f18e2e9..a0b9d10a 100644 --- a/src/iguana/algorithms/Algorithm.cc +++ b/src/iguana/algorithms/Algorithm.cc @@ -108,19 +108,37 @@ namespace iguana { void Algorithm::ParseYAMLConfig() { + + // start YAMLReader instance, if not yet started if(!m_yaml_config) { + // set config files and directories specified by `::SetConfigFile`, `::SetConfigDirectory`, etc. o_user_config_file = GetCachedOption("config_file").value_or(""); o_user_config_dir = GetCachedOption("config_dir").value_or(""); m_log->Debug("Instantiating `YAMLReader`"); m_yaml_config = std::make_unique("config|" + m_name); - m_yaml_config->SetLogLevel(m_log->GetLevel()); + m_yaml_config->SetLogLevel(m_log->GetLevel()); // synchronize log levels m_yaml_config->AddDirectory(o_user_config_dir); m_yaml_config->AddFile(m_default_config_file); m_yaml_config->AddFile(o_user_config_file); } else m_log->Debug("`YAMLReader` already instantiated for this algorithm; using that"); + + // parse the files m_yaml_config->LoadFiles(); + + // if "log" was not set by `SetOption` (i.e., not in `m_option_cache`), check if 'log' is set in + // the YAML node for this algorithm + if(m_option_cache.find("log") == m_option_cache.end()) { + try { + auto log_level = m_yaml_config->GetScalar({m_class_name, "log"}); + m_log->SetLevel(log_level); + m_yaml_config->SetLogLevel(log_level); + } + catch(std::runtime_error const& ex) { + // FIXME: maybe YAMLReader::GetScalar etc. should return std::optional + } + } } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/iguana/algorithms/Algorithm.h b/src/iguana/algorithms/Algorithm.h index 845d49d4..a7152240 100644 --- a/src/iguana/algorithms/Algorithm.h +++ b/src/iguana/algorithms/Algorithm.h @@ -88,8 +88,7 @@ namespace iguana { else m_log->Error("Option '{}' must be a string or a Logger::Level", key); } - else - m_option_cache[key] = val; + m_option_cache[key] = val; return val; } From 233d8c6f8d0aad3d6ee6ad17f7450458ceed242f Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Thu, 24 Oct 2024 00:30:03 -0400 Subject: [PATCH 2/4] refactor: use `std::optional` for `YAMLReader`'s accessors --- src/iguana/algorithms/Algorithm.cc | 48 ++++++++++++++---------------- src/iguana/services/YAMLReader.cc | 42 +++++++++++++------------- src/iguana/services/YAMLReader.h | 17 ++++++----- 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/src/iguana/algorithms/Algorithm.cc b/src/iguana/algorithms/Algorithm.cc index a0b9d10a..343a40c9 100644 --- a/src/iguana/algorithms/Algorithm.cc +++ b/src/iguana/algorithms/Algorithm.cc @@ -16,17 +16,17 @@ namespace iguana { template OPTION_TYPE Algorithm::GetOptionScalar(std::string const& key, YAMLReader::node_path_t node_path) const { - try { - CompleteOptionNodePath(key, node_path); - auto opt = GetCachedOption(key); - auto val = opt ? opt.value() : m_yaml_config->GetScalar(node_path); - PrintOptionValue(key, val); - return val; + CompleteOptionNodePath(key, node_path); + auto opt = GetCachedOption(key); + if(!opt.has_value()) { + opt = m_yaml_config->GetScalar(node_path); } - catch(std::runtime_error const& ex) { - m_log->Error("Failed to `GetOptionScalar` for key '{}'", key); + if(!opt.has_value()) { + m_log->Error("Failed to `GetOptionScalar` for key {:?}", key); throw std::runtime_error("config file parsing issue"); } + PrintOptionValue(key, opt.value()); + return opt.value(); } template int Algorithm::GetOptionScalar(std::string const& key, YAMLReader::node_path_t node_path) const; template double Algorithm::GetOptionScalar(std::string const& key, YAMLReader::node_path_t node_path) const; @@ -37,17 +37,17 @@ namespace iguana { template std::vector Algorithm::GetOptionVector(std::string const& key, YAMLReader::node_path_t node_path) const { - try { - CompleteOptionNodePath(key, node_path); - auto opt = GetCachedOption>(key); - auto val = opt ? opt.value() : m_yaml_config->GetVector(node_path); - PrintOptionValue(key, val); - return val; + CompleteOptionNodePath(key, node_path); + auto opt = GetCachedOption>(key); + if(!opt.has_value()) { + opt = m_yaml_config->GetVector(node_path); } - catch(std::runtime_error const& ex) { - m_log->Error("Failed to `GetOptionVector` for key '{}'", key); + if(!opt.has_value()) { + m_log->Error("Failed to `GetOptionVector` for key {:?}", key); throw std::runtime_error("config file parsing issue"); } + PrintOptionValue(key, opt.value()); + return opt.value(); } template std::vector Algorithm::GetOptionVector(std::string const& key, YAMLReader::node_path_t node_path) const; template std::vector Algorithm::GetOptionVector(std::string const& key, YAMLReader::node_path_t node_path) const; @@ -127,16 +127,14 @@ namespace iguana { // parse the files m_yaml_config->LoadFiles(); - // if "log" was not set by `SetOption` (i.e., not in `m_option_cache`), check if 'log' is set in - // the YAML node for this algorithm + // if "log" was not set by `SetOption` (i.e., not in `m_option_cache`) + // - NB: not using `GetCachedOption` here, since `T` can be a few different types for key=='log' if(m_option_cache.find("log") == m_option_cache.end()) { - try { - auto log_level = m_yaml_config->GetScalar({m_class_name, "log"}); - m_log->SetLevel(log_level); - m_yaml_config->SetLogLevel(log_level); - } - catch(std::runtime_error const& ex) { - // FIXME: maybe YAMLReader::GetScalar etc. should return std::optional + // check if 'log' is set in the YAML node for this algorithm + auto log_level_from_yaml = m_yaml_config->GetScalar({m_class_name, "log"}); + if(log_level_from_yaml) { + m_log->SetLevel(log_level_from_yaml.value()); + m_yaml_config->SetLogLevel(log_level_from_yaml.value()); } } } diff --git a/src/iguana/services/YAMLReader.cc b/src/iguana/services/YAMLReader.cc index 9c232e1e..2f417e76 100644 --- a/src/iguana/services/YAMLReader.cc +++ b/src/iguana/services/YAMLReader.cc @@ -22,7 +22,7 @@ namespace iguana { /////////////////////////////////////////////////////////////////////////////// template - SCALAR YAMLReader::GetScalar(YAML::Node node) + std::optional YAMLReader::GetScalar(YAML::Node node) { if(node.IsDefined() && !node.IsNull()) { try { @@ -35,32 +35,32 @@ namespace iguana { m_log->Error("YAML Misc. Exception: {}", e.what()); } } - throw std::runtime_error("Failed `GetScalar`"); + return std::nullopt; } - template int YAMLReader::GetScalar(YAML::Node node); - template double YAMLReader::GetScalar(YAML::Node node); - template std::string YAMLReader::GetScalar(YAML::Node node); + template std::optional YAMLReader::GetScalar(YAML::Node node); + template std::optional YAMLReader::GetScalar(YAML::Node node); + template std::optional YAMLReader::GetScalar(YAML::Node node); /////////////////////////////////////////////////////////////////////////////// template - SCALAR YAMLReader::GetScalar(node_path_t node_path) + std::optional YAMLReader::GetScalar(node_path_t node_path) { for(auto const& [config, filename] : m_configs) { auto node = FindNode(config, node_path); if(node.IsDefined() && !node.IsNull()) return GetScalar(node); } - throw std::runtime_error("Failed `GetScalar`"); + return std::nullopt; } - template int YAMLReader::GetScalar(node_path_t node_path); - template double YAMLReader::GetScalar(node_path_t node_path); - template std::string YAMLReader::GetScalar(node_path_t node_path); + template std::optional YAMLReader::GetScalar(node_path_t node_path); + template std::optional YAMLReader::GetScalar(node_path_t node_path); + template std::optional YAMLReader::GetScalar(node_path_t node_path); /////////////////////////////////////////////////////////////////////////////// template - std::vector YAMLReader::GetVector(YAML::Node node) + std::optional> YAMLReader::GetVector(YAML::Node node) { if(node.IsDefined() && !node.IsNull() && node.IsSequence()) { try { @@ -76,27 +76,27 @@ namespace iguana { m_log->Error("YAML Misc. Exception: {}", e.what()); } } - throw std::runtime_error("Failed `GetVector`"); + return std::nullopt; } - template std::vector YAMLReader::GetVector(YAML::Node node); - template std::vector YAMLReader::GetVector(YAML::Node node); - template std::vector YAMLReader::GetVector(YAML::Node node); + template std::optional> YAMLReader::GetVector(YAML::Node node); + template std::optional> YAMLReader::GetVector(YAML::Node node); + template std::optional> YAMLReader::GetVector(YAML::Node node); /////////////////////////////////////////////////////////////////////////////// template - std::vector YAMLReader::GetVector(node_path_t node_path) + std::optional> YAMLReader::GetVector(node_path_t node_path) { for(auto const& [config, filename] : m_configs) { auto node = FindNode(config, node_path); if(node.IsDefined() && !node.IsNull()) return GetVector(node); } - throw std::runtime_error("Failed `GetVector`"); + return std::nullopt; } - template std::vector YAMLReader::GetVector(node_path_t node_path); - template std::vector YAMLReader::GetVector(node_path_t node_path); - template std::vector YAMLReader::GetVector(node_path_t node_path); + template std::optional> YAMLReader::GetVector(node_path_t node_path); + template std::optional> YAMLReader::GetVector(node_path_t node_path); + template std::optional> YAMLReader::GetVector(node_path_t node_path); /////////////////////////////////////////////////////////////////////////////// @@ -114,7 +114,7 @@ namespace iguana { auto bounds_node = sub_node[key]; if(bounds_node.IsDefined()) { auto bounds = GetVector(bounds_node); - if(bounds.size() == 2 && bounds[0] <= val && bounds[1] >= val) + if(bounds.value().size() == 2 && bounds.value()[0] <= val && bounds.value()[1] >= val) return sub_node; } } diff --git a/src/iguana/services/YAMLReader.h b/src/iguana/services/YAMLReader.h index 3748a359..9aa73e26 100644 --- a/src/iguana/services/YAMLReader.h +++ b/src/iguana/services/YAMLReader.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -37,27 +38,27 @@ namespace iguana { /// Read a scalar value from a `YAML::Node` /// @param node the `YAML::Node` to read - /// @return the scalar + /// @return the scalar, if found template - SCALAR GetScalar(YAML::Node node); + std::optional GetScalar(YAML::Node node); /// Read a scalar value from a `YAML::Node` path; searches all currently loaded config files. /// @param node_path the `YAML::Node` path - /// @return the scalar + /// @return the scalar, if found template - SCALAR GetScalar(node_path_t node_path); + std::optional GetScalar(node_path_t node_path); /// Read a vector value from a `YAML::Node` /// @param node the `YAML::Node` to read - /// @return the vector + /// @return the vector, if found template - std::vector GetVector(YAML::Node node); + std::optional> GetVector(YAML::Node node); /// Read a vector value from a `YAML::Node` path; searches all currently loaded config files. /// @param node_path the `YAML::Node` path - /// @return the vector + /// @return the vector, if found template - std::vector GetVector(node_path_t node_path); + std::optional> GetVector(node_path_t node_path); /// Create a function to search a `YAML::Node` for a sub-`YAML::Node` such that /// the scalar `val` is within a range specified by `key` From cea810523f8b76d68f15181ffe6068e44b71ccf5 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Thu, 24 Oct 2024 00:37:42 -0400 Subject: [PATCH 3/4] doc: inform users of this feature --- examples/config/my_z_vertex_cuts.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/examples/config/my_z_vertex_cuts.yaml b/examples/config/my_z_vertex_cuts.yaml index 8d5d8e37..96033d6a 100644 --- a/examples/config/my_z_vertex_cuts.yaml +++ b/examples/config/my_z_vertex_cuts.yaml @@ -1,6 +1,13 @@ # Cut values for different run periods clas12::ZVertexFilter: + # NOTE: you can set the log level from the configuration file + log: trace + + # FIXME: with the addition of `log`, this is now + # now a proper YAML file; the list below should be put + # in their own separate node + # default cuts - default: electron_vz: [ -1.5, 1.3 ] From a8131cb3d5cfbaf87db74e2e3548314341e733ec Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Thu, 24 Oct 2024 12:16:58 -0400 Subject: [PATCH 4/4] fix: electron `vz` cut config array should be in its own separate YAML node to allow us to have a `log` node at the top level --- examples/config/my_combined_config_file.yaml | 14 +++++----- .../clas12/ZVertexFilter/Config.yaml | 21 ++++++++------- examples/config/my_z_vertex_cuts.yaml | 27 ++++++++++--------- .../clas12/ZVertexFilter/Algorithm.cc | 2 +- .../clas12/ZVertexFilter/Config.yaml | 22 ++++++++------- 5 files changed, 45 insertions(+), 41 deletions(-) diff --git a/examples/config/my_combined_config_file.yaml b/examples/config/my_combined_config_file.yaml index eb5f5252..8666c074 100644 --- a/examples/config/my_combined_config_file.yaml +++ b/examples/config/my_combined_config_file.yaml @@ -21,17 +21,15 @@ example::ExampleAlgorithm: clas12::ZVertexFilter: - # default cuts - - default: - electron_vz: [ -33.0, 11.0 ] + log: debug # NOTE: you may control algorithm log levels here, like so - #RG-A fall2018 inbending + electron: + - default: + vz: [ -33.0, 11.0 ] - runs: [ 4760, 5419 ] - electron_vz: [ -13.0, 12.0 ] - - #RG-A fall2018 outbending + vz: [ -13.0, 12.0 ] - runs: [ 5420, 5674 ] - electron_vz: [ -18.0, 10.0 ] + vz: [ -18.0, 10.0 ] another::Algorithm: #Cuts below are just examples: diff --git a/examples/config/my_config_directory/algorithms/clas12/ZVertexFilter/Config.yaml b/examples/config/my_config_directory/algorithms/clas12/ZVertexFilter/Config.yaml index 411b1103..ddb51358 100644 --- a/examples/config/my_config_directory/algorithms/clas12/ZVertexFilter/Config.yaml +++ b/examples/config/my_config_directory/algorithms/clas12/ZVertexFilter/Config.yaml @@ -1,14 +1,17 @@ # Cut values for different run periods clas12::ZVertexFilter: - # default cuts - - default: - electron_vz: [ -15.0, 15.0 ] + # scattered electron cuts + electron: - # RG-A fall2018 inbending - - runs: [ 4760, 5419 ] - electron_vz: [ -5.0, 3.0 ] + # default cuts + - default: + vz: [ -15.0, 15.0 ] - # RG-A fall2018 outbending - - runs: [ 5420, 5674 ] - electron_vz: [ -8.0, 7.0 ] + # RG-A fall2018 inbending + - runs: [ 4760, 5419 ] + vz: [ -5.0, 3.0 ] + + # RG-A fall2018 outbending + - runs: [ 5420, 5674 ] + vz: [ -8.0, 7.0 ] diff --git a/examples/config/my_z_vertex_cuts.yaml b/examples/config/my_z_vertex_cuts.yaml index 96033d6a..8b959550 100644 --- a/examples/config/my_z_vertex_cuts.yaml +++ b/examples/config/my_z_vertex_cuts.yaml @@ -1,21 +1,22 @@ # Cut values for different run periods clas12::ZVertexFilter: - # NOTE: you can set the log level from the configuration file + ################################################################################### + # NOTE: for convenience, you can also set the log level from the configuration file log: trace + ################################################################################### - # FIXME: with the addition of `log`, this is now - # now a proper YAML file; the list below should be put - # in their own separate node + # scattered electron cuts + electron: - # default cuts - - default: - electron_vz: [ -1.5, 1.3 ] + # default cuts + - default: + vz: [ -1.5, 1.3 ] - # RG-A fall2018 inbending - - runs: [ 4760, 5419 ] - electron_vz: [ -0.5, 0.5 ] + # RG-A fall2018 inbending + - runs: [ 4760, 5419 ] + vz: [ -0.5, 0.5 ] - # RG-A fall2018 outbending - - runs: [ 5420, 5674 ] - electron_vz: [ -0.8, 0.7 ] + # RG-A fall2018 outbending + - runs: [ 5420, 5674 ] + vz: [ -0.8, 0.7 ] diff --git a/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc b/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc index 16b872b3..f869c229 100644 --- a/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc +++ b/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc @@ -64,7 +64,7 @@ namespace iguana::clas12 { std::lock_guard const lock(m_mutex); // NOTE: be sure to lock successive `ConcurrentParam::Save` calls !!! m_log->Trace("-> calling Reload({}, {})", runnum, key); o_runnum->Save(runnum, key); - o_electron_vz_cuts->Save(GetOptionVector("electron_vz", {GetConfig()->InRange("runs", runnum), "electron_vz"}), key); + o_electron_vz_cuts->Save(GetOptionVector("electron_vz", {"electron", GetConfig()->InRange("runs", runnum), "vz"}), key); } bool ZVertexFilter::Filter(double const zvertex, int const pid, int const status, concurrent_key_t key) const diff --git a/src/iguana/algorithms/clas12/ZVertexFilter/Config.yaml b/src/iguana/algorithms/clas12/ZVertexFilter/Config.yaml index 557f9d33..8a7b1a2e 100644 --- a/src/iguana/algorithms/clas12/ZVertexFilter/Config.yaml +++ b/src/iguana/algorithms/clas12/ZVertexFilter/Config.yaml @@ -1,14 +1,16 @@ -# Cut values for different run periods clas12::ZVertexFilter: - # default cuts - - default: - electron_vz: [ -20.0, 20.0 ] + # scattered electron cuts + electron: - # RG-A fall2018 inbending - - runs: [ 4760, 5419 ] - electron_vz: [ -13.0, 12.0 ] + # default cuts + - default: + vz: [ -20.0, 20.0 ] - # RG-A fall2018 outbending - - runs: [ 5420, 5674 ] - electron_vz: [ -18.0, 10.0 ] + # RG-A fall2018 inbending + - runs: [ 4760, 5419 ] + vz: [ -13.0, 12.0 ] + + # RG-A fall2018 outbending + - runs: [ 5420, 5674 ] + vz: [ -18.0, 10.0 ]