MixFilter.h
Go to the documentation of this file.
1 #ifndef art_Framework_Modules_MixFilter_h
2 #define art_Framework_Modules_MixFilter_h
3 
4 ////////////////////////////////////////////////////////////////////////
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 the use of a type T as its
11 // template parameter; this type T must supply the following non-static
12 // member functions:
13 //
14 // T(fhicl::ParameterSet const &p, art::MixHelper &helper);
15 //
16 // // Construct an object of type T. The ParameterSet provided will
17 // // be the configuration of the module constructing the T. It is
18 // // recommended (but not enforced) that detail parameters be placed
19 // // in their own (eg "detail") ParameterSet to reduce the potential
20 // // for clashes with parameters used by the template. The helper
21 // // is not copyable and must be used in the constructor to
22 // // register:
23 // //
24 // // a. Any mixing operations to be carried out by this module by
25 // // means of declareMixOp<> calls.
26 // //
27 // // b. Any non-mix (e.g. bookkeeping) products by means of
28 // // produces<> calls.
29 // //
30 // // Further details may be found in
31 // // art/Framework/IO/ProductMix/MixHelper.h.
32 //
33 // size_t nSecondaries() const;
34 //
35 // // Provide the number of secondary events to be mixed into the
36 // // current primary event.
37 //
38 // In addition, T may optionally provide any or all of the following
39 // member functions; each will be called at the appropriate time iff
40 // it is declared. (There must, of course, be a function definition
41 // corresponding to each declared function.)
42 //
43 // void startEvent(art::Event const & e);
44 //
45 // // Reset internal cache information at the start of the current
46 // // event.
47 //
48 // size_t eventsToSkip();
49 //
50 // // Provide the number of secondary events at the beginning of the
51 // // next secondary input file that should be skipped. Note:
52 // // may be declare const or not as appropriate.
53 //
54 // void processEventIDs(art::EventIDSequence const & seq);
55 //
56 // // Receive the ordered sequence of EventIDs that will be mixed into
57 // // the current event; useful for bookkeeping purposes.
58 //
59 // void processEventAuxiliaries(art::EventAuxiliarySequence const & seq);
60 //
61 // // Receive the ordered sequence of EventAuxiliaries that will be mixed
62 // // into the current event; useful for bookkeeping purposes.
63 //
64 // void finalizeEvent(art::Event & e);
65 //
66 // // Do end-of-event tasks (e.g., inserting bookkeeping data products into
67 // // the primary event).
68 //
69 // void respondToOpenInputFile(FileBlock const & fb);
70 //
71 // // Called when a new primary input file is opened.
72 //
73 // void respondToCloseInputFile(FileBlock const & fb);
74 //
75 // // Called when a primary input file is closed.
76 //
77 // void respondToOpenOutputFiles(FileBlock const & fb);
78 //
79 // // Called when a new output file is opened.
80 //
81 // void respondToCloseOutputFiles(FileBlock const & fb);
82 //
83 // // Called when an output file is closed.
84 //
85 // void beginSubRun(art::SubRun const & sr);
86 //
87 // // Do beginning-of-subrun tasks.
88 //
89 // void endSubRun(art::SubRun & sr);
90 //
91 // // Do end-of-subrun tasks (e.g. insert products into the primary subrun).
92 //
93 // void beginRun(art::Run const & r);
94 //
95 // // Do beginning-of-run tasks.
96 //
97 // void endRun(art::Run & r);
98 //
99 // // Do end-of-run tasks (e.g. insert products into the primary run).
100 //
101 ////////////////////////////////////////////////////////////////////////
102 // Notes.
103 //
104 // 1. Functions declared to the MixHelper to actually carry out the
105 // mixing of the products may be (1) member functions of this or
106 // another class; or (2) free functions (including bound functions)
107 // or (3) function objects.
108 //
109 // 2. It is possible to declare mix operations which produce an output
110 // product of a different type to that of the mixed input products
111 // via the provision of an appropriate mixer function: see the
112 // documentation in art/Framework/IO/ProductMix/MixHelper.h for more
113 // details.
114 //
115 // 3. It is possible to declare mix operations which take as input
116 // products from the subrun or run streams. Some points to note:
117 //
118 // * The mix operation so declared will be invoked upon every primary
119 // event.
120 //
121 // * There will be one provided product for every mixed event from
122 // the secondary stream, regardless of duplication. It is the
123 // responsibility of the user's mixing function to deal with the
124 // provided information appropriately. We recommend making use of
125 // the optional processEventIDs(...) and
126 // prodcessEventAuxiliaries(...) functions to avoid unintentional
127 // double-counting of information.
128 //
129 // * The mix operation may generate event-level data for the primary
130 // stream from the provided subrun and run products exactly as if
131 // it were a normal event-level mix operation. Any production of
132 // subrun- or run-level data from the primary stream should be done
133 // in the optional endSubRun(..) and / or endRun(...) functions as
134 // appropriate. Any such subrun- or run-level products should be
135 // declared appropriately via art::MixHelper::products(...).
136 //
137 ////////////////////////////////////////////////////////////////////////
138 
145 #include "cetlib/metaprogramming.h"
147 
148 #include <functional>
149 #include <type_traits>
150 
151 namespace art {
152  template <class T>
153  class MixFilter;
154 
155  namespace detail {
156  // Template metaprogramming.
158 
159  ////////////////////////////////////////////////////////////////////
160  // Does the detail object have a method void startEvent()?
161  template <typename T, typename = void>
162  struct has_old_startEvent : std::false_type {};
163 
164  template <typename T>
166  T,
167  enable_if_function_exists_t<void (T::*)(), &T::startEvent>>
168  : std::true_type {};
169 
170  template <typename T>
172  public:
173  void
175  {
176  static bool need_warning = true;
177  if (need_warning) {
178  mf::LogWarning("Deprecated")
179  << "Mixing driver function has signature startEvent(), which is "
180  "deprecated.\n"
181  << "Please update your code to define startEvent(Event const &).\n"
182  << "In a future version of ART the old method will no longer be "
183  "called.";
184  need_warning = false;
185  }
186  t.startEvent();
187  }
188  };
189 
190  template <typename T>
192  void
194  {}
195  };
196 
197  template <typename T>
199  public:
201  void
203  {
207  maybe_call_old_startEvent;
208  maybe_call_old_startEvent(t);
209  }
210 
211  private:
212  };
213  //////////
214 
215  template <typename T, typename = void>
216  struct has_startEvent : std::false_type {};
217 
218  template <typename T>
220  T,
221  enable_if_function_exists_t<void (T::*)(Event const&), &T::startEvent>>
222  : std::true_type {};
223 
224  template <typename T>
226  public:
227  call_startEvent(Event const& e) : e_(e) {}
228  void
230  {
231  t.startEvent(e_);
232  }
233 
234  private:
235  Event const& e_;
236  };
237 
238  ////////////////////////////////////////////////////////////////////
239 
240  ////////////////////////////////////////////////////////////////////
241  // Does the detail object have a method size_t eventsToSkip() const?
242 
243  template <typename T, typename = void>
244  struct has_eventsToSkip : std::false_type {};
245 
246  template <typename T>
248  T,
249  enable_if_function_exists_t<size_t (T::*)(), &T::eventsToSkip>>
250  : std::true_type {};
251 
252  template <typename T>
254  T,
255  enable_if_function_exists_t<size_t (T::*)() const, &T::eventsToSkip>>
256  : std::true_type {};
257 
258  template <typename T>
261  };
262 
263  template <typename T>
264  size_t
266  {
267  return t.eventsToSkip();
268  }
269 
270  template <typename T>
273  {
275  std::bind(&detail::call_eventsToSkip<T>, std::ref(t)));
276  }
277  };
278 
279  ////////////////////////////////////////////////////////////////////
280 
281  ////////////////////////////////////////////////////////////////////
282  // Does the detail object have a method void
283  // processEventIDs(EventIDSequence const &)?
284 
285  template <typename T, typename = void>
286  struct has_processEventIDs : std::false_type {};
287 
288  template <typename T>
290  T,
291  enable_if_function_exists_t<void (T::*)(EventIDSequence const&),
292  &T::processEventIDs>> : std::true_type {};
293 
294  template <typename T>
296  void
298  {}
299  };
300 
301  template <typename T>
303  void
305  {
306  t.processEventIDs(seq);
307  }
308  };
309 
310  ////////////////////////////////////////////////////////////////////
311 
312  ////////////////////////////////////////////////////////////////////
313  // Does the detail object have a method void
314  // processEventAuxiliaries(EventAuxiliarySequence const &)?
315 
316  template <typename T, typename = void>
317  struct has_processEventAuxiliaries : std::false_type {};
318 
319  template <typename T>
321  T,
322  enable_if_function_exists_t<void (T::*)(EventAuxiliarySequence const&),
323  &T::processEventAuxiliaries>>
324  : std::true_type {};
325 
326  template <typename T>
328  void
330  {}
331  };
332 
333  template <typename T>
335  void
337  MixHelper& h,
338  EntryNumberSequence const& enseq,
339  size_t nSecondaries)
340  {
341  EventAuxiliarySequence auxseq;
342  auxseq.reserve(nSecondaries);
343  h.generateEventAuxiliarySequence(enseq, auxseq);
344  t.processEventAuxiliaries(auxseq);
345  }
346  };
347 
348  ////////////////////////////////////////////////////////////////////
349 
350  ////////////////////////////////////////////////////////////////////
351  // Does the detail object have a method void finalizeEvent(Event&)?
352  template <typename T, typename = void>
353  struct has_finalizeEvent : std::false_type {};
354 
355  template <typename T>
357  T,
358  enable_if_function_exists_t<void (T::*)(Event&), &T::finalizeEvent>>
359  : std::true_type {};
360 
361  template <typename T>
363  void
365  {}
366  };
367 
368  template <typename T>
370  void
372  {
373  t.finalizeEvent(e);
374  }
375  };
376 
377  ////////////////////////////////////////////////////////////////////
378 
379  ////////////////////////////////////////////////////////////////////
380  // Does the detail object have a method void beginSubRun(SubRun const &)?
381  template <typename T, typename = void>
382  struct has_beginSubRun : std::false_type {};
383 
384  template <typename T>
386  T,
387  enable_if_function_exists_t<void (T::*)(SubRun const&), &T::beginSubRun>>
388  : std::true_type {};
389 
390  template <typename T>
392  void
393  operator()(T&, SubRun const&)
394  {}
395  };
396 
397  template <typename T>
399  void
400  operator()(T& t, SubRun const& sr)
401  {
402  t.beginSubRun(sr);
403  }
404  };
405 
406  ////////////////////////////////////////////////////////////////////
407 
408  ////////////////////////////////////////////////////////////////////
409  // Does the detail object have a method void endSubRun(SubRun&)?
410  template <typename T, typename = void>
411  struct has_endSubRun : std::false_type {};
412 
413  template <typename T>
415  T,
416  enable_if_function_exists_t<void (T::*)(SubRun&), &T::endSubRun>>
417  : std::true_type {};
418 
419  template <typename T>
421  void
423  {}
424  };
425 
426  template <typename T>
427  struct call_endSubRun {
428  void
430  {
431  t.endSubRun(sr);
432  }
433  };
434 
435  ////////////////////////////////////////////////////////////////////
436 
437  ////////////////////////////////////////////////////////////////////
438  // Does the detail object have a method void beginRun(Run const &)?
439  template <typename T, typename = void>
440  struct has_beginRun : std::false_type {};
441 
442  template <typename T>
443  struct has_beginRun<
444  T,
445  enable_if_function_exists_t<void (T::*)(Run const&), &T::beginRun>>
446  : std::true_type {};
447 
448  template <typename T>
450  void
451  operator()(T&, Run const&)
452  {}
453  };
454 
455  template <typename T>
456  struct call_beginRun {
457  void
458  operator()(T& t, Run const& r)
459  {
460  t.beginRun(r);
461  }
462  };
463 
464  ////////////////////////////////////////////////////////////////////
465 
466  ////////////////////////////////////////////////////////////////////
467  // Does the detail object have a method void endRun(Run&)?
468  template <typename T, typename = void>
469  struct has_endRun : std::false_type {};
470 
471  template <typename T>
472  struct has_endRun<
473  T,
474  enable_if_function_exists_t<void (T::*)(Run&), &T::endRun>>
475  : std::true_type {};
476 
477  template <typename T>
479  void
481  {}
482  };
483 
484  template <typename T>
485  struct call_endRun {
486  void
488  {
489  t.endRun(r);
490  }
491  };
492 
493  ////////////////////////////////////////////////////////////////////
494 
495  ////////////////////////////////////////////////////////////////////
496  // Does the detail object have respondToXXX methods()?
497  template <typename T>
498  using respond_to_file = void (T::*)(FileBlock const&);
499 
500  template <typename T, respond_to_file<T>>
502 
503  template <typename T>
506  };
507 
508  template <typename T>
511  {
512  t.respondToOpenInputFile(fb);
513  }
514  };
515 
516  template <typename T>
519  {
520  t.respondToCloseInputFile(fb);
521  }
522  };
523 
524  template <typename T>
527  {
528  t.respondToOpenOutputFiles(fb);
529  }
530  };
531 
532  template <typename T>
535  {
536  t.respondToCloseOutputFiles(fb);
537  }
538  };
539 
540  // has_respondToOpenInputFile
541  template <typename T, typename = void>
542  struct has_respondToOpenInputFile : std::false_type {};
543 
544  template <typename T>
546  T,
548  &T::respondToOpenInputFile>>
549  : std::true_type {};
550 
551  // has_respondToCloseInputFile
552  template <typename T, typename = void>
553  struct has_respondToCloseInputFile : std::false_type {};
554 
555  template <typename T>
557  T,
559  &T::respondToCloseInputFile>>
560  : std::true_type {};
561 
562  // has_respondToOpenOutputFiles
563  template <typename T, typename = void>
564  struct has_respondToOpenOutputFiles : std::false_type {};
565 
566  template <typename T>
568  T,
570  &T::respondToOpenOutputFiles>>
571  : std::true_type {};
572 
573  // has_respondToCloseOutputFiles
574  template <typename T, typename = void>
575  struct has_respondToCloseOutputFiles : std::false_type {};
576 
577  template <typename T>
579  T,
581  &T::respondToCloseOutputFiles>>
582  : std::true_type {};
583 
584  ////////////////////////////////////////////////////////////////////
585 
586  } // detail namespace
587 
588 } // art namespace
589 
590 template <class T>
591 class art::MixFilter : public EDFilter {
592 public:
593  typedef T MixDetail;
594  explicit MixFilter(fhicl::ParameterSet const& p);
595 
596  void beginJob() override;
597  void respondToOpenInputFile(FileBlock const& fb) override;
598  void respondToCloseInputFile(FileBlock const& fb) override;
599  void respondToOpenOutputFiles(FileBlock const& fb) override;
600  void respondToCloseOutputFiles(FileBlock const& fb) override;
601  bool filter(Event& e) override;
602  bool beginSubRun(SubRun& sr) override;
603  bool endSubRun(SubRun& sr) override;
604  bool beginRun(Run& r) override;
605  bool endRun(Run& r) override;
606 
607 private:
608  fhicl::ParameterSet const& initEngine_(fhicl::ParameterSet const& p);
610  MixDetail detail_;
611 };
612 
613 template <class T>
615  : helper_(initEngine_(p), *this)
616  , // See note below
617  detail_(p, helper_)
618 {
619  // Note that the random number engine is created in the initializer
620  // list by calling initEngine(). This enables the engine to be
621  // obtained by the helper and or detail objects in their constructors
622  // via a service handle to the random number generator service. The
623  // initEngine() function returns a ParameterSet simply so that it may
624  // be called in this place without having to resort to comma-separated
625  // bundles to do the job.
629  maybe_setup_skipper(helper_, detail_);
630 }
631 
632 template <class T>
633 void
635 {}
636 
637 template <class T>
638 void
640 {
644 }
645 
646 template <class T>
647 void
649 {
653 }
654 
655 template <class T>
656 void
658 {
662 }
663 
664 template <class T>
665 void
667 {
671 }
672 
673 template <class T>
674 bool
676 {
677  // 1. Call detail object's startEvent() if it exists.
681  maybe_call_startEvent(e);
682  maybe_call_startEvent(detail_);
683  // 2. Ask detail object how many events to read.
684  size_t nSecondaries = detail_.nSecondaries();
685  // 3. Decide which events we're reading and prime the event tree cache.
686  EntryNumberSequence enSeq;
687  EventIDSequence eIDseq;
688  enSeq.reserve(nSecondaries);
689  eIDseq.reserve(nSecondaries);
690  if (!helper_.generateEventSequence(nSecondaries, enSeq, eIDseq)) {
692  << "Insufficient secondary events available to mix.\n";
693  }
694  // 4. Give the event ID sequence to the detail object.
698  maybe_call_processEventIDs;
699  maybe_call_processEventIDs(detail_, eIDseq);
700  // 5. Give the event auxiliary sequence to the detail object.
704  maybe_call_processEventAuxiliaries;
705  maybe_call_processEventAuxiliaries(detail_, helper_, enSeq, nSecondaries);
706  // 6. Make the MixHelper read info into all the products, invoke the
707  // mix functions and put the products into the event.
708  helper_.mixAndPut(enSeq, eIDseq, e);
709  // 7. Call detail object's finalizeEvent() if it exists.
713  maybe_call_finalizeEvent;
714  maybe_call_finalizeEvent(detail_, e);
715  return true;
716 }
717 
718 template <class T>
719 bool
721 {
725  maybe_call_beginSubRun;
726  maybe_call_beginSubRun(detail_, sr);
727  return true;
728 }
729 
730 template <class T>
731 bool
733 {
737  maybe_call_endSubRun;
738  maybe_call_endSubRun(detail_, sr);
739  return true;
740 }
741 
742 template <class T>
743 bool
745 {
749  maybe_call_beginRun;
750  maybe_call_beginRun(detail_, r);
751  return true;
752 }
753 
754 template <class T>
755 bool
757 {
761  maybe_call_endRun;
762  maybe_call_endRun(detail_, r);
763  return true;
764 }
765 
766 template <class T>
767 fhicl::ParameterSet const&
769 {
770  // If we can't create one of these, the helper will deal with the
771  // situation accordingly.
772  if (ServiceRegistry::isAvailable<RandomNumberGenerator>()) {
774  }
775  return p;
776 }
777 
778 #endif /* art_Framework_Modules_MixFilter_h */
779 
780 // Local Variables:
781 // mode: c++
782 // End:
void operator()(T &t, SubRun &sr)
Definition: MixFilter.h:429
std::vector< EventAuxiliary > EventAuxiliarySequence
Definition: MixTypes.h:24
std::vector< EventID > EventIDSequence
Definition: MixTypes.h:22
fhicl::ParameterSet const & initEngine_(fhicl::ParameterSet const &p)
Definition: MixFilter.h:768
void mixAndPut(EntryNumberSequence const &enSeq, EventIDSequence const &eIDseq, Event &e)
void setEventsToSkipFunction(std::function< size_t()> eventsToSkip)
void operator()(T &, SubRun const &)
Definition: MixFilter.h:393
void operator()(T &t, Run &r)
Definition: MixFilter.h:487
MixDetail detail_
Definition: MixFilter.h:610
const char * p
Definition: xmltok.h:285
void operator()(T &, MixHelper &, EntryNumberSequence const &, size_t)
Definition: MixFilter.h:329
base_engine_t & createEngine(seed_t seed)
void operator()(T &, Run const &)
Definition: MixFilter.h:451
enable_if_same_t< FT, decltype(f), R > enable_if_function_exists_t
seed_t get_seed_value(fhicl::ParameterSet const &pset, char const key[]="seed", seed_t const implicit_seed=-1)
void operator()(T &t, SubRun const &sr)
Definition: MixFilter.h:400
void respondToOpenInputFile(FileBlock const &fb) override
Definition: MixFilter.h:639
void beginJob() override
Definition: MixFilter.h:634
Definition: Run.h:31
Module that kips a configurable number of events between each that it allows through. Note that this module really skips (N-1) events, it uses a simple modular division as its critera. This module will cut down the data sample to 1/N of its original size.
void operator()(T &t, EventIDSequence const &seq)
Definition: MixFilter.h:304
bool generateEventSequence(size_t nSecondaries, EntryNumberSequence &enSeq, EventIDSequence &eIDseq)
do_not_call_respondToXXX(T &, FileBlock const &)
Definition: MixFilter.h:505
const XML_Char int const XML_Char * value
Definition: expat.h:331
void beginJob()
void operator()(T &t, Event &e)
Definition: MixFilter.h:371
do_not_setup_eventsToSkip(MixHelper &, T &)
Definition: MixFilter.h:260
void respondToCloseOutputFiles(FileBlock const &fb) override
Definition: MixFilter.h:666
void respondToOpenOutputFiles(FileBlock const &fb) override
Definition: MixFilter.h:657
call_respondToOpenInputFile(T &t, FileBlock const &fb)
Definition: MixFilter.h:510
void generateEventAuxiliarySequence(EntryNumberSequence const &, EventAuxiliarySequence &)
void operator()(T &, SubRun &)
Definition: MixFilter.h:422
caf::StandardRecord * sr
call_startEvent(Event const &e)
Definition: MixFilter.h:227
std::vector< FileIndex::EntryNumber_t > EntryNumberSequence
Definition: MixTypes.h:23
void(T::*)(FileBlock const &) respond_to_file
Definition: MixFilter.h:498
bool beginSubRun(SubRun &sr) override
Definition: MixFilter.h:720
call_respondToCloseInputFile(T &t, FileBlock const &fb)
Definition: MixFilter.h:518
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
bool filter(Event &e) override
Definition: MixFilter.h:675
void respondToCloseInputFile(FileBlock const &fb) override
Definition: MixFilter.h:648
call_respondToOpenOutputFiles(T &t, FileBlock const &fb)
Definition: MixFilter.h:526
MixFilter(fhicl::ParameterSet const &p)
Definition: MixFilter.h:614
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void operator()(T &t, MixHelper &h, EntryNumberSequence const &enseq, size_t nSecondaries)
Definition: MixFilter.h:336
TRandom3 r(0)
Service to store calibration data products (CDP) in the SQLite3 metadatabase of a file...
Definition: FillParentInfo.h:8
void operator()(T &, EventIDSequence const &)
Definition: MixFilter.h:297
void operator()(T &t, Run const &r)
Definition: MixFilter.h:458
double T
Definition: Xdiff_gwt.C:5
bool beginRun(Run &r) override
Definition: MixFilter.h:744
bool endRun(Run &r) override
Definition: MixFilter.h:756
MixHelper helper_
Definition: MixFilter.h:609
Float_t e
Definition: plot.C:35
typedef void(XMLCALL *XML_ElementDeclHandler)(void *userData
void operator()(T &, Run &)
Definition: MixFilter.h:480
size_t call_eventsToSkip(T &t)
Definition: MixFilter.h:265
bool endSubRun(SubRun &sr) override
Definition: MixFilter.h:732
setup_eventsToSkip(MixHelper &helper, T &t)
Definition: MixFilter.h:272
call_respondToCloseOutputFiles(T &t, FileBlock const &fb)
Definition: MixFilter.h:534