LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
Selector.h
Go to the documentation of this file.
1 #ifndef art_Framework_Principal_Selector_h
2 #define art_Framework_Principal_Selector_h
3 // vim: set sw=2 expandtab :
4 
5 // =====================================================================
6 // Classes for all "selector" objects, used to select EDProducts based
7 // on information in the associated Provenance.
8 //
9 // Users can use the classes defined below
10 //
11 // InputTagListSelector
12 // ModuleLabelSelector
13 // ProcessNameSelector
14 // ProductInstanceNameSelector
15 // SelectorByFunction
16 //
17 // Users can also use the class Selector, which can be constructed
18 // given a logical expression formed from any other selectors,
19 // combined with && (the AND operator), || (the OR operator) or ! (the
20 // NOT operator).
21 //
22 // For example, to select only products produced by a module with
23 // label "mymodule" and made in the process "PROD", one can use:
24 //
25 // Selector s{ModuleLabelSelector("mymodule") &&
26 // ProcessNameSelector("PROD")};
27 //
28 // If a module (EDProducter, EDFilter, EDAnalyzer, or OutputModule) is
29 // to use such a selector, it is best to initialize it directly upon
30 // construction of the module, rather than creating a new Selector
31 // instance for every event.
32 // =====================================================================
33 
36 
37 #include <functional>
38 #include <memory>
39 #include <string>
40 #include <type_traits>
41 
42 namespace art {
43  template <typename T>
44  constexpr bool is_selector =
45  std::is_base_of_v<SelectorBase, std::remove_reference_t<T>>;
46 
47  //--------------------------------------------------------------------
48  // Class ProcessNameSelector.
49  // Selects EDProducts based upon process name.
50  //
51  // As a special case, a ProcessNameSelector created with the string
52  // "*" matches *any* process (and so is rather like having no
53  // ProcessNameSelector at all). The ProcessNameSelector does *not*
54  // understand the string "current_process" as a match to the current
55  // process name. To do so with the current design would require the
56  // use of accessing global data, which we would like to avoid. If
57  // such matching is desired in the future, a redesign of the selector
58  // system could be considered. For now, if users wish to retrieve
59  // products with the process name "current_process", they must use the
60  // getBy* facilities provided by Event and friends.
61  // -------------------------------------------------------------------
62 
64  public:
65  explicit ProcessNameSelector(std::string const& pn)
66  : pn_{pn.empty() ? std::string{"*"} : pn}
67  {}
68 
69  private:
70  bool
71  doMatch(BranchDescription const& p) const override
72  {
73  return (pn_ == "*") || (p.processName() == pn_);
74  }
75 
76  std::string
77  doPrint(std::string const& indent) const override
78  {
79  std::string result{indent + "Process name: "};
80  if (pn_ == "*") {
81  result += "(empty)";
82  } else {
83  result += "'" + pn_ + "'";
84  }
85  return result;
86  }
87 
88  std::string pn_;
89  };
90 
91  //------------------------------------------------------------------
92  // Class ProductInstanceNameSelector.
93  // Selects EDProducts based upon product instance name.
94  //------------------------------------------------------------------
95 
97  public:
98  explicit ProductInstanceNameSelector(std::string const& pin) : pin_{pin} {}
99 
100  private:
101  bool
102  doMatch(BranchDescription const& p) const override
103  {
104  return p.productInstanceName() == pin_;
105  }
106 
107  std::string
108  doPrint(std::string const& indent) const override
109  {
110  return indent + "Product instance name: '" + pin_ + '\'';
111  }
112 
113  std::string pin_;
114  };
115 
116  //------------------------------------------------------------------
117  // Class ModuleLabelSelector.
118  // Selects EDProducts based upon module label.
119  //------------------------------------------------------------------
120 
122  public:
123  explicit ModuleLabelSelector(std::string const& label) : label_{label} {}
124 
125  private:
126  bool
127  doMatch(BranchDescription const& p) const override
128  {
129  return p.moduleLabel() == label_;
130  }
131 
132  std::string
133  doPrint(std::string const& indent) const override
134  {
135  return indent + "Module label: '" + label_ + '\'';
136  }
137 
138  std::string label_;
139  };
140 
141  //------------------------------------------------------------------
142  // Class MatchAllSelector.
143  // Dummy selector whose match function always returns true.
144  //------------------------------------------------------------------
145 
147  bool
148  doMatch(BranchDescription const&) const override
149  {
150  return true;
151  }
152 
153  std::string
154  doPrint(std::string const&) const override
155  {
156  return {};
157  }
158  };
159 
160  // Select products based on the result of a filter function (or
161  // functor) provided to the constructor.
163  public:
164  template <typename FUNC>
165  explicit SelectorByFunction(FUNC func, std::string description)
166  : func_(func), description_(description)
167  {}
168 
169  private:
170  bool
171  doMatch(art::BranchDescription const& p) const override
172  {
173  return func_(p);
174  }
175 
176  std::string
177  doPrint(std::string const& indent) const override
178  {
179  return indent + description_;
180  }
181 
182  std::function<bool(art::BranchDescription const&)> func_;
183  std::string description_;
184  };
185 
186  // Select products based on a sequence of wanted input tags.
188  public:
189  // Initialize wanted input tags from a sequence denoted by
190  // [begin, end).
191  //
192  // This constructor is only valid (via SFINAE) if the provided
193  // iterators dereference to a type convertible to art::InputTag.
194  template <typename IT>
196  IT begin,
197  IT end,
198  std::string const& description,
199  std::enable_if_t<std::is_convertible_v<decltype(std::declval<IT>().
200  operator*()),
201  art::InputTag>>* dummy
202  [[maybe_unused]] = nullptr)
203  : tags_{begin, end}, description_{description}
204  {}
205 
206  std::vector<art::InputTag> const&
207  wantedTags() const
208  {
209  return tags_;
210  }
211 
212  private:
213  bool
214  doMatch(art::BranchDescription const& p) const override
215  {
216  return std::any_of(
217  std::cbegin(tags_), std::cend(tags_), [&p](art::InputTag const& tag) {
218  return (tag.label().empty() || p.moduleLabel() == tag.label()) &&
219  (tag.instance().empty() ||
220  p.productInstanceName() == tag.instance()) &&
221  (tag.process().empty() || p.processName() == tag.process());
222  });
223  }
224 
225  std::string
226  doPrint(std::string const& indent) const override
227  {
228  return indent + description_;
229  }
230 
231  std::vector<art::InputTag> const tags_;
232  std::string description_;
233  };
234 
235  //----------------------------------------------------------
236  // AndHelper template.
237  // Used to form expressions involving && between other selectors.
238  //----------------------------------------------------------
239 
240  template <typename A, typename B>
241  class AndHelper : public SelectorBase {
242  public:
243  AndHelper(A const& a, B const& b) : a_{a}, b_{b} {}
244 
245  private:
246  bool
247  doMatch(BranchDescription const& p) const override
248  {
249  return a_.match(p) && b_.match(p);
250  }
251 
252  std::string
253  doPrint(std::string const& indent) const override
254  {
255  return a_.print(indent) + '\n' + b_.print(indent);
256  }
257 
258  A a_;
259  B b_;
260  };
261 
262  template <typename A, typename B>
263  std::enable_if_t<is_selector<A> && is_selector<B>, AndHelper<A, B>>
264  operator&&(A const& a, B const& b)
265  {
266  return AndHelper<A, B>{a, b};
267  }
268 
269  //----------------------------------------------------------
270  // OrHelper template.
271  // Used to form expressions involving || between other selectors.
272  //----------------------------------------------------------
273 
274  template <typename A, typename B>
275  class OrHelper : public SelectorBase {
276  public:
277  OrHelper(A const& a, B const& b) : a_{a}, b_{b} {}
278 
279  private:
280  bool
281  doMatch(BranchDescription const& p) const override
282  {
283  return a_.match(p) || b_.match(p);
284  }
285 
286  std::string
287  doPrint(std::string const& indent) const override
288  {
289  std::string result{indent + "[\n"};
290  result += indent + a_.print(indent) + '\n';
291  result += indent + indent + indent + "or\n";
292  result += indent + b_.print(indent) + '\n';
293  result += indent + ']';
294  return result;
295  }
296 
297  A a_;
298  B b_;
299  };
300 
301  template <typename A, typename B>
302  std::enable_if_t<is_selector<A> && is_selector<B>, OrHelper<A, B>>
303  operator||(A const& a, B const& b)
304  {
305  return OrHelper<A, B>{a, b};
306  }
307 
308  //----------------------------------------------------------
309  // NotHelper template.
310  // Used to form expressions involving ! acting on a selector.
311  //----------------------------------------------------------
312 
313  template <typename A>
314  class NotHelper : public SelectorBase {
315  public:
316  explicit NotHelper(A const& a) : a_{a} {}
317 
318  private:
319  bool
320  doMatch(BranchDescription const& p) const override
321  {
322  return !a_.match(p);
323  }
324 
325  std::string
326  doPrint(std::string const& indent) const override
327  {
328  std::string result{indent + "Not [\n"};
329  result += indent + a_.print(indent) + '\n';
330  result += indent + ']';
331  return result;
332  }
333  A a_;
334  };
335 
336  template <typename A>
337  std::enable_if_t<is_selector<A>, NotHelper<A>>
338  operator!(A const& a)
339  {
340  return NotHelper<A>{a};
341  }
342 
343  //----------------------------------------------------------
344  // ComposedSelectorWrapper template
345  // Used to hold an expression formed from the various helpers.
346  //----------------------------------------------------------
347 
348  template <typename T>
349  class ComposedSelectorWrapper : public SelectorBase {
350  public:
351  using wrapped_type = T;
352  explicit ComposedSelectorWrapper(T const& t) : expression_{t} {}
353 
354  private:
355  bool
356  doMatch(BranchDescription const& p) const override
357  {
358  return expression_.match(p);
359  }
360 
361  std::string
362  doPrint(std::string const& indent) const override
363  {
364  return expression_.print(indent);
365  }
366 
368  };
369 
370  //----------------------------------------------------------
371  // Selector
372  //----------------------------------------------------------
373 
374  class Selector : public SelectorBase {
375  public:
376  template <typename T>
377  explicit Selector(T const& expression)
378  : sel_{new ComposedSelectorWrapper<T>{expression}}
379  {}
380 
381  private:
382  bool doMatch(BranchDescription const& p) const override;
383  std::string doPrint(std::string const& indent) const override;
384 
385  std::shared_ptr<SelectorBase> sel_;
386  };
387 
388 } // namespace art
389 
390 #endif /* art_Framework_Principal_Selector_h */
391 
392 // Local Variables:
393 // mode: c++
394 // End:
std::vector< art::InputTag > const & wantedTags() const
Definition: Selector.h:207
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
Definition: StdUtils.h:93
std::function< bool(art::BranchDescription const &)> func_
Definition: Selector.h:182
constexpr bool is_selector
Definition: Selector.h:44
AndHelper(A const &a, B const &b)
Definition: Selector.h:243
std::shared_ptr< SelectorBase > sel_
Definition: Selector.h:385
Selector(T const &expression)
Definition: Selector.h:377
bool doMatch(BranchDescription const &p) const override
Definition: Selector.h:320
ProductInstanceNameSelector(std::string const &pin)
Definition: Selector.h:98
InputTagListSelector(IT begin, IT end, std::string const &description, std::enable_if_t< std::is_convertible_v< decltype(std::declval< IT >(). operator*()), art::InputTag >> *dummy[[maybe_unused]]=nullptr)
Definition: Selector.h:195
std::enable_if_t< is_selector< A >, NotHelper< A > > operator!(A const &a)
Definition: Selector.h:338
std::string description_
Definition: Selector.h:183
std::string doPrint(std::string const &) const override
Definition: Selector.h:154
std::string const & instance() const noexcept
Definition: InputTag.cc:85
bool doMatch(BranchDescription const &p) const override
Definition: Selector.h:247
std::string const & process() const noexcept
Definition: InputTag.cc:91
bool doMatch(BranchDescription const &p) const override
Definition: Selector.h:281
std::string const & processName() const noexcept
std::string doPrint(std::string const &indent) const override
Definition: Selector.h:362
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
std::string const & label() const noexcept
Definition: InputTag.cc:79
std::enable_if_t< is_selector< A > &&is_selector< B >, AndHelper< A, B > > operator&&(A const &a, B const &b)
Definition: Selector.h:264
std::string doPrint(std::string const &indent) const override
Definition: Selector.h:177
bool doMatch(BranchDescription const &p) const override
Definition: Selector.h:71
std::string doPrint(std::string const &indent) const override
Definition: Selector.h:77
std::string indent(std::size_t const i)
bool doMatch(BranchDescription const &) const override
Definition: Selector.h:148
bool doMatch(BranchDescription const &p) const override
Definition: Selector.h:127
std::string doPrint(std::string const &indent) const override
Definition: Selector.h:108
std::vector< art::InputTag > const tags_
Definition: Selector.h:231
std::string doPrint(std::string const &indent) const override
Definition: Selector.h:226
SelectorByFunction(FUNC func, std::string description)
Definition: Selector.h:165
bool doMatch(BranchDescription const &p) const override
Definition: Selector.h:356
std::string description_
Definition: Selector.h:232
ModuleLabelSelector(std::string const &label)
Definition: Selector.h:123
std::string doPrint(std::string const &indent) const override
Definition: Selector.h:253
std::string doPrint(std::string const &indent) const override
Definition: Selector.h:287
std::string const & moduleLabel() const noexcept
OrHelper(A const &a, B const &b)
Definition: Selector.h:277
bool doMatch(BranchDescription const &p) const override
Definition: Selector.h:102
ComposedSelectorWrapper(T const &t)
Definition: Selector.h:352
std::string const & productInstanceName() const noexcept
ProcessNameSelector(std::string const &pn)
Definition: Selector.h:65
std::string doPrint(std::string const &indent) const override
Definition: Selector.h:326
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
Definition: StdUtils.h:85
Definition: MVAAlg.h:12
NotHelper(A const &a)
Definition: Selector.h:316
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
bool doMatch(art::BranchDescription const &p) const override
Definition: Selector.h:214
bool doMatch(art::BranchDescription const &p) const override
Definition: Selector.h:171
std::enable_if_t< is_selector< A > &&is_selector< B >, OrHelper< A, B > > operator||(A const &a, B const &b)
Definition: Selector.h:303
std::string doPrint(std::string const &indent) const override
Definition: Selector.h:133