LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
EventSelector.cc
Go to the documentation of this file.
2 // vim: set sw=2 expandtab :
3 
9 #include "cetlib/container_algorithms.h"
10 #include "fhiclcpp/ParameterSet.h"
14 #include "range/v3/view.hpp"
15 
16 #include <algorithm>
17 #include <cassert>
18 #include <string>
19 #include <vector>
20 
21 using namespace art;
22 using namespace cet;
23 using namespace std;
24 
26 
27 namespace {
28  unsigned int
29  path_position(vector<string> const& trigger_path_names,
31  {
32  return distance(trigger_path_names.begin(), it);
33  }
34 
35  bool
36  remove_noexception(std::string const& full_path_specifier,
37  std::string& specifier)
38  {
39  string const noexLiteral{"&noexception"};
40  auto const noexception_pos = specifier.find(noexLiteral);
41  if (noexception_pos == string::npos) {
42  return false;
43  }
44 
45  if ((noexception_pos + noexLiteral.length()) < specifier.length()) {
47  << "EventSelector::init, A module is using SelectEvents\n"
48  << "to request a trigger name that has extra characters after "
49  "'&noexception'.\n"
50  << "The improper trigger name is: " << full_path_specifier << '\n';
51  }
52  specifier.erase(noexception_pos);
53  return true;
54  }
55 
56  bool
57  remove_negation(std::string& specifier)
58  {
59  if (specifier[0] != '!') {
60  return false;
61  }
62  specifier.erase(0, 1);
63  return true;
64  }
65 
66  bool
67  remove_exception(std::string const& full_path_specifier,
68  std::string& specifier)
69  {
70  // Remove "exception@"
71  string const exLiteral{"exception@"};
72  auto const pos = specifier.find(exLiteral);
73  if (pos == 0) {
74  specifier.erase(0, exLiteral.length());
75  return true;
76  }
77 
78  // Any other non-npos position is illegal.
79  if (pos != string::npos) {
81  << "EventSelector::init, A module is using SelectEvents\n"
82  << "to request a trigger name that has disallowed characters before "
83  "'exception@'.\n"
84  << "The improper trigger name is: " << full_path_specifier << '\n';
85  }
86  return false;
87  }
88 
89  // Indicate if any bit in the trigger results matches the desired value
90  // at that position, based on the bits array. If s is Exception, this
91  // looks for a Exceptionmatch; otherwise, true-->Pass, false-->Fail.
92  bool
93  any_bit(vector<BitInfo> const& bits,
94  HLTGlobalStatus const& tr,
95  hlt::HLTState const s = hlt::Ready)
96  {
97  bool const check_for_exception = (s == hlt::Exception);
98  return std::any_of(
99  begin(bits), end(bits), [check_for_exception, &tr](auto const& b) {
100  hlt::HLTState const bstate = check_for_exception ? hlt::Exception :
101  b.accept_state ? hlt::Pass :
102  hlt::Fail;
103  return tr.at(b.pos).state() == bstate;
104  });
105  }
106 
107  // Indicate if *every* bit in the trigger results matches the desired value
108  // at that position, based on the bits array: true-->Pass, false-->Fail.
109  bool
110  all_bits(vector<BitInfo> const& bits, HLTGlobalStatus const& tr)
111  {
112  return std::all_of(begin(bits), end(bits), [&tr](auto const& b) {
113  hlt::HLTState const bstate = b.accept_state ? hlt::Pass : hlt::Fail;
114  return tr.at(b.pos).state() == bstate;
115  });
116  }
117 
118  bool
119  accept_all(vector<string> const& path_specs)
120  {
121  if (empty(path_specs)) {
122  return true;
123  }
124 
125  // The following are for the purpose of establishing accept_all_ by
126  // virtue of an inclusive set of paths.
127  bool unrestricted_star = false;
128  bool negated_star = false;
129  bool exception_star = false;
130 
131  for (string const& pathSpecifier : path_specs) {
132  assert(not art::detail::has_whitespace(pathSpecifier));
133 
134  if (pathSpecifier == "*") {
135  unrestricted_star = true;
136  } else if (pathSpecifier == "!*") {
137  negated_star = true;
138  } else if (pathSpecifier == "exception@*") {
139  exception_star = true;
140  }
141  }
142  return unrestricted_star && negated_star && exception_star;
143  }
144 }
145 
146 namespace art {
147 
148  EventSelector::EventSelector(vector<string> const& pathspecs)
149  : path_specs_{pathspecs}, accept_all_{accept_all(path_specs_)}
150  {
151  acceptors_.expand_to_num_schedules();
152  }
153 
156  EventSelector::~EventSelector() = default;
157 
158  // This should be called per new file.
161  {
162  fhicl::ParameterSet pset;
164  // This should never happen
166  << "EventSelector::acceptEvent cannot find the trigger names for\n"
167  << "a process for which the configuration has requested that the\n"
168  << "OutputModule use TriggerResults to select events from. This "
169  "should\n"
170  << "be impossible, please send information to reproduce this problem "
171  "to\n"
172  << "the art developers at artists@fnal.gov.\n";
173  }
174  auto const trigger_path_specs =
175  pset.get<vector<string>>("trigger_paths", {});
176  if (trigger_path_specs.size() != tr.size()) {
178  << "EventSelector::acceptEvent: Trigger names vector and\n"
179  << "TriggerResults are different sizes. This should be impossible,\n"
180  << "please send information to reproduce this problem to\n"
181  << "the art developers.\n";
182  }
183 
184  std::vector<BitInfo> absolute_acceptors;
185  std::vector<BitInfo> conditional_acceptors;
186  std::vector<BitInfo> exception_acceptors;
187  std::vector<std::vector<BitInfo>> all_must_fail;
188  std::vector<std::vector<BitInfo>> all_must_fail_noex;
189 
190  for (string const& pathSpecifier : path_specs_) {
191  string specifier{pathSpecifier};
192 
193  bool const noex_demanded = remove_noexception(pathSpecifier, specifier);
194  bool const negative_criterion = remove_negation(specifier);
195  bool const exception_spec = remove_exception(pathSpecifier, specifier);
196 
197  if (negative_criterion && exception_spec) {
199  << "EventSelector::init, A module is using SelectEvents\n"
200  << "to request a trigger name starting with !exception@.\n"
201  << "This is not supported.\n"
202  << "The improper trigger name is: " << pathSpecifier << '\n';
203  }
204 
205  if (noex_demanded && exception_spec) {
207  << "EventSelector::init, A module is using SelectEvents\n"
208  << "to request a trigger name starting with exception@ "
209  << "and also demanding &noexception.\n"
210  << "The improper trigger name is: " << pathSpecifier << '\n';
211  }
212 
213  // instead of "see if the name can be found in the full list of
214  // paths" we want to find all paths that match this name.
215  //
216  // 'specifier' now corresponds to the real trigger-path name,
217  // free of any decorations.
218  string const& realname{specifier};
219  auto const matches = regexMatch(trigger_path_specs, realname);
220  if (matches.empty()) {
221  if (is_glob(realname)) {
222  mf::LogWarning("Configuration")
223  << "EventSelector::init, A module is using SelectEvents\n"
224  "to request a wildcarded trigger name that does not match any "
225  "trigger.\n"
226  "The wildcarded trigger name is: "
227  << realname
228  << " (from trigger-path specification: " << pathSpecifier << ")";
229  } else {
231  << "EventSelector::init, A module is using SelectEvents\n"
232  "to request a trigger name that does not exist.\n"
233  "The unknown trigger name is: "
234  << realname
235  << " (from trigger-path specification: " << pathSpecifier << ") \n";
236  }
237  }
238 
239  auto makeBitInfoPass = [&trigger_path_specs](auto m) {
240  return BitInfo{path_position(trigger_path_specs, m), true};
241  };
242  auto makeBitInfoFail = [&trigger_path_specs](auto m) {
243  return BitInfo{path_position(trigger_path_specs, m), false};
244  };
245 
246  if (!negative_criterion && !noex_demanded && !exception_spec) {
247  cet::transform_all(
248  matches, back_inserter(absolute_acceptors), makeBitInfoPass);
249  continue;
250  }
251 
252  if (!negative_criterion && noex_demanded) {
253  cet::transform_all(
254  matches, back_inserter(conditional_acceptors), makeBitInfoPass);
255  continue;
256  }
257 
258  if (exception_spec) {
259  cet::transform_all(
260  matches, back_inserter(exception_acceptors), makeBitInfoPass);
261  continue;
262  }
263 
264  if (negative_criterion && !noex_demanded) {
265  if (matches.empty()) {
267  << "EventSelector::init, A module is using SelectEvents\n"
268  "to request all fails on a set of trigger names that do not "
269  "exist\n"
270  << "The problematic name is: " << pathSpecifier << '\n';
271  }
272 
273  if (matches.size() == 1) {
274  BitInfo bi{path_position(trigger_path_specs, matches[0]), false};
275  absolute_acceptors.push_back(bi);
276  } else {
277  // We set this to false because that will demand bits are Fail.
278  auto must_fail = matches |
279  ::ranges::views::transform(makeBitInfoFail) |
280  ::ranges::to_vector;
281  all_must_fail.push_back(std::move(must_fail));
282  }
283  continue;
284  }
285 
286  if (negative_criterion && noex_demanded) {
287  if (matches.empty()) {
289  << "EventSelector::init, A module is using SelectEvents\n"
290  "to request all fails on a set of trigger names that do not "
291  "exist\n"
292  << "The problematic name is: " << pathSpecifier << '\n';
293  }
294 
295  if (matches.size() == 1) {
296  BitInfo bi{path_position(trigger_path_specs, matches[0]), false};
297  conditional_acceptors.push_back(bi);
298  } else {
299  auto must_fail = matches |
300  ::ranges::views::transform(makeBitInfoFail) |
301  ::ranges::to_vector;
302  all_must_fail_noex.push_back(std::move(must_fail));
303  }
304  }
305  }
306  return ScheduleData{tr.parameterSetID(),
307  absolute_acceptors,
308  conditional_acceptors,
309  exception_acceptors,
310  all_must_fail,
311  all_must_fail_noex};
312  }
313 
314  bool
316  TriggerResults const& tr) const
317  {
318  if (accept_all_) {
319  return true;
320  }
321 
322  auto& data = acceptors_.at(id);
323  if (data.psetID != tr.parameterSetID()) {
324  data = data_for(tr);
325  }
326  return selectionDecision(data, tr);
327  }
328 
329  bool
331  HLTGlobalStatus const& tr) const
332  {
333  if (accept_all_) {
334  return true;
335  }
336 
337  if (any_bit(data.absolute_acceptors, tr)) {
338  return true;
339  }
340 
341  bool exceptionPresent = false;
342  bool exceptionsLookedFor = false;
343  if (any_bit(data.conditional_acceptors, tr)) {
344  exceptionPresent = tr.error();
345  if (!exceptionPresent) {
346  return true;
347  }
348  exceptionsLookedFor = true;
349  }
350 
351  if (any_bit(data.exception_acceptors, tr, hlt::Exception)) {
352  return true;
353  }
354 
355  for (auto const& f : data.all_must_fail) {
356  if (all_bits(f, tr)) {
357  return true;
358  }
359  }
360 
361  for (auto const& fn : data.all_must_fail_noex) {
362  if (all_bits(fn, tr)) {
363  if (!exceptionsLookedFor) {
364  exceptionPresent = tr.error();
365  }
366  return !exceptionPresent;
367  }
368  }
369  return false;
370  }
371 
372 } // namespace art
std::vector< std::string > const path_specs_
Definition: EventSelector.h:29
PerScheduleContainer< ScheduleData > acceptors_
Definition: EventSelector.h:39
static collection_type const & get() noexcept
STL namespace.
intermediate_table::const_iterator const_iterator
std::vector< std::vector< std::string >::const_iterator > regexMatch(std::vector< std::string > const &strings, std::string const &pattern)
Definition: RegexMatch.cc:25
HLTState
Definition: HLTenums.h:6
std::vector< BitInfo > conditional_acceptors
Definition: EventSelector.h:34
TFile f
Definition: plotHisto.C:6
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
fhicl::ParameterSetID const & parameterSetID() const
std::vector< std::vector< BitInfo > > all_must_fail_noex
Definition: EventSelector.h:37
std::vector< PathSpec > path_specs(std::vector< std::string > const &path_spec_strs)
Definition: PathSpec.cc:34
bool acceptEvent(ScheduleID id, TriggerResults const &tr) const
T get(std::string const &key) const
Definition: ParameterSet.h:314
std::vector< BitInfo > absolute_acceptors
Definition: EventSelector.h:33
bool has_whitespace(std::string const &str)
bool const accept_all_
Definition: EventSelector.h:30
std::vector< std::vector< BitInfo > > all_must_fail
Definition: EventSelector.h:36
std::size_t size() const
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
HLTPathStatus const & at(unsigned const i) const
ScheduleData data_for(TriggerResults const &tr) const
bool selectionDecision(ScheduleData const &data, HLTGlobalStatus const &) const
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
Definition: MVAAlg.h:12
EventSelector::BitInfo BitInfo
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
hlt::HLTState state() const
std::vector< BitInfo > exception_acceptors
Definition: EventSelector.h:35
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:109
bool is_glob(std::string const &pattern)
Definition: RegexMatch.cc:11
EventSelector(std::vector< std::string > const &pathspecs)