5 #include "boost/algorithm/string.hpp" 10 #include <initializer_list> 15 using namespace fhicl;
21 using modules_t = std::map<std::string, std::string>;
26 std::string const trigger_paths_str{
"trigger_paths"};
31 std::regex
const path_spec_re{R
"((\d+:)?)" + path_name}; 32 return std::regex_match(path_spec_str, path_spec_re);
35 auto module_tables = {
"physics.producers",
39 auto modifier_tables = {
"physics.producers",
"physics.filters"};
40 auto observer_tables = {
"physics.analyzers",
"outputs"};
42 auto allowed_physics_tables = {
"producers",
"filters",
"analyzers"};
53 path_exception(
std::string const& selection_override,
59 msg +=
" (i.e. '" + suffix +
"'):";
60 return config_exception(
msg);
67 case ModuleCategory::modifier:
70 case ModuleCategory::observer:
73 case ModuleCategory::unset:
82 auto result = ModuleCategory::unset;
84 case ModuleCategory::modifier:
85 result = ModuleCategory::observer;
87 case ModuleCategory::observer:
88 result = ModuleCategory::modifier;
90 case ModuleCategory::unset: {
92 <<
"The " << cat <<
" category has no opposite.\n";
104 full_module_key.substr(0, full_module_key.find_last_of(
'.'));
106 return ModuleCategory::modifier;
109 return ModuleCategory::observer;
111 return ModuleCategory::unset;
115 is_path_selection_override(
std::string const& path_name)
117 return path_name == trigger_paths_str or path_name == end_paths_str;
124 case ModuleCategory::modifier:
125 return trigger_paths_str;
126 case ModuleCategory::observer:
127 return end_paths_str;
137 std::initializer_list<char const*> tables)
140 for (
auto const tbl : tables) {
144 for (
auto const& [modname,
value] : table) {
152 auto const [it, success] = result.try_emplace(modname,
fhicl_key(
key));
153 if (!success && it->second !=
key) {
154 auto const& cached_key = it->second;
156 cached_key.substr(0, cached_key.rfind(modname) - 1);
157 throw config_exception(
"An error occurred while processing " 158 "module configurations.")
159 <<
"Module label '" << modname <<
"' has been used in '" << tbl
160 <<
"' and '" <<
parent <<
"'.\n" 161 <<
"Module labels must be unique across an art process.\n";
171 std::vector<ModuleSpec>
174 std::vector<ModuleSpec>
result;
175 for (
auto const& ev : seq) {
176 if (allow_nil_entries and ev.is_a(
NIL)) {
183 auto mod_spec = ev.to_string();
184 if (
empty(mod_spec)) {
189 if (mod_spec[0] ==
'!') {
190 action = FilterAction::Veto;
191 mod_spec = mod_spec.substr(1);
192 }
else if (mod_spec[0] ==
'-') {
193 action = FilterAction::Ignore;
194 mod_spec = mod_spec.substr(1);
198 if (mod_spec.find_first_of(
"!-") != std::string::npos) {
199 throw config_exception(
"There was an error parsing the entry "s +
200 ev.to_string() +
"in a FHiCL sequence.")
201 <<
"The '!' or '-' character may appear as only the first character " 202 "in the path entry.\n";
204 result.push_back({mod_spec,
action});
207 if (result.size() != seq.size()) {
208 throw config_exception(
"There was an error parsing the specified entries " 209 "in a FHiCL sequence.")
210 <<
"One of the presented elements is either an empty string or not a " 216 std::vector<art::PathSpec>
217 path_specs(std::vector<ModuleSpec>
const& selection_override_entries,
223 std::ostringstream oss;
224 oss <<
"If you would like to repeat the path specification, all " 225 "path specifications\n" 227 << name <<
"' must be prepended with the same path ID (e.g.):\n\n" 228 <<
" " << path_selection_override <<
": ['" << id_str <<
':' << name
229 <<
"', '" << id_str <<
':' << name <<
"', ...]\n\n";
233 std::map<PathID, std::string> id_to_name;
234 std::map<std::string, PathID> name_to_id;
235 std::vector<art::PathSpec>
result;
238 for (
auto it =
cbegin(selection_override_entries),
239 e =
cend(selection_override_entries);
242 auto const& path = *it;
244 if (spec.name == at_nil) {
249 auto const emplacement_result =
250 name_to_id.try_emplace(spec.name, spec.path_id);
251 bool const name_already_present = not emplacement_result.second;
252 auto const emplaced_path_id = emplacement_result.first->second;
254 if (name_already_present) {
256 throw path_exception(path_selection_override, i, path.name)
257 <<
"The path name '" << spec.name
258 <<
"' has already been specified in the " << path_selection_override
260 << guidance(spec.name,
261 path_selection_override,
264 if (spec.path_id != emplaced_path_id) {
265 throw path_exception(path_selection_override, i, path.name)
266 <<
"The path name '" << spec.name
267 <<
"' has already been specified (perhaps implicitly) with a\n" 269 <<
to_string(emplaced_path_id) <<
" (not " 270 <<
to_string(spec.path_id) <<
") in the " << path_selection_override
272 << guidance(spec.name,
273 path_selection_override,
284 emplacement_result.first->second = spec.path_id;
288 if (
auto const [it, inserted] =
289 id_to_name.try_emplace(spec.path_id, spec.name);
291 throw path_exception(path_selection_override, i, path.name)
293 <<
" cannot be assigned to path name '" << spec.name
294 <<
"' as it has already been assigned to path name '" << it->second
306 verify_supported_names(
table_t const& physics_table)
309 for (
auto const& [
name,
value] : physics_table) {
319 bad_names +=
" \"physics." +
name +
"\" (" + type +
")\n";
322 if (
empty(bad_names)) {
326 throw config_exception(
327 "\nYou have specified the following unsupported parameters in the\n" 328 "\"physics\" block of your configuration:\n")
330 <<
"\nSupported parameters include the following tables:\n" 331 " \"physics.producers\"\n" 332 " \"physics.filters\"\n" 333 " \"physics.analyzers\"\n" 334 "and sequences. Atomic configuration parameters are not " 340 std::set<std::string>
const& empty_paths,
347 for (
auto const&
name : empty_paths) {
348 std::replace_if(
begin(result),
350 [&
name](
auto const& ex_val) {
351 if (not ex_val.is_a(
STRING)) {
370 std::set<std::string> empty_paths;
371 std::map<std::string, std::vector<ModuleSpec>> paths;
373 verify_supported_names(table);
374 for (
auto const& [path_name, module_names] : table) {
379 if (
empty(entries)) {
380 empty_paths.insert(path_name);
383 module_names, is_path_selection_override(path_name));
388 config, empty_paths,
fhicl_key(physics, trigger_paths_str));
389 replace_empty_paths(config, empty_paths,
fhicl_key(physics, end_paths_str));
408 for (
auto const& [path_name, entries] : all_paths) {
410 if (is_path_selection_override(path_name)) {
413 std::vector<ModuleSpec> right_modules;
414 std::vector<std::string> wrong_modules;
415 for (
auto const& mod_spec : entries) {
416 auto const&
name = mod_spec.name;
417 auto full_module_key_it = modules.
find(
name);
418 if (full_module_key_it ==
cend(modules)) {
419 throw config_exception(
"The following error occurred while " 420 "processing a path configuration:")
421 <<
"Entry with name " <<
name <<
" in path " << path_name
422 <<
" does not have a module configuration.\n";
424 auto const& full_module_key = full_module_key_it->second;
425 auto const module_cat = module_category(full_module_key);
426 assert(module_cat != ModuleCategory::unset);
427 if (module_cat == category) {
428 right_modules.push_back(mod_spec);
430 wrong_modules.push_back(
name);
434 if (right_modules.empty()) {
441 if (right_modules.size() == entries.size()) {
442 sorted_result.try_emplace(path_name,
move(right_modules));
446 auto e = config_exception(
"An error occurred while " 447 "processing a path configuration.");
448 e <<
"The following modules specified in path " << path_name <<
" are " 449 << opposite(category)
452 << category <<
"s:\n";
453 for (
auto const& modname : wrong_modules) {
454 e <<
" '" << modname <<
"'\n";
463 for (
auto const& [path_name, modules] : sorted_result) {
471 std::vector<ModuleSpec>
const& override_entries,
480 std::ostringstream os;
481 for (
auto& spec : specs) {
482 auto res = modules_for_path.
find(spec.name);
483 if (res ==
cend(modules_for_path)) {
484 os <<
"Unknown path " << spec.name <<
" has been specified in '" 485 << path_selection_override <<
"'.\n";
490 if (
empty(res->second)) {
495 for (
auto const&
entry : res->second) {
497 auto full_module_key_it = modules.
find(
name);
498 if (full_module_key_it ==
cend(modules)) {
499 throw config_exception(
"The following error occurred while " 500 "processing a path configuration:")
501 <<
"Entry with name " <<
name <<
" in path " << spec.name
502 <<
" does not have a module configuration.\n";
505 result.emplace_back(
std::move(spec), res->second);
508 auto const err = os.str();
510 throw config_exception(
511 "The following error occurred while processing path configurations:")
519 get_enabled_modules(
modules_t const& modules,
524 for (
auto const& [
path_spec, entries] : enabled_paths) {
525 for (
auto const& [module_name,
action] : entries) {
526 auto const& module_key = modules.
at(module_name);
527 auto const actual_category = module_category(module_key);
529 if (actual_category != category) {
530 throw config_exception(
"The following error occurred while " 531 "processing a path configuration:")
532 <<
"The '" << path_selection_override(category)
533 <<
"' override parameter contains the path " <<
path_spec.
name 535 << (actual_category == ModuleCategory::observer ?
" an\n" :
" a\n")
536 <<
to_string(
type) <<
" with the name " << module_name <<
".\n\n" 538 <<
" should instead be included as part of the '" 539 << path_selection_override(opposite(category)) <<
"' parameter.\n" 540 <<
"Contact artists@fnal.gov for guidance.\n";
544 throw config_exception(
"The following error occurred while " 545 "processing a path configuration:")
546 <<
"Entry with name " << module_name <<
" in path " 548 << (category == ModuleCategory::observer ?
" an " :
" a ")
549 <<
to_string(
type) <<
" and cannot have a '!' or '-' prefix.\n";
557 std::pair<module_entries_for_ordered_path_t, bool>
562 auto const selection_override = path_selection_override(category);
563 auto const it = paths.find(selection_override);
564 if (it ==
cend(paths)) {
565 return {paths_for_category(paths, modules, category),
false};
569 explicitly_declared_paths(paths, it->second, modules, selection_override),
576 bool const report_enabled,
579 auto const modules = declared_modules(config, module_tables);
581 auto paths = all_paths(config);
583 auto [trigger_paths, trigger_paths_override] =
584 enabled_paths(paths, modules, ModuleCategory::modifier);
585 auto [end_paths, end_paths_override] =
586 enabled_paths(paths, modules, ModuleCategory::observer);
588 auto enabled_modules =
589 get_enabled_modules(modules, trigger_paths, ModuleCategory::modifier);
593 auto end_path_enabled_modules =
594 get_enabled_modules(modules, end_paths, ModuleCategory::observer);
595 enabled_modules.insert(
begin(end_path_enabled_modules),
596 end(end_path_enabled_modules));
599 for (
auto const& pr : modules) {
600 if (enabled_modules.find(pr.first) ==
cend(enabled_modules)) {
601 unused_modules.insert(pr);
606 paths.erase(
"trigger_paths");
607 paths.erase(
"end_paths");
608 for (
auto const& pr : trigger_paths) {
609 paths.erase(pr.first.name);
611 for (
auto const& pr : end_paths) {
612 paths.erase(pr.first.name);
616 if (report_enabled && !
empty(paths)) {
617 std::cerr <<
"The following paths have not been enabled for execution and " 618 "will be ignored:\n";
619 for (
auto const& pr : paths) {
620 std::cerr <<
" " << pr.first <<
'\n';
624 if (report_enabled && !
empty(unused_modules)) {
625 std::ostringstream os;
626 os <<
"The following module label" 627 << ((unused_modules.size() == 1) ?
" is" :
"s are")
628 <<
" either not assigned to any path,\n" 629 <<
"or " << ((unused_modules.size() == 1ull) ?
"it has" :
"they have")
630 <<
" been assigned to ignored path(s):\n";
631 for (
auto const& pr : unused_modules) {
632 os <<
" " << pr.first <<
'\n';
634 std::cerr << os.str();
638 for (
auto const& pr : paths) {
641 for (
auto const& pr : unused_modules) {
642 config.
erase(pr.second);
646 for (
auto const& table_name : module_tables) {
651 config.
erase(table_name);
658 config.
erase(
"physics");
664 if (trigger_paths_override) {
665 std::vector<std::string> explicit_entries;
667 back_inserter(explicit_entries),
668 [](
auto const& pr) {
return to_string(pr.first); });
669 config.
put(
"trigger_paths.trigger_paths", explicit_entries);
675 trigger_paths_override,
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
static void replace_all(std::string &str, const std::string &old, const std::string &repl)
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
bool exists_outside_prolog(fhicl::intermediate_table const &config, std::string const &key)
void msg(const char *fmt,...)
std::vector< ModuleSpec > sequence_to_entries(sequence_t const &seq, bool const allow_nil_entries)
std::map< std::string, ModuleKeyAndType > keytype_for_name_t
ModuleType module_type(std::string const &full_key)
std::map< std::string, std::vector< ModuleSpec >> module_entries_for_path_t
int find(char c, int index=0, bool cs=TRUE) const
int find(const type *d) const
std::string to_string(Protection p)
void decode(std::any const &, std::string &)
std::map< std::string, std::string > modules_t
EnabledModules prune_config_if_enabled(bool prune_config, bool report_enabled, fhicl::intermediate_table &config)
bool search_all(FwdCont const &, Datum const &)
std::enable_if_t< std::is_convertible_v< T, std::string >, std::string > fhicl_key(T const &name)
std::vector< extended_value > sequence_t
shims::map< std::string, extended_value > table_t
auto transform_all(Container &, OutputIt, UnaryOp)
void err(const char *fmt,...)
fhicl::extended_value::sequence_t sequence_t
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
constexpr static auto invalid() noexcept
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
bool is_table(par_type const pt)
PathSpec path_spec(std::string const &path_spec)
std::vector< art::PathSpec > path_specs(std::vector< ModuleSpec > const &selection_override_entries, std::string const &path_selection_override)
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
std::ostream & operator<<(std::ostream &, ParameterSetID const &)
std::string to_string(ModuleType const mt)
def parent(G, child, parent_type)
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
std::vector< std::pair< PathSpec, std::vector< ModuleSpec >>> module_entries_for_ordered_path_t