From d430133d9a6d63379ce7abb946465e8303d37e16 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Thu, 22 Jan 2026 12:18:10 -0500 Subject: [PATCH 01/10] fix!: standardize config param names for `Algorithm::SetOption` --- src/iguana/algorithms/Algorithm.cc | 23 ++++----- src/iguana/algorithms/Algorithm.h | 20 ++++---- .../clas12/EventBuilderFilter/Algorithm.cc | 2 +- .../MatchParticleProximity/Algorithm.cc | 4 +- .../clas12/PhotonGBTFilter/Algorithm.cc | 4 +- .../clas12/SectorFinder/Algorithm.cc | 6 +-- .../clas12/ZVertexFilter/Algorithm.cc | 2 +- .../rga/FiducialFilterPass1/Algorithm.cc | 8 ++-- .../rga/FiducialFilterPass2/Algorithm.cc | 6 +-- .../example/ExampleAlgorithm/Algorithm.cc | 4 +- .../physics/DihadronKinematics/Algorithm.cc | 6 +-- .../physics/InclusiveKinematics/Algorithm.cc | 14 +++--- .../SingleHadronKinematics/Algorithm.cc | 2 +- src/iguana/services/Deprecated.cc | 29 +++++++++++ src/iguana/services/Deprecated.h | 12 +++++ src/iguana/services/YAMLReader.cc | 18 +++++++ src/iguana/services/YAMLReader.h | 21 +++++--- src/iguana/services/meson.build | 2 + src/iguana/tests/include/TestConfig.h | 48 +++++++++---------- 19 files changed, 144 insertions(+), 87 deletions(-) create mode 100644 src/iguana/services/Deprecated.cc create mode 100644 src/iguana/services/Deprecated.h diff --git a/src/iguana/algorithms/Algorithm.cc b/src/iguana/algorithms/Algorithm.cc index 3eb3276e..c9ba9d84 100644 --- a/src/iguana/algorithms/Algorithm.cc +++ b/src/iguana/algorithms/Algorithm.cc @@ -31,30 +31,31 @@ namespace iguana { /////////////////////////////////////////////////////////////////////////////// template - OPTION_TYPE Algorithm::GetOptionScalar(std::string const& key, YAMLReader::node_path_t node_path) const + OPTION_TYPE Algorithm::GetOptionScalar(YAMLReader::node_path_t node_path) const { - CompleteOptionNodePath(key, node_path); + node_path.push_front(m_class_name); + auto key = YAMLReader::NodePath2String(node_path); auto opt = GetCachedOption(key); if(!opt.has_value()) { opt = m_yaml_config->GetScalar(node_path); } if(!opt.has_value()) { - m_log->Error("Failed to `GetOptionScalar` for key {:?}", key); + m_log->Error("Failed to `GetOptionScalar` for parameter {:?}", 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; - template std::string Algorithm::GetOptionScalar(std::string const& key, YAMLReader::node_path_t node_path) const; + template int Algorithm::GetOptionScalar(YAMLReader::node_path_t node_path) const; + template double Algorithm::GetOptionScalar(YAMLReader::node_path_t node_path) const; + template std::string Algorithm::GetOptionScalar(YAMLReader::node_path_t node_path) const; /////////////////////////////////////////////////////////////////////////////// template std::vector Algorithm::GetOptionVector(std::string const& key, YAMLReader::node_path_t node_path) const { - CompleteOptionNodePath(key, node_path); + node_path.push_front(m_class_name); auto opt = GetCachedOption>(key); if(!opt.has_value()) { opt = m_yaml_config->GetVector(node_path); @@ -430,12 +431,4 @@ namespace iguana { throw std::runtime_error("algorithm has been renamed"); } - /////////////////////////////////////////////////////////////////////////////// - - void Algorithm::CompleteOptionNodePath(std::string const& key, YAMLReader::node_path_t& node_path) const - { - if(node_path.empty()) - node_path.push_front(key); - node_path.push_front(m_class_name); - } } diff --git a/src/iguana/algorithms/Algorithm.h b/src/iguana/algorithms/Algorithm.h index f48049a1..74c8d2cf 100644 --- a/src/iguana/algorithms/Algorithm.h +++ b/src/iguana/algorithms/Algorithm.h @@ -8,6 +8,7 @@ #include "AlgorithmBoilerplate.h" #include "iguana/bankdefs/BankDefs.h" +#include "iguana/services/Deprecated.h" #include "iguana/services/RCDBReader.h" #include "iguana/services/YAMLReader.h" #include @@ -119,27 +120,27 @@ namespace iguana { else m_log->Error("Option '{}' must be a string or a Logger::Level", key); } + // make sure the key hasn't been renamed or deprecated + iguana::deprecated::CheckSetOptionKey(m_class_name, key); + // add it to the cache m_option_cache[key] = val; return val; } /// Get the value of a scalar option - /// @param key the unique key name of this option, for caching; if empty, the option will not be cached - /// @param node_path the `YAML::Node` identifier path to search for this option in the config files; if empty, it will just use `key` + /// @param node_path the `YAML::Node` identifier path to search for this option in the config files /// @returns the scalar option template - OPTION_TYPE GetOptionScalar(std::string const& key, YAMLReader::node_path_t node_path = {}) const; + OPTION_TYPE GetOptionScalar(YAMLReader::node_path_t node_path = {}) const; /// Get the value of a vector option - /// @param key the unique key name of this option, for caching; if empty, the option will not be cached - /// @param node_path the `YAML::Node` identifier path to search for this option in the config files; if empty, it will just use `key` + /// @param node_path the `YAML::Node` identifier path to search for this option in the config files /// @returns the vector option template std::vector GetOptionVector(std::string const& key, YAMLReader::node_path_t node_path = {}) const; /// Get the value of a vector option, and convert it to `std::set` - /// @param key the unique key name of this option - /// @param node_path the `YAML::Node` identifier path to search for this option in the config files; if empty, it will just use `key` + /// @param node_path the `YAML::Node` identifier path to search for this option in the config files /// @returns the vector option converted to `std::set` template std::set GetOptionSet(std::string const& key, YAMLReader::node_path_t node_path = {}) const; @@ -262,11 +263,6 @@ namespace iguana { private: // methods - /// Prepend `node_path` with the full algorithm name. If `node_path` is empty, set it to `{key}`. - /// @param key the key name for this option - /// @param node_path the `YAMLReader::node_path_t` to prepend - void CompleteOptionNodePath(std::string const& key, YAMLReader::node_path_t& node_path) const; - // PrintOptionValue: overloaded for different value types void PrintOptionValue(std::string const& key, int const& val, Logger::Level const level = Logger::debug, std::string_view prefix = "OPTION") const; void PrintOptionValue(std::string const& key, double const& val, Logger::Level const level = Logger::debug, std::string_view prefix = "OPTION") const; diff --git a/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.cc b/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.cc index 2ade4e27..9a529d59 100644 --- a/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.cc +++ b/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.cc @@ -9,7 +9,7 @@ namespace iguana::clas12 { // define options, their default values, and cache them ParseYAMLConfig(); - o_particle_bank = GetOptionScalar("particle_bank"); + o_particle_bank = GetOptionScalar({"particle_bank"}); o_pids = GetOptionSet("pids"); // get expected bank indices diff --git a/src/iguana/algorithms/clas12/MatchParticleProximity/Algorithm.cc b/src/iguana/algorithms/clas12/MatchParticleProximity/Algorithm.cc index 7ada847d..615476e0 100644 --- a/src/iguana/algorithms/clas12/MatchParticleProximity/Algorithm.cc +++ b/src/iguana/algorithms/clas12/MatchParticleProximity/Algorithm.cc @@ -9,8 +9,8 @@ namespace iguana::clas12 { { // parse config file ParseYAMLConfig(); - o_bank_a = GetOptionScalar("bank_a"); - o_bank_b = GetOptionScalar("bank_b"); + o_bank_a = GetOptionScalar({"bank_a"}); + o_bank_b = GetOptionScalar({"bank_b"}); // banklist indices b_bank_a = GetBankIndex(banks, o_bank_a); diff --git a/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.cc b/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.cc index 0af25cd7..2fc572d1 100644 --- a/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.cc +++ b/src/iguana/algorithms/clas12/PhotonGBTFilter/Algorithm.cc @@ -39,8 +39,8 @@ namespace iguana::clas12 { b_calorimeter = GetBankIndex(banks, "REC::Calorimeter"); b_config = GetBankIndex(banks, "RUN::config"); - o_pass = GetOptionScalar("pass"); - o_threshold = GetOptionScalar("threshold"); + o_pass = GetOptionScalar({"pass"}); + o_threshold = GetOptionScalar({"threshold"}); } bool PhotonGBTFilter::Run(hipo::banklist& banks) const diff --git a/src/iguana/algorithms/clas12/SectorFinder/Algorithm.cc b/src/iguana/algorithms/clas12/SectorFinder/Algorithm.cc index 3b6be04e..37144984 100644 --- a/src/iguana/algorithms/clas12/SectorFinder/Algorithm.cc +++ b/src/iguana/algorithms/clas12/SectorFinder/Algorithm.cc @@ -9,13 +9,13 @@ namespace iguana::clas12 { // define options, their default values, and cache them ParseYAMLConfig(); - o_bankname_charged = GetOptionScalar("bank_charged"); + o_bankname_charged = GetOptionScalar({"bank_charged"}); try { - o_bankname_neutral = GetOptionScalar("bank_neutral"); + o_bankname_neutral = GetOptionScalar({"bank_neutral"}); } catch(std::runtime_error const& ex) { m_log->Warn("searching instead for configuration parameter named 'bank_uncharged'..."); - o_bankname_neutral = GetOptionScalar("bank_uncharged"); + o_bankname_neutral = GetOptionScalar({"bank_uncharged"}); m_log->Warn("...found 'bank_uncharged' and using it; note that 'bank_uncharged' has been renamed to 'bank_neutral', please update your configuration"); } diff --git a/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc b/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc index ef147b49..0fcab0a7 100644 --- a/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc +++ b/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc @@ -10,7 +10,7 @@ namespace iguana::clas12 { // get configuration ParseYAMLConfig(); - o_particle_bank = GetOptionScalar("particle_bank"); + o_particle_bank = GetOptionScalar({"particle_bank"}); o_runnum = ConcurrentParamFactory::Create(); o_electron_vz_cuts = ConcurrentParamFactory::Create>(); diff --git a/src/iguana/algorithms/clas12/rga/FiducialFilterPass1/Algorithm.cc b/src/iguana/algorithms/clas12/rga/FiducialFilterPass1/Algorithm.cc index f33970d5..f4948b70 100644 --- a/src/iguana/algorithms/clas12/rga/FiducialFilterPass1/Algorithm.cc +++ b/src/iguana/algorithms/clas12/rga/FiducialFilterPass1/Algorithm.cc @@ -8,10 +8,10 @@ namespace iguana::clas12::rga { void FiducialFilterPass1::Start(hipo::banklist& banks) { ParseYAMLConfig(); - o_pcal_electron_cut_level = ParseCutLevel(GetOptionScalar("pcal_electron_cut_level")); - o_pcal_photon_cut_level = ParseCutLevel(GetOptionScalar("pcal_photon_cut_level")); - o_enable_pcal_cuts = GetOptionScalar("enable_pcal_cuts") == 1; - o_enable_dc_cuts = GetOptionScalar("enable_dc_cuts") == 1; + o_pcal_electron_cut_level = ParseCutLevel(GetOptionScalar({"pcal_electron_cut_level"})); + o_pcal_photon_cut_level = ParseCutLevel(GetOptionScalar({"pcal_photon_cut_level"})); + o_enable_pcal_cuts = GetOptionScalar({"enable_pcal_cuts"}) == 1; + o_enable_dc_cuts = GetOptionScalar({"enable_dc_cuts"}) == 1; b_particle = GetBankIndex(banks, "REC::Particle"); b_config = GetBankIndex(banks, "RUN::config"); diff --git a/src/iguana/algorithms/clas12/rga/FiducialFilterPass2/Algorithm.cc b/src/iguana/algorithms/clas12/rga/FiducialFilterPass2/Algorithm.cc index fff78018..3bedc319 100644 --- a/src/iguana/algorithms/clas12/rga/FiducialFilterPass2/Algorithm.cc +++ b/src/iguana/algorithms/clas12/rga/FiducialFilterPass2/Algorithm.cc @@ -29,7 +29,7 @@ namespace iguana::clas12::rga { void FiducialFilterPass2::LoadConfig() { - m_cal_strictness = GetOptionScalar("calorimeter.strictness", {"calorimeter", "strictness"}); + m_cal_strictness = GetOptionScalar({"calorimeter", "strictness"}); if(m_cal_strictness < 1 || m_cal_strictness > 3) { throw std::runtime_error("[RGAFID] 'calorimeter.strictness' must be 1, 2, or 3"); } @@ -81,7 +81,7 @@ namespace iguana::clas12::rga { if(m_cvt.edge_layers.empty()) { throw std::runtime_error("[RGAFID] 'cvt.edge_layers' must be non-empty"); } - m_cvt.edge_min = GetOptionScalar("cvt.edge_min", {"cvt", "edge_min"}); + m_cvt.edge_min = GetOptionScalar({"cvt", "edge_min"}); m_cvt.phi_forbidden_deg.clear(); try { @@ -103,7 +103,7 @@ namespace iguana::clas12::rga { { m_dc.theta_small_deg = - GetOptionScalar("dc.theta_small_deg", {"dc", "theta_small_deg"}); + GetOptionScalar({"dc", "theta_small_deg"}); auto need3 = [&](char const* key) -> std::array { auto v = GetOptionVector(std::string("dc.") + key, {"dc", key}); diff --git a/src/iguana/algorithms/example/ExampleAlgorithm/Algorithm.cc b/src/iguana/algorithms/example/ExampleAlgorithm/Algorithm.cc index 4217c795..a1198470 100644 --- a/src/iguana/algorithms/example/ExampleAlgorithm/Algorithm.cc +++ b/src/iguana/algorithms/example/ExampleAlgorithm/Algorithm.cc @@ -33,8 +33,8 @@ namespace iguana::example { // # user has specified to use a different configuration file or directory // ############################################################################ ParseYAMLConfig(); - o_exampleInt = GetOptionScalar("exampleInt"); - o_exampleDouble = GetOptionScalar("exampleDouble"); + o_exampleInt = GetOptionScalar({"exampleInt"}); + o_exampleDouble = GetOptionScalar({"exampleDouble"}); // ############################################################################ // # get expected bank indices // # - here we make sure that parameter `banks` includes the banks that are diff --git a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc index 6901892b..7f0d6d61 100644 --- a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc +++ b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc @@ -12,11 +12,11 @@ namespace iguana::physics { { // parse config file ParseYAMLConfig(); - o_particle_bank = GetOptionScalar("particle_bank"); + o_particle_bank = GetOptionScalar({"particle_bank"}); o_hadron_a_pdgs = GetOptionSet("hadron_a_list"); o_hadron_b_pdgs = GetOptionSet("hadron_b_list"); - o_phi_r_method = GetOptionScalar("phi_r_method"); - o_theta_method = GetOptionScalar("theta_method"); + o_phi_r_method = GetOptionScalar({"phi_r_method"}); + o_theta_method = GetOptionScalar({"theta_method"}); // check phiR method if(o_phi_r_method == "RT_via_covariant_kT") diff --git a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc index 858cf86f..7612bcca 100644 --- a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc +++ b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc @@ -13,14 +13,14 @@ namespace iguana::physics { { // parse config file ParseYAMLConfig(); - o_particle_bank = GetOptionScalar("particle_bank"); + o_particle_bank = GetOptionScalar({"particle_bank"}); o_runnum = ConcurrentParamFactory::Create(); o_target_PxPyPzM = ConcurrentParamFactory::Create>(); o_beam_PxPyPzM = ConcurrentParamFactory::Create>(); - o_theta_between_FD_and_FT = GetOptionScalar("theta_between_FD_and_FT"); + o_theta_between_FD_and_FT = GetOptionScalar({"theta_between_FD_and_FT"}); // get reconstruction method configuration - auto method_reconstruction_str = GetOptionScalar("reconstruction", {"method", "reconstruction"}); + auto method_reconstruction_str = GetOptionScalar({"method", "reconstruction"}); if(method_reconstruction_str == "scattered_lepton") { o_method_reconstruction = method_reconstruction::scattered_lepton; } @@ -30,7 +30,7 @@ namespace iguana::physics { } // get scattered lepton finder configuration - auto method_lepton_finder_str = GetOptionScalar("lepton_finder", {"method", "lepton_finder"}); + auto method_lepton_finder_str = GetOptionScalar({"method", "lepton_finder"}); if(method_lepton_finder_str == "highest_energy_FD_trigger") o_method_lepton_finder = method_lepton_finder::highest_energy_FD_trigger; else if(method_lepton_finder_str == "lund_beam_daughter") @@ -42,7 +42,7 @@ namespace iguana::physics { // get beam PDG and mass o_beam_pdg = 0; - auto beam_particle = GetOptionScalar("beam_particle", {"method", "beam_particle"}); + auto beam_particle = GetOptionScalar({"method", "beam_particle"}); for(auto const& [pdg, name] : particle::name) { if(name == beam_particle) { o_beam_pdg = pdg; @@ -76,7 +76,7 @@ namespace iguana::physics { // instantiate RCDB reader `m_rcdb` StartRCDBReader(); - o_override_beam_energy = GetOptionScalar("override_beam_energy"); + o_override_beam_energy = GetOptionScalar({"override_beam_energy"}); if(o_override_beam_energy > 0) m_rcdb->SetBeamEnergyOverride(o_override_beam_energy); } @@ -257,7 +257,7 @@ namespace iguana::physics { // parse config params auto beam_energy = user_beam_energy < 0 ? m_rcdb->GetBeamEnergy(runnum) : user_beam_energy; auto beam_direction = GetOptionVector("beam_direction", {"initial_state", GetConfig()->InRange("runs", runnum), "beam_direction"}); - auto target_particle = GetOptionScalar("target_particle", {"initial_state", GetConfig()->InRange("runs", runnum), "target_particle"}); + auto target_particle = GetOptionScalar({"initial_state", GetConfig()->InRange("runs", runnum), "target_particle"}); // get the target mass and momentum double target_mass = -1; diff --git a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc index bfb18b8a..9adc85df 100644 --- a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc +++ b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc @@ -12,7 +12,7 @@ namespace iguana::physics { { // parse config file ParseYAMLConfig(); - o_particle_bank = GetOptionScalar("particle_bank"); + o_particle_bank = GetOptionScalar({"particle_bank"}); o_hadron_pdgs = GetOptionSet("hadron_list"); // get bank indices diff --git a/src/iguana/services/Deprecated.cc b/src/iguana/services/Deprecated.cc new file mode 100644 index 00000000..cfd351b0 --- /dev/null +++ b/src/iguana/services/Deprecated.cc @@ -0,0 +1,29 @@ +#include "Deprecated.h" + +#include +#include + +namespace iguana::deprecated { + + void CheckSetOptionKey(std::string const& algo_class_name, std::string const& key) noexcept(false) + { + // clang-format off + std::map> renames = { + { "physics::InclusiveKinematics", { + { "reconstruction", "method/reconstruction" }, + { "lepton_finder", "method/lepton_finder" }, + { "beam_particle", "method/beam_particle" }, + { "beam_direction", "initial_state/beam_direction" }, + { "target_particle", "initial_state/target_particle" }, + }, + }, + }; + // clang-format on + if(auto algo_it{renames.find(algo_class_name)}; algo_it != renames.end()) { + if(auto rename_it{algo_it->second.find(key)}; rename_it != algo_it->second.end()) { + throw std::runtime_error("Called 'SetOption' with deprecated key '" + key + "'; it has been renamed to '" + rename_it->second + "'"); + } + } + } + +} diff --git a/src/iguana/services/Deprecated.h b/src/iguana/services/Deprecated.h new file mode 100644 index 00000000..2a96614b --- /dev/null +++ b/src/iguana/services/Deprecated.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace iguana::deprecated { + + /// @brief check if a configuration parameter name (key), used in `Algorithm::SetOption`, has been deprecated; if so, throw exception with guidance + /// @param algo_class_name the name of the algorithm class + /// @param key the configuration parameter name (key) used in `Algorithm::SetOption` + void CheckSetOptionKey(std::string const& algo_class_name, std::string const& key) noexcept(false); + +} diff --git a/src/iguana/services/YAMLReader.cc b/src/iguana/services/YAMLReader.cc index 37d30160..803826bb 100644 --- a/src/iguana/services/YAMLReader.cc +++ b/src/iguana/services/YAMLReader.cc @@ -2,6 +2,10 @@ namespace iguana { + std::string YAMLReader::KEY_DELIM = "/"; + + /////////////////////////////////////////////////////////////////////////////// + void YAMLReader::LoadFiles() { m_log->Debug("YAMLReader::LoadFiles():"); @@ -18,6 +22,20 @@ namespace iguana { } } } + /////////////////////////////////////////////////////////////////////////////// + + std::string YAMLReader::NodePath2String(node_path_t const& node_path) + { + if(node_path.empty()) + return ""; + std::vector tokens; + auto node_id_visitor = [&tokens](auto&& arg) { + if constexpr(std::is_same_v, std::string>) + tokens.push_back(arg); + }; + std::visit(node_id_visitor, node_path.front()); + return fmt::format("{}", fmt::join(tokens, KEY_DELIM)); + } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/iguana/services/YAMLReader.h b/src/iguana/services/YAMLReader.h index 79408d0d..60274861 100644 --- a/src/iguana/services/YAMLReader.h +++ b/src/iguana/services/YAMLReader.h @@ -27,6 +27,9 @@ namespace iguana { /// Representation of a path of `YAML::Node`s in a `YAML::Node` tree, _e.g._, in a YAML file. using node_path_t = std::deque; + /// Delimiter for parameter key names + static std::string KEY_DELIM; + /// @param name of this reader (for `Logger`) YAMLReader(std::string_view name = "config") : ConfigFileReader(name) @@ -36,32 +39,36 @@ namespace iguana { /// Parse the YAML files added by `ConfigFileReader::AddFile` void LoadFiles(); - /// Read a scalar value from a `YAML::Node` + /// @brief Convert a `YAML::Node` path to a string + /// @param node_path the `YAML::Node` path + /// @return the converted string + static std::string NodePath2String(node_path_t const& node_path); + + /// @brief Read a scalar value from a `YAML::Node` /// @param node the `YAML::Node` to read /// @return the scalar, if found template std::optional GetScalar(YAML::Node node); - /// Read a scalar value from a `YAML::Node` path; searches all currently loaded config files. + /// @brief 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, if found template std::optional GetScalar(node_path_t node_path); - /// Read a vector value from a `YAML::Node` + /// @brief Read a vector value from a `YAML::Node` /// @param node the `YAML::Node` to read /// @return the vector, if found template std::optional> GetVector(YAML::Node node); - /// Read a vector value from a `YAML::Node` path; searches all currently loaded config files. + /// @brief 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, if found template 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` + /// @brief 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` /// @param key the key of the sub-`YAML::Node` to use as the range (its value must be a 2-vector) /// @param val the scalar value to check /// @returns the search function @@ -70,7 +77,7 @@ namespace iguana { private: - /// Search a tree of `YAML::Node`s for a node specified by a `node_path_t` + /// @brief Search a tree of `YAML::Node`s for a node specified by a `node_path_t` /// @param node the root `YAML::Node` /// @param node_path the path of `YAML::Node` identifiers /// @returns either the found `YAML::Node`, or an empty (null) `YAML::Node` if one is not found diff --git a/src/iguana/services/meson.build b/src/iguana/services/meson.build index 86e93f74..c4623bf3 100644 --- a/src/iguana/services/meson.build +++ b/src/iguana/services/meson.build @@ -7,6 +7,7 @@ services_sources = [ 'GlobalParam.cc', 'RCDBReader.cc', 'Tools.cc', + 'Deprecated.cc', ] services_headers = [ 'Logger.h', @@ -17,6 +18,7 @@ services_headers = [ 'GlobalParam.h', 'RCDBReader.h', 'Tools.h', + 'Deprecated.h', ] if rcdb_dep.found() diff --git a/src/iguana/tests/include/TestConfig.h b/src/iguana/tests/include/TestConfig.h index 1f60babc..8db6f7fb 100644 --- a/src/iguana/tests/include/TestConfig.h +++ b/src/iguana/tests/include/TestConfig.h @@ -31,9 +31,9 @@ inline int TestConfig(int test_num, std::string log_level) case 1: { // test `GetOptionScalar` - assert((algo->GetOptionScalar("scalar_int") == 1)); - assert((algo->GetOptionScalar("scalar_double") == 2.5)); - assert((algo->GetOptionScalar("scalar_string") == "lizard")); + assert((algo->GetOptionScalar({"scalar_int"}) == 1)); + assert((algo->GetOptionScalar({"scalar_double"}) == 2.5)); + assert((algo->GetOptionScalar({"scalar_string"}) == "lizard")); // test `GetOptionVector` assert((algo->GetOptionVector("vector_int") == std::vector{1, 2, 3})); assert((algo->GetOptionVector("vector_double") == std::vector{1.5, 2.5})); @@ -45,7 +45,7 @@ inline int TestConfig(int test_num, std::string log_level) assert((s.find("bee") == s.end())); // test empty access - expect exceptions, so just catch them and do nothing try { - algo->GetOptionScalar("scalar_empty"); + algo->GetOptionScalar({"scalar_empty"}); fmt::print(stderr, "ERROR: accessing 'scalar_empty' did not throw exception\n"); return 1; } @@ -70,7 +70,7 @@ inline int TestConfig(int test_num, std::string log_level) } // test access to a key that does not exist try { - algo->GetOptionScalar("non_existent_scalar"); + algo->GetOptionScalar({"non_existent_scalar"}); fmt::print(stderr, "ERROR: accessing 'non_existent_scalar' did not throw exception\n"); return 1; } @@ -97,9 +97,9 @@ inline int TestConfig(int test_num, std::string log_level) } case 2: { - assert((algo->GetOptionScalar("t1s1", {"tree1", "scalar1"}) == 1.5)); - assert((algo->GetOptionScalar("t1s2", {"tree1", "scalar2"}) == 2.5)); - assert((algo->GetOptionScalar("t2t1s1", {"tree2", "tree1", "scalar1"}) == 3.5)); + assert((algo->GetOptionScalar({"tree1", "scalar1"}) == 1.5)); + assert((algo->GetOptionScalar({"tree1", "scalar2"}) == 2.5)); + assert((algo->GetOptionScalar({"tree2", "tree1", "scalar1"}) == 3.5)); assert((algo->GetOptionVector("t2t2t3v1", {"tree2", "tree2", "tree3", "vector1"}) == std::vector{"gecko", "snake"})); assert((algo->GetOptionVector("t2v2", {"tree2", "vector2"}) == std::vector{3, -4, 5})); assert((algo->GetOptionVector("vector1", {"vector1"}) == std::vector{"bee"})); @@ -109,25 +109,25 @@ inline int TestConfig(int test_num, std::string log_level) case 3: { // test InRange tree1 - assert((algo->GetOptionScalar("t1a", {"tree1", algo->GetConfig()->InRange("test_range", 1), "val"}) == 3)); - assert((algo->GetOptionScalar("t1b", {"tree1", algo->GetConfig()->InRange("test_range", 3), "val"}) == 3)); - assert((algo->GetOptionScalar("t1c", {"tree1", algo->GetConfig()->InRange("test_range", 5), "val"}) == 3)); // at a border - assert((algo->GetOptionScalar("t1d", {"tree1", algo->GetConfig()->InRange("test_range", 6), "val"}) == 4)); - assert((algo->GetOptionScalar("t1e", {"tree1", algo->GetConfig()->InRange("test_range", 10), "val"}) == 4)); - assert((algo->GetOptionScalar("t1f", {"tree1", algo->GetConfig()->InRange("test_range", 11), "val"}) == 0)); // default fallback - assert((algo->GetOptionScalar("t1g", {"tree1", algo->GetConfig()->InRange("test_range", 10.1), "val"}) == 0)); // wrong type - assert((algo->GetOptionScalar("t1h", {"tree1", algo->GetConfig()->InRange("test_range", 3.7), "val"}) == 3)); // wrong type + assert((algo->GetOptionScalar({"tree1", algo->GetConfig()->InRange("test_range", 1), "val"}) == 3)); + assert((algo->GetOptionScalar({"tree1", algo->GetConfig()->InRange("test_range", 3), "val"}) == 3)); + assert((algo->GetOptionScalar({"tree1", algo->GetConfig()->InRange("test_range", 5), "val"}) == 3)); // at a border + assert((algo->GetOptionScalar({"tree1", algo->GetConfig()->InRange("test_range", 6), "val"}) == 4)); + assert((algo->GetOptionScalar({"tree1", algo->GetConfig()->InRange("test_range", 10), "val"}) == 4)); + assert((algo->GetOptionScalar({"tree1", algo->GetConfig()->InRange("test_range", 11), "val"}) == 0)); // default fallback + assert((algo->GetOptionScalar({"tree1", algo->GetConfig()->InRange("test_range", 10.1), "val"}) == 0)); // wrong type + assert((algo->GetOptionScalar({"tree1", algo->GetConfig()->InRange("test_range", 3.7), "val"}) == 3)); // wrong type // test InRange tree2 - assert((algo->GetOptionScalar("t2a", {"tree2", algo->GetConfig()->InRange("test_range", 1.9), "subtree", "lizard"}) == "iguana")); - assert((algo->GetOptionScalar("t2b", {"tree2", algo->GetConfig()->InRange("test_range", 1.9), "subtree", "number"}) == 7)); - assert((algo->GetOptionScalar("t2c", {"tree2", algo->GetConfig()->InRange("test_range", 3.0), "subtree", algo->GetConfig()->InRange("sub_range", 1), "val"}) == 7)); - assert((algo->GetOptionScalar("t2d", {"tree2", algo->GetConfig()->InRange("test_range", 3.0), "subtree", algo->GetConfig()->InRange("sub_range", 8), "val"}) == 8)); - assert((algo->GetOptionScalar("t2e", {"tree2", algo->GetConfig()->InRange("test_range", 3.5), "subtree", algo->GetConfig()->InRange("sub_range", 11), "val"}) == 1)); - assert((algo->GetOptionScalar("t2f", {"tree2", algo->GetConfig()->InRange("test_range", 4.0), "subtree"}) == 10)); + assert((algo->GetOptionScalar({"tree2", algo->GetConfig()->InRange("test_range", 1.9), "subtree", "lizard"}) == "iguana")); + assert((algo->GetOptionScalar({"tree2", algo->GetConfig()->InRange("test_range", 1.9), "subtree", "number"}) == 7)); + assert((algo->GetOptionScalar({"tree2", algo->GetConfig()->InRange("test_range", 3.0), "subtree", algo->GetConfig()->InRange("sub_range", 1), "val"}) == 7)); + assert((algo->GetOptionScalar({"tree2", algo->GetConfig()->InRange("test_range", 3.0), "subtree", algo->GetConfig()->InRange("sub_range", 8), "val"}) == 8)); + assert((algo->GetOptionScalar({"tree2", algo->GetConfig()->InRange("test_range", 3.5), "subtree", algo->GetConfig()->InRange("sub_range", 11), "val"}) == 1)); + assert((algo->GetOptionScalar({"tree2", algo->GetConfig()->InRange("test_range", 4.0), "subtree"}) == 10)); // test InRange tree3 - assert((algo->GetOptionScalar("t3a", {"tree3", algo->GetConfig()->InRange("test_range", 3), "val"}) == 3)); + assert((algo->GetOptionScalar({"tree3", algo->GetConfig()->InRange("test_range", 3), "val"}) == 3)); try { - assert((algo->GetOptionScalar("t3b", {"tree3", algo->GetConfig()->InRange("test_range", 11), "val"}) == 0)); + assert((algo->GetOptionScalar({"tree3", algo->GetConfig()->InRange("test_range", 11), "val"}) == 0)); fmt::print(stderr, "ERROR: accessing a missing default value for `InRange` did not throw exception\n"); return 1; } From 0657fda3bc1cfde5230c30ef64d37399c73a0524 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Thu, 22 Jan 2026 18:23:43 -0500 Subject: [PATCH 02/10] fix: update `GetOption{Vector,Set}` too --- src/iguana/algorithms/Algorithm.cc | 21 +++++++++-------- src/iguana/algorithms/Algorithm.h | 4 ++-- .../clas12/EventBuilderFilter/Algorithm.cc | 2 +- .../clas12/ZVertexFilter/Algorithm.cc | 2 +- .../rga/FiducialFilterPass2/Algorithm.cc | 12 ++++------ .../physics/DihadronKinematics/Algorithm.cc | 4 ++-- .../physics/InclusiveKinematics/Algorithm.cc | 2 +- .../SingleHadronKinematics/Algorithm.cc | 2 +- src/iguana/tests/include/TestConfig.h | 23 +++++++++---------- 9 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/iguana/algorithms/Algorithm.cc b/src/iguana/algorithms/Algorithm.cc index c9ba9d84..295f164f 100644 --- a/src/iguana/algorithms/Algorithm.cc +++ b/src/iguana/algorithms/Algorithm.cc @@ -53,37 +53,38 @@ namespace iguana { /////////////////////////////////////////////////////////////////////////////// template - std::vector Algorithm::GetOptionVector(std::string const& key, YAMLReader::node_path_t node_path) const + std::vector Algorithm::GetOptionVector(YAMLReader::node_path_t node_path) const { node_path.push_front(m_class_name); + auto key = YAMLReader::NodePath2String(node_path); auto opt = GetCachedOption>(key); if(!opt.has_value()) { opt = m_yaml_config->GetVector(node_path); } if(!opt.has_value()) { - m_log->Error("Failed to `GetOptionVector` for key {:?}", key); + m_log->Error("Failed to `GetOptionVector` for parameter {:?}", 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; - template std::vector Algorithm::GetOptionVector(std::string const& key, YAMLReader::node_path_t node_path) const; + template std::vector Algorithm::GetOptionVector(YAMLReader::node_path_t node_path) const; + template std::vector Algorithm::GetOptionVector(YAMLReader::node_path_t node_path) const; + template std::vector Algorithm::GetOptionVector(YAMLReader::node_path_t node_path) const; /////////////////////////////////////////////////////////////////////////////// template - std::set Algorithm::GetOptionSet(std::string const& key, YAMLReader::node_path_t node_path) const + std::set Algorithm::GetOptionSet(YAMLReader::node_path_t node_path) const { - auto val_vec = GetOptionVector(key, node_path); + auto val_vec = GetOptionVector(node_path); std::set val_set; std::copy(val_vec.begin(), val_vec.end(), std::inserter(val_set, val_set.end())); return val_set; } - template std::set Algorithm::GetOptionSet(std::string const& key, YAMLReader::node_path_t node_path) const; - template std::set Algorithm::GetOptionSet(std::string const& key, YAMLReader::node_path_t node_path) const; - template std::set Algorithm::GetOptionSet(std::string const& key, YAMLReader::node_path_t node_path) const; + template std::set Algorithm::GetOptionSet(YAMLReader::node_path_t node_path) const; + template std::set Algorithm::GetOptionSet(YAMLReader::node_path_t node_path) const; + template std::set Algorithm::GetOptionSet(YAMLReader::node_path_t node_path) const; /////////////////////////////////////////////////////////////////////////////// diff --git a/src/iguana/algorithms/Algorithm.h b/src/iguana/algorithms/Algorithm.h index 74c8d2cf..bce35bb4 100644 --- a/src/iguana/algorithms/Algorithm.h +++ b/src/iguana/algorithms/Algorithm.h @@ -137,13 +137,13 @@ namespace iguana { /// @param node_path the `YAML::Node` identifier path to search for this option in the config files /// @returns the vector option template - std::vector GetOptionVector(std::string const& key, YAMLReader::node_path_t node_path = {}) const; + std::vector GetOptionVector(YAMLReader::node_path_t node_path = {}) const; /// Get the value of a vector option, and convert it to `std::set` /// @param node_path the `YAML::Node` identifier path to search for this option in the config files /// @returns the vector option converted to `std::set` template - std::set GetOptionSet(std::string const& key, YAMLReader::node_path_t node_path = {}) const; + std::set GetOptionSet(YAMLReader::node_path_t node_path = {}) const; /// Set the name of this algorithm /// @param name the new name diff --git a/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.cc b/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.cc index 9a529d59..a4de4cb9 100644 --- a/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.cc +++ b/src/iguana/algorithms/clas12/EventBuilderFilter/Algorithm.cc @@ -10,7 +10,7 @@ namespace iguana::clas12 { // define options, their default values, and cache them ParseYAMLConfig(); o_particle_bank = GetOptionScalar({"particle_bank"}); - o_pids = GetOptionSet("pids"); + o_pids = GetOptionSet({"pids"}); // get expected bank indices b_particle = GetBankIndex(banks, o_particle_bank); diff --git a/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc b/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc index 0fcab0a7..efafece4 100644 --- a/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc +++ b/src/iguana/algorithms/clas12/ZVertexFilter/Algorithm.cc @@ -71,7 +71,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", {"electron", GetConfig()->InRange("runs", runnum), "vz"}), key); + o_electron_vz_cuts->Save(GetOptionVector({"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/rga/FiducialFilterPass2/Algorithm.cc b/src/iguana/algorithms/clas12/rga/FiducialFilterPass2/Algorithm.cc index 3bedc319..12eee662 100644 --- a/src/iguana/algorithms/clas12/rga/FiducialFilterPass2/Algorithm.cc +++ b/src/iguana/algorithms/clas12/rga/FiducialFilterPass2/Algorithm.cc @@ -35,7 +35,7 @@ namespace iguana::clas12::rga { } { - auto radius = GetOptionVector("forward_tagger.radius", {"forward_tagger", "radius"}); + auto radius = GetOptionVector({"forward_tagger", "radius"}); if(radius.size() != 2) { throw std::runtime_error("[RGAFID] 'forward_tagger.radius' must be [rmin, rmax]"); } @@ -49,8 +49,7 @@ namespace iguana::clas12::rga { u_ft_params.holes.clear(); std::vector holes_flat; try { - holes_flat = GetOptionVector("forward_tagger.holes_flat", - {"forward_tagger", "holes_flat"}); + holes_flat = GetOptionVector({"forward_tagger", "holes_flat"}); } catch(std::exception const& e) { std::string const msg = e.what(); @@ -77,7 +76,7 @@ namespace iguana::clas12::rga { } { - m_cvt.edge_layers = GetOptionVector("cvt.edge_layers", {"cvt", "edge_layers"}); + m_cvt.edge_layers = GetOptionVector({"cvt", "edge_layers"}); if(m_cvt.edge_layers.empty()) { throw std::runtime_error("[RGAFID] 'cvt.edge_layers' must be non-empty"); } @@ -85,8 +84,7 @@ namespace iguana::clas12::rga { m_cvt.phi_forbidden_deg.clear(); try { - m_cvt.phi_forbidden_deg = GetOptionVector("cvt.phi_forbidden_deg", - {"cvt", "phi_forbidden_deg"}); + m_cvt.phi_forbidden_deg = GetOptionVector({"cvt", "phi_forbidden_deg"}); } catch(std::exception const& e) { std::string const msg = e.what(); @@ -106,7 +104,7 @@ namespace iguana::clas12::rga { GetOptionScalar({"dc", "theta_small_deg"}); auto need3 = [&](char const* key) -> std::array { - auto v = GetOptionVector(std::string("dc.") + key, {"dc", key}); + auto v = GetOptionVector({"dc", key}); if(v.size() != 3) { throw std::runtime_error(std::string("[RGAFID] 'dc.") + key + "' must be [e1,e2,e3]"); } diff --git a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc index 7f0d6d61..2f710946 100644 --- a/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc +++ b/src/iguana/algorithms/physics/DihadronKinematics/Algorithm.cc @@ -13,8 +13,8 @@ namespace iguana::physics { // parse config file ParseYAMLConfig(); o_particle_bank = GetOptionScalar({"particle_bank"}); - o_hadron_a_pdgs = GetOptionSet("hadron_a_list"); - o_hadron_b_pdgs = GetOptionSet("hadron_b_list"); + o_hadron_a_pdgs = GetOptionSet({"hadron_a_list"}); + o_hadron_b_pdgs = GetOptionSet({"hadron_b_list"}); o_phi_r_method = GetOptionScalar({"phi_r_method"}); o_theta_method = GetOptionScalar({"theta_method"}); diff --git a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc index 7612bcca..ddc74a42 100644 --- a/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc +++ b/src/iguana/algorithms/physics/InclusiveKinematics/Algorithm.cc @@ -256,7 +256,7 @@ namespace iguana::physics { // parse config params auto beam_energy = user_beam_energy < 0 ? m_rcdb->GetBeamEnergy(runnum) : user_beam_energy; - auto beam_direction = GetOptionVector("beam_direction", {"initial_state", GetConfig()->InRange("runs", runnum), "beam_direction"}); + auto beam_direction = GetOptionVector({"initial_state", GetConfig()->InRange("runs", runnum), "beam_direction"}); auto target_particle = GetOptionScalar({"initial_state", GetConfig()->InRange("runs", runnum), "target_particle"}); // get the target mass and momentum diff --git a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc index 9adc85df..b0986953 100644 --- a/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc +++ b/src/iguana/algorithms/physics/SingleHadronKinematics/Algorithm.cc @@ -13,7 +13,7 @@ namespace iguana::physics { // parse config file ParseYAMLConfig(); o_particle_bank = GetOptionScalar({"particle_bank"}); - o_hadron_pdgs = GetOptionSet("hadron_list"); + o_hadron_pdgs = GetOptionSet({"hadron_list"}); // get bank indices b_particle = GetBankIndex(banks, o_particle_bank); diff --git a/src/iguana/tests/include/TestConfig.h b/src/iguana/tests/include/TestConfig.h index 8db6f7fb..8bb9be48 100644 --- a/src/iguana/tests/include/TestConfig.h +++ b/src/iguana/tests/include/TestConfig.h @@ -35,11 +35,11 @@ inline int TestConfig(int test_num, std::string log_level) assert((algo->GetOptionScalar({"scalar_double"}) == 2.5)); assert((algo->GetOptionScalar({"scalar_string"}) == "lizard")); // test `GetOptionVector` - assert((algo->GetOptionVector("vector_int") == std::vector{1, 2, 3})); - assert((algo->GetOptionVector("vector_double") == std::vector{1.5, 2.5})); - assert((algo->GetOptionVector("vector_string") == std::vector{"spider", "bat", "chameleon", "spider"})); + assert((algo->GetOptionVector({"vector_int"}) == std::vector{1, 2, 3})); + assert((algo->GetOptionVector({"vector_double"}) == std::vector{1.5, 2.5})); + assert((algo->GetOptionVector({"vector_string"}) == std::vector{"spider", "bat", "chameleon", "spider"})); // test `GetOptionSet` - auto s = algo->GetOptionSet("vector_string"); + auto s = algo->GetOptionSet({"vector_string"}); assert((s.size() == 3)); assert((s.find("spider") != s.end())); assert((s.find("bee") == s.end())); @@ -53,7 +53,7 @@ inline int TestConfig(int test_num, std::string log_level) fmt::print("SUCCESS: accessing 'scalar_empty' threw an expected exception\n"); } try { - algo->GetOptionVector("vector_empty"); + algo->GetOptionVector({"vector_empty"}); fmt::print(stderr, "ERROR: accessing 'vector_empty' did not throw exception\n"); return 1; } @@ -61,7 +61,7 @@ inline int TestConfig(int test_num, std::string log_level) fmt::print("SUCCESS: accessing 'vector_empty' threw an expected exception\n"); } try { - algo->GetOptionSet("vector_empty"); + algo->GetOptionSet({"vector_empty"}); fmt::print(stderr, "ERROR: accessing 'vector_empty' as a `set` did not throw exception\n"); return 1; } @@ -78,7 +78,7 @@ inline int TestConfig(int test_num, std::string log_level) fmt::print("SUCCESS: accessing 'non_existent_scalar' threw an expected exception\n"); } try { - algo->GetOptionVector("non_existent_vector"); + algo->GetOptionVector({"non_existent_vector"}); fmt::print(stderr, "ERROR: accessing 'non_existent_vector' did not throw exception\n"); return 1; } @@ -86,7 +86,7 @@ inline int TestConfig(int test_num, std::string log_level) fmt::print("SUCCESS: accessing 'non_existent_vector' threw an expected exception\n"); } try { - algo->GetOptionSet("non_existent_vector"); + algo->GetOptionSet({"non_existent_vector"}); fmt::print(stderr, "ERROR: accessing 'non_existent_vector' as a `set` did not throw exception\n"); return 1; } @@ -100,10 +100,9 @@ inline int TestConfig(int test_num, std::string log_level) assert((algo->GetOptionScalar({"tree1", "scalar1"}) == 1.5)); assert((algo->GetOptionScalar({"tree1", "scalar2"}) == 2.5)); assert((algo->GetOptionScalar({"tree2", "tree1", "scalar1"}) == 3.5)); - assert((algo->GetOptionVector("t2t2t3v1", {"tree2", "tree2", "tree3", "vector1"}) == std::vector{"gecko", "snake"})); - assert((algo->GetOptionVector("t2v2", {"tree2", "vector2"}) == std::vector{3, -4, 5})); - assert((algo->GetOptionVector("vector1", {"vector1"}) == std::vector{"bee"})); - assert((algo->GetOptionVector("vector1") == std::vector{"bee"})); + assert((algo->GetOptionVector({"tree2", "tree2", "tree3", "vector1"}) == std::vector{"gecko", "snake"})); + assert((algo->GetOptionVector({"tree2", "vector2"}) == std::vector{3, -4, 5})); + assert((algo->GetOptionVector({"vector1"}) == std::vector{"bee"})); break; } From b25d1d4ae1c22aa6b83da3d8f323d8439e363e28 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Thu, 22 Jan 2026 19:04:44 -0500 Subject: [PATCH 03/10] refactor: minimize `SetOption` usage --- .../iguana_ex_python_00_run_functions.py | 8 +++++--- .../iguana_ex_python_01_action_functions.py | 6 +++--- bind/python/iguana_ex_python_hipopy.py | 6 +++--- examples/iguana_ex_cpp_00_run_functions.cc | 8 +++++--- ...guana_ex_cpp_00_run_functions_with_banks.cc | 8 +++++--- examples/iguana_ex_cpp_01_action_functions.cc | 8 +++++--- src/iguana/algorithms/Algorithm.h | 12 ++++++------ src/iguana/algorithms/AlgorithmSequence.h | 9 +++++++++ src/iguana/services/YAMLReader.cc | 18 +++++++++++++++--- src/iguana/services/YAMLReader.h | 3 --- src/iguana/tests/include/TestAlgorithm.h | 2 +- src/iguana/tests/include/TestConfig.h | 2 +- src/iguana/tests/include/TestMultithreading.h | 2 +- src/iguana/tests/include/TestValidator.h | 2 +- 14 files changed, 60 insertions(+), 34 deletions(-) diff --git a/bind/python/iguana_ex_python_00_run_functions.py b/bind/python/iguana_ex_python_00_run_functions.py index 1f82093a..3f9e5f37 100755 --- a/bind/python/iguana_ex_python_00_run_functions.py +++ b/bind/python/iguana_ex_python_00_run_functions.py @@ -44,12 +44,14 @@ # set log levels # NOTE: this can also be done in a config file -seq.SetOption('clas12::EventBuilderFilter', 'log', 'info') -seq.SetOption('clas12::SectorFinder', 'log', 'info') -seq.SetOption('clas12::rga::MomentumCorrection', 'log', 'info') +seq.SetLogLevel('clas12::EventBuilderFilter' 'info') +seq.SetLogLevel('clas12::SectorFinder' 'info') +seq.SetLogLevel('clas12::rga::MomentumCorrection' 'info') # set algorithm options # NOTE: this can also be done in a config file, but setting options here OVERRIDES config file settings +# WARNING: in practice, verify the configuration parameter was set the way you want; configuration parameter values +# are printed out for algorithms at the "debug" log level seq.SetOption('clas12::EventBuilderFilter', 'pids', [11, 211, -211]) # start the algorithms diff --git a/bind/python/iguana_ex_python_01_action_functions.py b/bind/python/iguana_ex_python_01_action_functions.py index f2624ba9..aadae951 100755 --- a/bind/python/iguana_ex_python_01_action_functions.py +++ b/bind/python/iguana_ex_python_01_action_functions.py @@ -52,9 +52,9 @@ algo_momentum_correction = iguana.clas12.rga.MomentumCorrection() # momentum corrections (a transformer algorithm) # set log levels -algo_eventbuilder_filter.SetOption('log', 'info') -algo_sector_finder.SetOption('log', 'info') -algo_momentum_correction.SetOption('log', 'info') +algo_eventbuilder_filter.SetLogLevel('info') +algo_sector_finder.SetLogLevel('info') +algo_momentum_correction.SetLogLevel('info') # set algorithm options algo_eventbuilder_filter.SetOption('pids', [11, 211, -211]) diff --git a/bind/python/iguana_ex_python_hipopy.py b/bind/python/iguana_ex_python_hipopy.py index bcc16abd..0172c215 100755 --- a/bind/python/iguana_ex_python_hipopy.py +++ b/bind/python/iguana_ex_python_hipopy.py @@ -45,9 +45,9 @@ algo_momentum_correction = iguana.clas12.rga.MomentumCorrection() # momentum corrections (a transformer algorithm) # set log levels -algo_eventbuilder_filter.SetOption('log', 'info') -algo_sector_finder.SetOption('log', 'info') -algo_momentum_correction.SetOption('log', 'info') +algo_eventbuilder_filter.SetLogLevel('info') +algo_sector_finder.SetLogLevel('info') +algo_momentum_correction.SetLogLevel('info') # set algorithm options algo_eventbuilder_filter.SetOption('pids', [11, 211, -211]) diff --git a/examples/iguana_ex_cpp_00_run_functions.cc b/examples/iguana_ex_cpp_00_run_functions.cc index f36156d4..ceda54fd 100644 --- a/examples/iguana_ex_cpp_00_run_functions.cc +++ b/examples/iguana_ex_cpp_00_run_functions.cc @@ -49,12 +49,14 @@ int main(int argc, char** argv) // set log levels // NOTE: this can also be done in a config file - seq.SetOption("clas12::EventBuilderFilter", "log", "info"); - seq.SetOption("clas12::SectorFinder", "log", "info"); - seq.SetOption("clas12::rga::MomentumCorrection", "log", "info"); + seq.SetLogLevel("clas12::EventBuilderFilter", "info"); + seq.SetLogLevel("clas12::SectorFinder", "info"); + seq.SetLogLevel("clas12::rga::MomentumCorrection", "info"); // set algorithm options // NOTE: this can also be done in a config file, but setting options here OVERRIDES config file settings + // WARNING: in practice, verify the configuration parameter was set the way you want; configuration parameter values + // are printed out for algorithms at the "debug" log level seq.SetOption>("clas12::EventBuilderFilter", "pids", {11, 211, -211}); // start the algorithms diff --git a/examples/iguana_ex_cpp_00_run_functions_with_banks.cc b/examples/iguana_ex_cpp_00_run_functions_with_banks.cc index bb98f780..b14ee7ea 100644 --- a/examples/iguana_ex_cpp_00_run_functions_with_banks.cc +++ b/examples/iguana_ex_cpp_00_run_functions_with_banks.cc @@ -53,12 +53,14 @@ int main(int argc, char** argv) // set log levels // NOTE: this can also be done in a config file - algo_eventbuilder_filter.SetOption("log", "info"); - algo_sector_finder.SetOption("log", "info"); - algo_momentum_correction.SetOption("log", "info"); + algo_eventbuilder_filter.SetLogLevel("info"); + algo_sector_finder.SetLogLevel("info"); + algo_momentum_correction.SetLogLevel("info"); // set algorithm options // NOTE: this can also be done in a config file, but setting options here OVERRIDES config file settings + // WARNING: in practice, verify the configuration parameter was set the way you want; configuration parameter values + // are printed out for algorithms at the "debug" log level algo_eventbuilder_filter.SetOption>("pids", {11, 211, -211}); // start the algorithms diff --git a/examples/iguana_ex_cpp_01_action_functions.cc b/examples/iguana_ex_cpp_01_action_functions.cc index 11c1aaaa..f58e0d01 100644 --- a/examples/iguana_ex_cpp_01_action_functions.cc +++ b/examples/iguana_ex_cpp_01_action_functions.cc @@ -58,12 +58,14 @@ int main(int argc, char** argv) iguana::clas12::rga::MomentumCorrection algo_momentum_correction; // momentum corrections (a transformer algorithm) // set log levels - algo_eventbuilder_filter.SetOption("log", "info"); - algo_sector_finder.SetOption("log", "info"); - algo_momentum_correction.SetOption("log", "info"); + algo_eventbuilder_filter.SetLogLevel("info"); + algo_sector_finder.SetLogLevel("info"); + algo_momentum_correction.SetLogLevel("info"); // set algorithm options // NOTE: this can also be done in a config file + // WARNING: in practice, verify the configuration parameter was set the way you want; configuration parameter values + // are printed out for algorithms at the "debug" log level algo_eventbuilder_filter.SetOption>("pids", {11, 211, -211}); // start the algorithms diff --git a/src/iguana/algorithms/Algorithm.h b/src/iguana/algorithms/Algorithm.h index bce35bb4..4913926f 100644 --- a/src/iguana/algorithms/Algorithm.h +++ b/src/iguana/algorithms/Algorithm.h @@ -249,12 +249,6 @@ namespace iguana { /// @param level the log level void ShowBank(hipo::bank const& bank, std::string_view message = "", Logger::Level const level = Logger::trace) const; - /// Get an option from the option cache - /// @param key the key name associated with this option - /// @returns the option value, if found (using `std::optional`) - template - std::optional GetCachedOption(std::string const& key) const; - /// Throw a runtime exception since this algorithm has been renamed. /// Guidance will be printed for the user. /// @param new_name the new name of the algorithm @@ -263,6 +257,12 @@ namespace iguana { private: // methods + /// Get an option from the option cache + /// @param key the key name associated with this option + /// @returns the option value, if found (using `std::optional`) + template + std::optional GetCachedOption(std::string const& key) const; + // PrintOptionValue: overloaded for different value types void PrintOptionValue(std::string const& key, int const& val, Logger::Level const level = Logger::debug, std::string_view prefix = "OPTION") const; void PrintOptionValue(std::string const& key, double const& val, Logger::Level const level = Logger::debug, std::string_view prefix = "OPTION") const; diff --git a/src/iguana/algorithms/AlgorithmSequence.h b/src/iguana/algorithms/AlgorithmSequence.h index d4742540..b22cf501 100644 --- a/src/iguana/algorithms/AlgorithmSequence.h +++ b/src/iguana/algorithms/AlgorithmSequence.h @@ -119,6 +119,15 @@ namespace iguana { Get(algo_instance_name)->SetOption(key, val); } + /// @brief Set an algorithm log level + /// @see `Logger::Level` for available levels + /// @param algo_instance_name the algorithm instance name + /// @param lev the log level name + void SetLogLevel(std::string const& algo_instance_name, std::string const& lev) + { + Get(algo_instance_name)->SetLogLevel(lev); + } + /// Set the name of this sequence /// @param name the new name void SetName(std::string_view name); diff --git a/src/iguana/services/YAMLReader.cc b/src/iguana/services/YAMLReader.cc index 803826bb..8341322e 100644 --- a/src/iguana/services/YAMLReader.cc +++ b/src/iguana/services/YAMLReader.cc @@ -2,8 +2,6 @@ namespace iguana { - std::string YAMLReader::KEY_DELIM = "/"; - /////////////////////////////////////////////////////////////////////////////// void YAMLReader::LoadFiles() @@ -34,11 +32,25 @@ namespace iguana { tokens.push_back(arg); }; std::visit(node_id_visitor, node_path.front()); - return fmt::format("{}", fmt::join(tokens, KEY_DELIM)); + return fmt::format("{}", fmt::join(tokens, "/")); } /////////////////////////////////////////////////////////////////////////////// + // YAMLReader::node_path_t YAMLReader::String2NodePath(std::string const& str) + // { + // if(str.empty()) + // return {}; + // node_path_t node_path; + // std::istringstream stm(str); + // std::string tok; + // while(getline(stm, tok, '/')) // tokenize + // node_path.push_back(tok); + // return node_path; + // } + + /////////////////////////////////////////////////////////////////////////////// + template std::optional YAMLReader::GetScalar(YAML::Node node) { diff --git a/src/iguana/services/YAMLReader.h b/src/iguana/services/YAMLReader.h index 60274861..db806005 100644 --- a/src/iguana/services/YAMLReader.h +++ b/src/iguana/services/YAMLReader.h @@ -27,9 +27,6 @@ namespace iguana { /// Representation of a path of `YAML::Node`s in a `YAML::Node` tree, _e.g._, in a YAML file. using node_path_t = std::deque; - /// Delimiter for parameter key names - static std::string KEY_DELIM; - /// @param name of this reader (for `Logger`) YAMLReader(std::string_view name = "config") : ConfigFileReader(name) diff --git a/src/iguana/tests/include/TestAlgorithm.h b/src/iguana/tests/include/TestAlgorithm.h index b07bde1b..028d529a 100644 --- a/src/iguana/tests/include/TestAlgorithm.h +++ b/src/iguana/tests/include/TestAlgorithm.h @@ -40,7 +40,7 @@ inline int TestAlgorithm( seq.Add(algo_name); seq.SetName("TEST"); seq.PrintSequence(); - seq.SetOption(algo_name, "log", log_level); + seq.SetLogLevel(algo_name, log_level); // start the algorithm seq.Start(banks_after); diff --git a/src/iguana/tests/include/TestConfig.h b/src/iguana/tests/include/TestConfig.h index 8bb9be48..99df0ce5 100644 --- a/src/iguana/tests/include/TestConfig.h +++ b/src/iguana/tests/include/TestConfig.h @@ -22,7 +22,7 @@ inline int TestConfig(int test_num, std::string log_level) // then test configuring an algorithm auto algo = iguana::AlgorithmFactory::Create("example::ExampleAlgorithm"); - algo->SetOption("log", log_level); + algo->SetLogLevel(log_level); algo->SetConfigDirectory("src/iguana/tests"); // must be relative to build directory algo->SetConfigFile(fmt::format("test_{}.yaml", test_num)); algo->Start(); diff --git a/src/iguana/tests/include/TestMultithreading.h b/src/iguana/tests/include/TestMultithreading.h index 1c85beac..7b608a2b 100644 --- a/src/iguana/tests/include/TestMultithreading.h +++ b/src/iguana/tests/include/TestMultithreading.h @@ -94,7 +94,7 @@ inline int TestMultithreading( seq.Add(algo_name); seq.SetName("TEST thread " + std::to_string(order)); seq.PrintSequence(); - seq.SetOption(algo_name, "log", log_level); + seq.SetLogLevel(algo_name, log_level); // start the algorithm seq.Start(banks); diff --git a/src/iguana/tests/include/TestValidator.h b/src/iguana/tests/include/TestValidator.h index aa03b827..5d8ba182 100644 --- a/src/iguana/tests/include/TestValidator.h +++ b/src/iguana/tests/include/TestValidator.h @@ -34,7 +34,7 @@ inline int TestValidator( // define the validator auto vdor = iguana::AlgorithmFactory::Create(vdor_name); dynamic_cast(vdor.get())->SetOutputDirectory(output_dir); - vdor->SetOption("log", log_level); + vdor->SetLogLevel(log_level); // event loop vdor->Start(banks); From de22905f4b8f35e6851ad7dd07c87f4f23e6ba34 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Thu, 22 Jan 2026 19:20:48 -0500 Subject: [PATCH 04/10] fix: more renames --- src/iguana/services/Deprecated.cc | 37 +++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/iguana/services/Deprecated.cc b/src/iguana/services/Deprecated.cc index cfd351b0..b8d62950 100644 --- a/src/iguana/services/Deprecated.cc +++ b/src/iguana/services/Deprecated.cc @@ -9,13 +9,36 @@ namespace iguana::deprecated { { // clang-format off std::map> renames = { - { "physics::InclusiveKinematics", { - { "reconstruction", "method/reconstruction" }, - { "lepton_finder", "method/lepton_finder" }, - { "beam_particle", "method/beam_particle" }, - { "beam_direction", "initial_state/beam_direction" }, - { "target_particle", "initial_state/target_particle" }, - }, + { + "clas12::rga::FiducialFilterPass2", + { + { "calorimeter.strictness", "calorimeter/strictness" }, + { "forward_tagger.radius", "forward_tagger/radius" }, + { "forward_tagger.holes_flat", "forward_tagger/holes_flat" }, + { "cvt.edge_layers", "cvt/edge_layers" }, + { "cvt.edge_min", "cvt/edge_min" }, + { "cvt.phi_forbidden_deg", "cvt/phi_forbidden_deg" }, + { "dc.theta_small_deg", "dc/theta_small_deg" }, + { "dc.thresholds_out", "dc/thresholds_out" }, + { "dc.thresholds_in_smallTheta", "dc/thresholds_in_smallTheta" }, + { "dc.thresholds_in_largeTheta", "dc/thresholds_in_largeTheta" }, + } + }, + { + "clas12::ZVertexFilter", + { + {"electron_vz", "electron/vz"}, + } + }, + { + "physics::InclusiveKinematics", + { + { "reconstruction", "method/reconstruction" }, + { "lepton_finder", "method/lepton_finder" }, + { "beam_particle", "method/beam_particle" }, + { "beam_direction", "initial_state/beam_direction" }, + { "target_particle", "initial_state/target_particle" }, + } }, }; // clang-format on From 52cb87fbbd756e43266957e48206cf9b70b9875c Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Fri, 23 Jan 2026 12:12:20 -0500 Subject: [PATCH 05/10] fix: `SetOption` can't be used for data-dependent params --- doc/doxygen/mainpage.md | 4 +++- src/iguana/services/Deprecated.cc | 26 ++++++++++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/doc/doxygen/mainpage.md b/doc/doxygen/mainpage.md index bbcf3b76..d8e70056 100644 --- a/doc/doxygen/mainpage.md +++ b/doc/doxygen/mainpage.md @@ -243,7 +243,9 @@ Many algorithms are configurable. An algorithm's configuration parameters and th Iguana provides a few ways to configure algorithms; in general, you may either: - use YAML for configuration that gets applied at runtime, _i.e._, no need to recompile -- use @link iguana::Algorithm::SetOption @endlink to configure an algorithm more directly, which may require recompilation, depending on how you use Iguana algorithms +- use @link iguana::Algorithm::SetOption @endlink to configure an algorithm more directly, however: + - this may require recompilation, depending on how you use Iguana algorithms + - some options cannot be set this way, in particular, options that depend on data, such as a run number-dependent vertex cut The default configuration YAML files are installed in the `etc/` subdirectory of the Iguana installation. If you have set the Iguana environment variables using, _e.g._ `source this_iguana.sh`, or if you are using the version of Iguana installed on `ifarm`, you will have the environment variable `$IGUANA_CONFIG_PATH` set to include this `etc/` directory. diff --git a/src/iguana/services/Deprecated.cc b/src/iguana/services/Deprecated.cc index b8d62950..0a03c704 100644 --- a/src/iguana/services/Deprecated.cc +++ b/src/iguana/services/Deprecated.cc @@ -1,12 +1,32 @@ #include "Deprecated.h" +#include #include #include +#include namespace iguana::deprecated { void CheckSetOptionKey(std::string const& algo_class_name, std::string const& key) noexcept(false) { + // handle options which shouldn't be used with `SetOption` + // clang-format off + std::map> avoids = { + { + "clas12::ZVertexFilter", + { + "electron_vz", + } + }, + }; + //clang-format on + if(auto algo_it{avoids.find(algo_class_name)}; algo_it != avoids.end()) { + if(std::find(algo_it->second.begin(), algo_it->second.end(), key) != algo_it->second.end()) { + throw std::runtime_error("Called 'SetOption' with deprecated key '" + key + "'; use a configuration YAML file instead"); + } + } + + // handle renamed options // clang-format off std::map> renames = { { @@ -24,12 +44,6 @@ namespace iguana::deprecated { { "dc.thresholds_in_largeTheta", "dc/thresholds_in_largeTheta" }, } }, - { - "clas12::ZVertexFilter", - { - {"electron_vz", "electron/vz"}, - } - }, { "physics::InclusiveKinematics", { From 72d70f6a6031753e96c698abd179fc780839c28d Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Fri, 23 Jan 2026 19:07:59 -0500 Subject: [PATCH 06/10] fix: encourage config YAML in all examples --- .../iguana_ex_python_00_run_functions.py | 21 ++++++++--------- .../iguana_ex_python_01_action_functions.py | 17 ++++++++------ bind/python/iguana_ex_python_hipopy.py | 12 ++++------ examples/config/config.yaml | 9 ++++++++ examples/iguana_ex_cpp_00_run_functions.cc | 21 ++++++++--------- ...uana_ex_cpp_00_run_functions_with_banks.cc | 23 +++++++++---------- examples/iguana_ex_cpp_01_action_functions.cc | 20 ++++++++-------- examples/iguana_ex_cpp_dataframes.cc | 3 ++- 8 files changed, 67 insertions(+), 59 deletions(-) create mode 100644 examples/config/config.yaml diff --git a/bind/python/iguana_ex_python_00_run_functions.py b/bind/python/iguana_ex_python_00_run_functions.py index 3f9e5f37..5d82c332 100755 --- a/bind/python/iguana_ex_python_00_run_functions.py +++ b/bind/python/iguana_ex_python_00_run_functions.py @@ -42,17 +42,16 @@ seq.Add('clas12::rga::MomentumCorrection') # momentum corrections (a transformer algorithm) # seq.PrintSequence() -# set log levels -# NOTE: this can also be done in a config file -seq.SetLogLevel('clas12::EventBuilderFilter' 'info') -seq.SetLogLevel('clas12::SectorFinder' 'info') -seq.SetLogLevel('clas12::rga::MomentumCorrection' 'info') - -# set algorithm options -# NOTE: this can also be done in a config file, but setting options here OVERRIDES config file settings -# WARNING: in practice, verify the configuration parameter was set the way you want; configuration parameter values -# are printed out for algorithms at the "debug" log level -seq.SetOption('clas12::EventBuilderFilter', 'pids', [11, 211, -211]) +# configure algorithms with a custom YAML file +# - in practice you can put your config file(s) where you want +# - for this example, we use a YAML file installed alongside iguana (copied from `./config/config.yaml`) +config_file = iguana.ConfigFileReader.GetConfigInstallationPrefix() + '/examples/config.yaml' +# print the file name (so you can open it to see) +print(f'CONFIG FILE: {config_file}') +# use this configuration for all algorithms in the sequence +seq.SetConfigFileForEachAlgorithm(config_file) +# alternatively: use this configuration for the algorithm that needs it +# seq.Get("clas12::EventBuilderFilter").SetConfigFile(config_file) # start the algorithms seq.Start(banks) diff --git a/bind/python/iguana_ex_python_01_action_functions.py b/bind/python/iguana_ex_python_01_action_functions.py index aadae951..8d6c0b79 100755 --- a/bind/python/iguana_ex_python_01_action_functions.py +++ b/bind/python/iguana_ex_python_01_action_functions.py @@ -51,13 +51,16 @@ algo_sector_finder = iguana.clas12.SectorFinder() # get the sector for each particle (a creator algorithm) algo_momentum_correction = iguana.clas12.rga.MomentumCorrection() # momentum corrections (a transformer algorithm) -# set log levels -algo_eventbuilder_filter.SetLogLevel('info') -algo_sector_finder.SetLogLevel('info') -algo_momentum_correction.SetLogLevel('info') - -# set algorithm options -algo_eventbuilder_filter.SetOption('pids', [11, 211, -211]) +# configure algorithms with a custom YAML file +# - in practice you can put your config file(s) where you want +# - for this example, we use a YAML file installed alongside iguana (copied from `./config/config.yaml`) +config_file = iguana.ConfigFileReader.GetConfigInstallationPrefix() + '/examples/config.yaml' +# print the file name (so you can open it to see) +print(f'CONFIG FILE: {config_file}') +# use this configuration for each algorithm +algo_eventbuilder_filter.SetConfigFile(config_file) +algo_sector_finder.SetConfigFile(config_file) +algo_momentum_correction.SetConfigFile(config_file) # start the algorithms algo_eventbuilder_filter.Start() diff --git a/bind/python/iguana_ex_python_hipopy.py b/bind/python/iguana_ex_python_hipopy.py index 0172c215..e82cae70 100755 --- a/bind/python/iguana_ex_python_hipopy.py +++ b/bind/python/iguana_ex_python_hipopy.py @@ -44,13 +44,11 @@ algo_sector_finder = iguana.clas12.SectorFinder() # get the sector for each particle (a creator algorithm) algo_momentum_correction = iguana.clas12.rga.MomentumCorrection() # momentum corrections (a transformer algorithm) -# set log levels -algo_eventbuilder_filter.SetLogLevel('info') -algo_sector_finder.SetLogLevel('info') -algo_momentum_correction.SetLogLevel('info') - -# set algorithm options -algo_eventbuilder_filter.SetOption('pids', [11, 211, -211]) +# configure algorithms with a custom YAML file +config_file = iguana.ConfigFileReader.GetConfigInstallationPrefix() + '/examples/config.yaml' +algo_eventbuilder_filter.SetConfigFile(config_file) +algo_sector_finder.SetConfigFile(config_file) +algo_momentum_correction.SetConfigFile(config_file) # start the algorithms algo_eventbuilder_filter.Start() diff --git a/examples/config/config.yaml b/examples/config/config.yaml new file mode 100644 index 00000000..0f0d2f4b --- /dev/null +++ b/examples/config/config.yaml @@ -0,0 +1,9 @@ +clas12::EventBuilderFilter: + log: info # set the log level + pids: [ 11, 211, -211, 22 ] # customize the list of PDGs to filter for + +clas12::SectorFinder: + log: info + +clas12::rga::MomentumCorrection: + log: info diff --git a/examples/iguana_ex_cpp_00_run_functions.cc b/examples/iguana_ex_cpp_00_run_functions.cc index ceda54fd..12f5a855 100644 --- a/examples/iguana_ex_cpp_00_run_functions.cc +++ b/examples/iguana_ex_cpp_00_run_functions.cc @@ -47,17 +47,16 @@ int main(int argc, char** argv) seq.Add("clas12::rga::MomentumCorrection"); // momentum corrections (a transformer algorithm) // seq.PrintSequence(); - // set log levels - // NOTE: this can also be done in a config file - seq.SetLogLevel("clas12::EventBuilderFilter", "info"); - seq.SetLogLevel("clas12::SectorFinder", "info"); - seq.SetLogLevel("clas12::rga::MomentumCorrection", "info"); - - // set algorithm options - // NOTE: this can also be done in a config file, but setting options here OVERRIDES config file settings - // WARNING: in practice, verify the configuration parameter was set the way you want; configuration parameter values - // are printed out for algorithms at the "debug" log level - seq.SetOption>("clas12::EventBuilderFilter", "pids", {11, 211, -211}); + // configure algorithms with a custom YAML file + // - in practice you can put your config file(s) where you want + // - for this example, we use a YAML file installed alongside iguana (copied from `./config/config.yaml`) + auto config_file = iguana::ConfigFileReader::GetConfigInstallationPrefix() + "/examples/config.yaml"; + // print the file name (so you can open it to see) + fmt::println("CONFIG FILE: {}", config_file); + // use this configuration for all algorithms in the sequence + seq.SetConfigFileForEachAlgorithm(config_file); + // alternatively: use this configuration for the algorithm that needs it + // seq.Get("clas12::EventBuilderFilter")->SetConfigFile(config_file); // start the algorithms seq.Start(banks); diff --git a/examples/iguana_ex_cpp_00_run_functions_with_banks.cc b/examples/iguana_ex_cpp_00_run_functions_with_banks.cc index b14ee7ea..bfba8961 100644 --- a/examples/iguana_ex_cpp_00_run_functions_with_banks.cc +++ b/examples/iguana_ex_cpp_00_run_functions_with_banks.cc @@ -50,18 +50,17 @@ int main(int argc, char** argv) iguana::clas12::EventBuilderFilter algo_eventbuilder_filter; // filter by Event Builder PID (a filter algorithm) iguana::clas12::SectorFinder algo_sector_finder; // get the sector for each particle (a creator algorithm) iguana::clas12::rga::MomentumCorrection algo_momentum_correction; // momentum corrections (a transformer algorithm) - - // set log levels - // NOTE: this can also be done in a config file - algo_eventbuilder_filter.SetLogLevel("info"); - algo_sector_finder.SetLogLevel("info"); - algo_momentum_correction.SetLogLevel("info"); - - // set algorithm options - // NOTE: this can also be done in a config file, but setting options here OVERRIDES config file settings - // WARNING: in practice, verify the configuration parameter was set the way you want; configuration parameter values - // are printed out for algorithms at the "debug" log level - algo_eventbuilder_filter.SetOption>("pids", {11, 211, -211}); + // + // configure algorithms with a custom YAML file + // - in practice you can put your config file(s) where you want + // - for this example, we use a YAML file installed alongside iguana (copied from `./config/config.yaml`) + auto config_file = iguana::ConfigFileReader::GetConfigInstallationPrefix() + "/examples/config.yaml"; + // print the file name (so you can open it to see) + fmt::println("CONFIG FILE: {}", config_file); + // use this configuration for each algorithm + algo_eventbuilder_filter.SetConfigFile(config_file); + algo_sector_finder.SetConfigFile(config_file); + algo_momentum_correction.SetConfigFile(config_file); // start the algorithms algo_eventbuilder_filter.Start(); diff --git a/examples/iguana_ex_cpp_01_action_functions.cc b/examples/iguana_ex_cpp_01_action_functions.cc index f58e0d01..b61786ff 100644 --- a/examples/iguana_ex_cpp_01_action_functions.cc +++ b/examples/iguana_ex_cpp_01_action_functions.cc @@ -57,16 +57,16 @@ int main(int argc, char** argv) iguana::clas12::SectorFinder algo_sector_finder; // get the sector for each particle (a creator algorithm) iguana::clas12::rga::MomentumCorrection algo_momentum_correction; // momentum corrections (a transformer algorithm) - // set log levels - algo_eventbuilder_filter.SetLogLevel("info"); - algo_sector_finder.SetLogLevel("info"); - algo_momentum_correction.SetLogLevel("info"); - - // set algorithm options - // NOTE: this can also be done in a config file - // WARNING: in practice, verify the configuration parameter was set the way you want; configuration parameter values - // are printed out for algorithms at the "debug" log level - algo_eventbuilder_filter.SetOption>("pids", {11, 211, -211}); + // configure algorithms with a custom YAML file + // - in practice you can put your config file(s) where you want + // - for this example, we use a YAML file installed alongside iguana (copied from `./config/config.yaml`) + auto config_file = iguana::ConfigFileReader::GetConfigInstallationPrefix() + "/examples/config.yaml"; + // print the file name (so you can open it to see) + fmt::println("CONFIG FILE: {}", config_file); + // use this configuration for each algorithm + algo_eventbuilder_filter.SetConfigFile(config_file); + algo_sector_finder.SetConfigFile(config_file); + algo_momentum_correction.SetConfigFile(config_file); // start the algorithms algo_eventbuilder_filter.Start(); diff --git a/examples/iguana_ex_cpp_dataframes.cc b/examples/iguana_ex_cpp_dataframes.cc index b67ed321..0e73e2cb 100644 --- a/examples/iguana_ex_cpp_dataframes.cc +++ b/examples/iguana_ex_cpp_dataframes.cc @@ -33,7 +33,8 @@ int main(int argc, char** argv) // iguana algorithms iguana::clas12::EventBuilderFilter algo_eventbuilder_filter; - algo_eventbuilder_filter.SetOption>("pids", {11, 211, -211}); + auto config_file = iguana::ConfigFileReader::GetConfigInstallationPrefix() + "/examples/config.yaml"; + algo_eventbuilder_filter.SetConfigFile(config_file); algo_eventbuilder_filter.Start(); // enable interactive mode From 0c0725febd5db7dffe068d059b6ca2695eaab28d Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Fri, 23 Jan 2026 19:09:22 -0500 Subject: [PATCH 07/10] doc: note --- doc/doxygen/mainpage.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/doxygen/mainpage.md b/doc/doxygen/mainpage.md index d8e70056..86735178 100644 --- a/doc/doxygen/mainpage.md +++ b/doc/doxygen/mainpage.md @@ -246,6 +246,7 @@ Iguana provides a few ways to configure algorithms; in general, you may either: - use @link iguana::Algorithm::SetOption @endlink to configure an algorithm more directly, however: - this may require recompilation, depending on how you use Iguana algorithms - some options cannot be set this way, in particular, options that depend on data, such as a run number-dependent vertex cut + - using the YAML file is preferred in general The default configuration YAML files are installed in the `etc/` subdirectory of the Iguana installation. If you have set the Iguana environment variables using, _e.g._ `source this_iguana.sh`, or if you are using the version of Iguana installed on `ifarm`, you will have the environment variable `$IGUANA_CONFIG_PATH` set to include this `etc/` directory. From 752c631e23f154eb9d17709cffcd1403b77f7229 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Fri, 23 Jan 2026 19:17:14 -0500 Subject: [PATCH 08/10] fix: deprecations --- src/iguana/services/Deprecated.cc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/iguana/services/Deprecated.cc b/src/iguana/services/Deprecated.cc index 0a03c704..4fd2dffc 100644 --- a/src/iguana/services/Deprecated.cc +++ b/src/iguana/services/Deprecated.cc @@ -18,6 +18,13 @@ namespace iguana::deprecated { "electron_vz", } }, + { + "physics::InclusiveKinematics", + { + "beam_direction", + "target_particle", + } + }, }; //clang-format on if(auto algo_it{avoids.find(algo_class_name)}; algo_it != avoids.end()) { @@ -50,8 +57,6 @@ namespace iguana::deprecated { { "reconstruction", "method/reconstruction" }, { "lepton_finder", "method/lepton_finder" }, { "beam_particle", "method/beam_particle" }, - { "beam_direction", "initial_state/beam_direction" }, - { "target_particle", "initial_state/target_particle" }, } }, }; From fc7a078c0603b554b2f7614ea00d98d21a097212 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Fri, 23 Jan 2026 19:52:49 -0500 Subject: [PATCH 09/10] fix: broken `SetOption` --- src/iguana/algorithms/Algorithm.cc | 4 ++-- src/iguana/algorithms/clas12/SectorFinder/Validator.cc | 2 +- src/iguana/algorithms/clas12/ZVertexFilter/Validator.cc | 2 -- src/iguana/algorithms/clas12/ZVertexFilter/Validator.h | 7 ------- 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/iguana/algorithms/Algorithm.cc b/src/iguana/algorithms/Algorithm.cc index 295f164f..95f4d480 100644 --- a/src/iguana/algorithms/Algorithm.cc +++ b/src/iguana/algorithms/Algorithm.cc @@ -33,9 +33,9 @@ namespace iguana { template OPTION_TYPE Algorithm::GetOptionScalar(YAMLReader::node_path_t node_path) const { - node_path.push_front(m_class_name); auto key = YAMLReader::NodePath2String(node_path); auto opt = GetCachedOption(key); + node_path.push_front(m_class_name); if(!opt.has_value()) { opt = m_yaml_config->GetScalar(node_path); } @@ -55,9 +55,9 @@ namespace iguana { template std::vector Algorithm::GetOptionVector(YAMLReader::node_path_t node_path) const { - node_path.push_front(m_class_name); auto key = YAMLReader::NodePath2String(node_path); auto opt = GetCachedOption>(key); + node_path.push_front(m_class_name); if(!opt.has_value()) { opt = m_yaml_config->GetVector(node_path); } diff --git a/src/iguana/algorithms/clas12/SectorFinder/Validator.cc b/src/iguana/algorithms/clas12/SectorFinder/Validator.cc index 04cca4d3..a65317be 100644 --- a/src/iguana/algorithms/clas12/SectorFinder/Validator.cc +++ b/src/iguana/algorithms/clas12/SectorFinder/Validator.cc @@ -14,7 +14,7 @@ namespace iguana::clas12 { m_algo_seq->Add("clas12::SectorFinder"); m_algo_seq->SetOption>("clas12::EventBuilderFilter", "pids", u_pdg_list); m_algo_seq->SetOption("clas12::SectorFinder", "bank_charged", "REC::Track"); - m_algo_seq->SetOption("clas12::SectorFinder", "bank_uncharged", "default"); + m_algo_seq->SetOption("clas12::SectorFinder", "bank_neutral", "default"); m_algo_seq->Start(banks); diff --git a/src/iguana/algorithms/clas12/ZVertexFilter/Validator.cc b/src/iguana/algorithms/clas12/ZVertexFilter/Validator.cc index 130a0869..7db4458a 100644 --- a/src/iguana/algorithms/clas12/ZVertexFilter/Validator.cc +++ b/src/iguana/algorithms/clas12/ZVertexFilter/Validator.cc @@ -12,8 +12,6 @@ namespace iguana::clas12 { // define the algorithm sequence m_algo_seq = std::make_unique(); m_algo_seq->Add("clas12::ZVertexFilter"); - m_algo_seq->SetOption>("clas12::ZVertexFilter", "pids", u_pdgtocut_list); - m_algo_seq->SetOption>("clas12::ZVertexFilter", "cuts", u_cuts_list); m_algo_seq->Start(banks); // get bank indices diff --git a/src/iguana/algorithms/clas12/ZVertexFilter/Validator.h b/src/iguana/algorithms/clas12/ZVertexFilter/Validator.h index e3375df3..101be6e1 100644 --- a/src/iguana/algorithms/clas12/ZVertexFilter/Validator.h +++ b/src/iguana/algorithms/clas12/ZVertexFilter/Validator.h @@ -33,13 +33,6 @@ namespace iguana::clas12 { particle::PDG::proton, particle::PDG::neutron}; - std::vector const u_pdgtocut_list = { - particle::PDG::electron}; - - std::vector const u_cuts_list = { - -5, - 5}; - TString m_output_file_basename; TFile* m_output_file; mutable std::unordered_map> u_zvertexplots; From dcec7151b96c33e4becc4eefc95b019406b3bd79 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Fri, 23 Jan 2026 19:58:09 -0500 Subject: [PATCH 10/10] fix: cleanup --- src/iguana/services/YAMLReader.cc | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/iguana/services/YAMLReader.cc b/src/iguana/services/YAMLReader.cc index 8341322e..5926bbeb 100644 --- a/src/iguana/services/YAMLReader.cc +++ b/src/iguana/services/YAMLReader.cc @@ -2,8 +2,6 @@ namespace iguana { - /////////////////////////////////////////////////////////////////////////////// - void YAMLReader::LoadFiles() { m_log->Debug("YAMLReader::LoadFiles():"); @@ -20,6 +18,7 @@ namespace iguana { } } } + /////////////////////////////////////////////////////////////////////////////// std::string YAMLReader::NodePath2String(node_path_t const& node_path) @@ -37,20 +36,6 @@ namespace iguana { /////////////////////////////////////////////////////////////////////////////// - // YAMLReader::node_path_t YAMLReader::String2NodePath(std::string const& str) - // { - // if(str.empty()) - // return {}; - // node_path_t node_path; - // std::istringstream stm(str); - // std::string tok; - // while(getline(stm, tok, '/')) // tokenize - // node_path.push_back(tok); - // return node_path; - // } - - /////////////////////////////////////////////////////////////////////////////// - template std::optional YAMLReader::GetScalar(YAML::Node node) {