LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
MixFilter.h
Go to the documentation of this file.
1 #ifndef art_Framework_Modules_MixFilter_h
2 #define art_Framework_Modules_MixFilter_h
3 
5 //
6 // The MixFilter class template is used to create filters capable of
7 // mixing products from a secondary event (or subrun, or run) stream
8 // into the primary event.
9 //
10 // The MixFilter class template requires two template arguments:
11 //
12 // - the use of a type T as its
13 // template parameter; this type T must supply the following non-static
14 // member functions:
15 //
16 // T(fhicl::ParameterSet const& p, art::MixHelper& helper);
17 //
18 // // Construct an object of type T. The ParameterSet provided will
19 // // be the configuration of the module constructing the T. It is
20 // // recommended (but not enforced) that detail parameters be placed
21 // // in their own (eg "detail") ParameterSet to reduce the potential
22 // // for clashes with parameters used by the template. The helper
23 // // is not copyable and must be used in the constructor to
24 // // register:
25 // //
26 // // a. Any mixing operations to be carried out by this module by
27 // // means of declareMixOp<> calls.
28 // //
29 // // b. Any non-mix (e.g. bookkeeping) products by means of
30 // // produces<> calls.
31 // //
32 // // Further details may be found in
33 // // art/Framework/IO/ProductMix/MixHelper.h.
34 //
35 // size_t nSecondaries();
36 //
37 // // Provide the number of secondary events to be mixed into the
38 // // current primary event.
39 //
40 // In addition, T may optionally provide any or all of the following
41 // member functions; each will be called at the appropriate time iff
42 // it is declared. (There must, of course, be a function definition
43 // corresponding to each declared function.)
44 //
45 // void startEvent(art::Event const& e);
46 //
47 // // Reset internal cache information at the start of the current
48 // // event.
49 //
50 // size_t eventsToSkip();
51 //
52 // // Provide the number of secondary events at the beginning of the
53 // // next secondary input file that should be skipped. Note:
54 // // may be declare const or not as appropriate.
55 //
56 // void processEventIDs(art::EventIDSequence const& seq);
57 //
58 // // Receive the ordered sequence of EventIDs that will be mixed into
59 // // the current event; useful for bookkeeping purposes.
60 //
61 // void processEventAuxiliaries(art::EventAuxiliarySequence const& seq);
62 //
63 // // Receive the ordered sequence of EventAuxiliaries that will be mixed
64 // // into the current event; useful for bookkeeping purposes.
65 //
66 // void finalizeEvent(art::Event& e);
67 //
68 // // Do end-of-event tasks (e.g., inserting bookkeeping data products into
69 // // the primary event).
70 //
71 // void respondToOpenInputFile(FileBlock const& fb);
72 //
73 // // Called when a new primary input file is opened.
74 //
75 // void respondToCloseInputFile(FileBlock const& fb);
76 //
77 // // Called when a primary input file is closed.
78 //
79 // void respondToOpenOutputFiles(FileBlock const& fb);
80 //
81 // // Called when a new output file is opened.
82 //
83 // void respondToCloseOutputFiles(FileBlock const& fb);
84 //
85 // // Called when an output file is closed.
86 //
87 // void beginSubRun(art::SubRun const& sr);
88 //
89 // // Do beginning-of-subrun tasks.
90 //
91 // void endSubRun(art::SubRun& sr);
92 //
93 // // Do end-of-subrun tasks (e.g. insert products into the primary subrun).
94 //
95 // void beginRun(art::Run const& r);
96 //
97 // // Do beginning-of-run tasks.
98 //
99 // void endRun(art::Run& r);
100 //
101 // // Do end-of-run tasks (e.g. insert products into the primary run).
102 //
104 // Notes.
105 //
106 // 1. Functions declared to the MixHelper to actually carry out the
107 // mixing of the products may be (1) member functions of this or
108 // another class; or (2) free functions (including bound functions)
109 // or (3) function objects.
110 //
111 // 2. It is possible to declare mix operations which produce an output
112 // product of a different type to that of the mixed input products
113 // via the provision of an appropriate mixer function: see the
114 // documentation in art/Framework/IO/ProductMix/MixHelper.h for more
115 // details.
116 //
117 // 3. It is possible to declare mix operations which take as input
118 // products from the subrun or run streams. Some points to note:
119 //
120 // * The mix operation so declared will be invoked upon every primary
121 // event.
122 //
123 // * There will be one provided product for every mixed event from
124 // the secondary stream, regardless of duplication. It is the
125 // responsibility of the user's mixing function to deal with the
126 // provided information appropriately. We recommend making use of
127 // the optional processEventIDs(...) and
128 // processEventAuxiliaries(...) functions to avoid unintentional
129 // double-counting of information.
130 //
131 // * The mix operation may generate event-level data for the primary
132 // stream from the provided subrun and run products exactly as if
133 // it were a normal event-level mix operation. Any production of
134 // subrun- or run-level data from the primary stream should be done
135 // in the optional endSubRun(..) and / or endRun(...) functions as
136 // appropriate. Any such subrun- or run-level products should be
137 // declared appropriately via art::MixHelper::products(...).
138 //
140 
146 #include "cetlib/metaprogramming.h"
148 
149 #include <functional>
150 #include <memory>
151 #include <type_traits>
152 
153 namespace art {
154  template <typename T, typename IOPolicy>
155  class MixFilter;
156 
157  template <typename T>
159  public:
160  using value_type = T;
161 
162  auto const&
163  operator()() const
164  {
165  return fragment_();
166  }
167 
168  private:
170  };
171 
172  namespace detail {
173  // Template metaprogramming.
174  using cet::enable_if_function_exists_t;
175 
177  // Does the detail object have a method void startEvent()?
178 
179  template <typename T, typename = void>
180  struct has_startEvent : std::false_type {};
181 
182  template <typename T>
184  T,
185  enable_if_function_exists_t<void (T::*)(Event const&), &T::startEvent>>
186  : std::true_type {};
187 
189 
191  // Does the detail object have a method size_t eventsToSkip() const?
192 
193  template <typename T, typename = void>
194  struct has_eventsToSkip : std::false_type {};
195 
196  template <typename T>
198  T,
199  enable_if_function_exists_t<size_t (T::*)(), &T::eventsToSkip>>
200  : std::true_type {};
201 
202  template <typename T>
204  T,
205  enable_if_function_exists_t<size_t (T::*)() const, &T::eventsToSkip>>
206  : std::true_type {};
208 
210  // Does the detail object have a method void
211  // processEventIDs(EventIDSequence const&)?
212 
213  template <typename T, typename = void>
214  struct has_processEventIDs : std::false_type {};
215 
216  template <typename T>
218  T,
219  enable_if_function_exists_t<void (T::*)(EventIDSequence const&),
220  &T::processEventIDs>> : std::true_type {};
221 
223 
225  // Does the detail object have a method void
226  // processEventAuxiliaries(EventAuxiliarySequence const&)?
227 
228  template <typename T, typename = void>
229  struct has_processEventAuxiliaries : std::false_type {};
230 
231  template <typename T>
233  T,
234  enable_if_function_exists_t<void (T::*)(EventAuxiliarySequence const&),
235  &T::processEventAuxiliaries>>
236  : std::true_type {};
237 
239 
241  // Does the detail object have a method void finalizeEvent(Event&)?
242  template <typename T, typename = void>
243  struct has_finalizeEvent : std::false_type {};
244 
245  template <typename T>
247  T,
248  enable_if_function_exists_t<void (T::*)(Event&), &T::finalizeEvent>>
249  : std::true_type {};
250 
252 
254  // Does the detail object have a method void beginSubRun(SubRun const&)?
255  template <typename T, typename = void>
256  struct has_beginSubRun : std::false_type {};
257 
258  template <typename T>
260  T,
261  enable_if_function_exists_t<void (T::*)(SubRun const&), &T::beginSubRun>>
262  : std::true_type {};
263 
265 
267  // Does the detail object have a method void endSubRun(SubRun&)?
268  template <typename T, typename = void>
269  struct has_endSubRun : std::false_type {};
270 
271  template <typename T>
273  T,
274  enable_if_function_exists_t<void (T::*)(SubRun&), &T::endSubRun>>
275  : std::true_type {};
276 
278 
280  // Does the detail object have a method void beginRun(Run const&)?
281  template <typename T, typename = void>
282  struct has_beginRun : std::false_type {};
283 
284  template <typename T>
285  struct has_beginRun<
286  T,
287  enable_if_function_exists_t<void (T::*)(Run const&), &T::beginRun>>
288  : std::true_type {};
289 
291 
293  // Does the detail object have a method void endRun(Run&)?
294  template <typename T, typename = void>
295  struct has_endRun : std::false_type {};
296 
297  template <typename T>
298  struct has_endRun<
299  T,
300  enable_if_function_exists_t<void (T::*)(Run&), &T::endRun>>
301  : std::true_type {};
302 
304 
306  // Does the detail object have respondToXXX methods()?
307  template <typename T>
308  using respond_to_file = void (T::*)(FileBlock const&);
309 
310  template <typename T, respond_to_file<T>>
312 
313  // has_respondToOpenInputFile
314  template <typename T, typename = void>
315  struct has_respondToOpenInputFile : std::false_type {};
316 
317  template <typename T>
319  T,
320  enable_if_function_exists_t<respond_to_file<T>,
321  &T::respondToOpenInputFile>>
322  : std::true_type {};
323 
324  // has_respondToCloseInputFile
325  template <typename T, typename = void>
326  struct has_respondToCloseInputFile : std::false_type {};
327 
328  template <typename T>
330  T,
331  enable_if_function_exists_t<respond_to_file<T>,
332  &T::respondToCloseInputFile>>
333  : std::true_type {};
334 
335  // has_respondToOpenOutputFiles
336  template <typename T, typename = void>
337  struct has_respondToOpenOutputFiles : std::false_type {};
338 
339  template <typename T>
341  T,
342  enable_if_function_exists_t<respond_to_file<T>,
343  &T::respondToOpenOutputFiles>>
344  : std::true_type {};
345 
346  // has_respondToCloseOutputFiles
347  template <typename T, typename = void>
348  struct has_respondToCloseOutputFiles : std::false_type {};
349 
350  template <typename T>
352  T,
353  enable_if_function_exists_t<respond_to_file<T>,
354  &T::respondToCloseOutputFiles>>
355  : std::true_type {};
356 
358 
360  // Does the detail object have a Parameters type?
361  template <typename T, typename = void>
362  struct maybe_has_Parameters : std::false_type {
364  };
365 
366  template <typename T>
367  struct maybe_has_Parameters<T, std::void_t<typename T::Parameters>>
368  : std::true_type {
369  using user_config_t = typename T::Parameters;
370  struct Config {
372  user_config_t userConfig;
373  };
375  };
376 
377  } // namespace detail
378 
379 } // namespace art
380 
381 template <typename T, typename IOPolicy>
382 class art::MixFilter : public EDFilter {
383 public:
384  using MixDetail = T;
385 
387 
388  template <typename U = Parameters>
389  explicit MixFilter(std::enable_if_t<std::is_same_v<U, fhicl::ParameterSet>,
390  fhicl::ParameterSet> const& p);
391  template <typename U = Parameters>
392  explicit MixFilter(
393  std::enable_if_t<!std::is_same_v<U, fhicl::ParameterSet>, U> const& p);
394 
395 private:
396  void respondToOpenInputFile(FileBlock const& fb) override;
397  void respondToCloseInputFile(FileBlock const& fb) override;
398  void respondToOpenOutputFiles(FileBlock const& fb) override;
399  void respondToCloseOutputFiles(FileBlock const& fb) override;
400  bool filter(Event& e) override;
401  bool beginSubRun(SubRun& sr) override;
402  bool endSubRun(SubRun& sr) override;
403  bool beginRun(Run& r) override;
404  bool endRun(Run& r) override;
405 
408 };
409 
410 template <typename T, typename IOPolicy>
411 template <typename U>
413  std::enable_if_t<std::is_same_v<U, fhicl::ParameterSet>,
414  fhicl::ParameterSet> const& p)
415  : EDFilter{p}
416  , helper_{p,
417  p.template get<std::string>("module_label"),
419  std::make_unique<IOPolicy>()}
420  , detail_{p, helper_}
421 {
422  if constexpr (detail::has_eventsToSkip<T>::value) {
423  helper_.setEventsToSkipFunction([this] { return detail_.eventsToSkip(); });
424  }
425 }
426 
427 template <typename T, typename IOPolicy>
428 template <typename U>
430  std::enable_if_t<!std::is_same_v<U, fhicl::ParameterSet>, U> const& p)
431  : EDFilter{p}
432  , helper_{p().mixHelper(),
433  p.get_PSet().template get<std::string>("module_label"),
435  std::make_unique<IOPolicy>()}
436  , detail_{p().userConfig, helper_}
437 {
438  if constexpr (detail::has_eventsToSkip<T>::value) {
439  helper_.setEventsToSkipFunction([this] { return detail_.eventsToSkip(); });
440  }
441 }
442 
443 template <typename T, typename IOPolicy>
444 void
446 {
448  detail_.respondToOpenInputFile(fb);
449  }
450 }
451 
452 template <typename T, typename IOPolicy>
453 void
455 {
457  detail_.respondToCloseInputFile(fb);
458  }
459 }
460 
461 template <typename T, typename IOPolicy>
462 void
464 {
466  detail_.respondToOpenOutputFiles(fb);
467  }
468 }
469 
470 template <typename T, typename IOPolicy>
471 void
473 {
475  detail_.respondToCloseOutputFiles(fb);
476  }
477 }
478 
479 template <typename T, typename IOPolicy>
480 bool
482 {
483  // 1. Call detail object's startEvent() if it exists.
484  if constexpr (detail::has_startEvent<T>::value) {
485  detail_.startEvent(e);
486  }
487 
488  // 2. Ask detail object how many events to read.
489  size_t const nSecondaries = detail_.nSecondaries();
490 
491  // 3. Decide which events we're reading and prime the event tree
492  // cache.
493  EntryNumberSequence enSeq;
494  EventIDSequence eIDseq;
495  enSeq.reserve(nSecondaries);
496  eIDseq.reserve(nSecondaries);
497  if (!helper_.generateEventSequence(nSecondaries, enSeq, eIDseq)) {
499  << "Insufficient secondary events available to mix.\n";
500  }
501 
502  // 4. Give the event ID sequence to the detail object.
504  detail_.processEventIDs(eIDseq);
505  }
506 
507  // 5. Give the event auxiliary sequence to the detail object.
509  auto const auxseq = helper_.generateEventAuxiliarySequence(enSeq);
510  detail_.processEventAuxiliaries(auxseq);
511  }
512 
513  // 6. Make the MixHelper read info into all the products, invoke the
514  // mix functions and put the products into the event.
515  helper_.mixAndPut(enSeq, eIDseq, e);
516 
517  // 7. Call detail object's finalizeEvent() if it exists.
518  if constexpr (detail::has_finalizeEvent<T>::value) {
519  detail_.finalizeEvent(e);
520  }
521  return true;
522 }
523 
524 template <typename T, typename IOPolicy>
525 bool
527 {
528  if constexpr (detail::has_beginSubRun<T>::value) {
529  detail_.beginSubRun(sr);
530  }
531  return true;
532 }
533 
534 template <typename T, typename IOPolicy>
535 bool
537 {
538  if constexpr (detail::has_endSubRun<T>::value) {
539  detail_.endSubRun(sr);
540  }
541  return true;
542 }
543 
544 template <typename T, typename IOPolicy>
545 bool
547 {
548  if constexpr (detail::has_beginRun<T>::value) {
549  detail_.beginRun(r);
550  }
551  return true;
552 }
553 
554 template <typename T, typename IOPolicy>
555 bool
557 {
558  if constexpr (detail::has_endRun<T>::value) {
559  detail_.endRun(r);
560  }
561  return true;
562 }
563 
564 #endif /* art_Framework_Modules_MixFilter_h */
565 
566 // Local Variables:
567 // mode: c++
568 // End:
TRandom r
Definition: spectrum.C:23
std::vector< EventID > EventIDSequence
Definition: MixTypes.h:26
void mixAndPut(EntryNumberSequence const &enSeq, EventIDSequence const &eIDseq, Event &e)
Definition: MixHelper.cc:289
void setEventsToSkipFunction(std::function< size_t()> eventsToSkip)
Definition: MixHelper.cc:360
typename detail::maybe_has_Parameters< T >::Parameters Parameters
Definition: MixFilter.h:386
bool beginRun(Run &r) override
Definition: MixFilter.h:546
void respondToOpenInputFile(FileBlock const &fb) override
Definition: MixFilter.h:445
void respondToCloseInputFile(FileBlock const &fb) override
Definition: MixFilter.h:454
STL namespace.
bool endRun(Run &r) override
Definition: MixFilter.h:556
Definition: Run.h:37
bool generateEventSequence(size_t nSecondaries, EntryNumberSequence &enSeq, EventIDSequence &eIDseq)
Definition: MixHelper.cc:193
void respondToCloseOutputFiles(FileBlock const &fb) override
Definition: MixFilter.h:472
void respondToOpenOutputFiles(FileBlock const &fb) override
Definition: MixFilter.h:463
bool filter(Event &e) override
Definition: MixFilter.h:481
std::vector< FileIndex::EntryNumber_t > EntryNumberSequence
Definition: MixTypes.h:27
bool endSubRun(SubRun &sr) override
Definition: MixFilter.h:536
MixHelper helper_
Definition: MixFilter.h:406
MixFilter(std::enable_if_t< std::is_same_v< U, fhicl::ParameterSet >, fhicl::ParameterSet > const &p)
Definition: MixFilter.h:412
void(T::*)(FileBlock const &) respond_to_file
Definition: MixFilter.h:308
TFile fb("Li6.root")
ProducesCollector & producesCollector() noexcept
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
bool beginSubRun(SubRun &sr) override
Definition: MixFilter.h:526
EventAuxiliarySequence generateEventAuxiliarySequence(EntryNumberSequence const &)
Definition: MixHelper.cc:279
auto const & operator()() const
Definition: MixFilter.h:163
Definition: MVAAlg.h:12
Float_t e
Definition: plot.C:35
MixDetail detail_
Definition: MixFilter.h:407
fhicl::TableFragment< T > fragment_
Definition: MixFilter.h:169