LArSoft  v07_13_02
Liquid Argon Software toolkit - http://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 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 //
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 //
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.
157  using cet::enable_if_function_exists_t;
158 
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 
165  template <typename T>
167  T,
168  enable_if_function_exists_t<void (T::*)(), &T::startEvent>>
169  : std::true_type {
170  };
171 
172  template <typename T>
174  public:
175  void
177  {
178  static bool need_warning = true;
179  if (need_warning) {
180  mf::LogWarning("Deprecated")
181  << "Mixing driver function has signature startEvent(), which is "
182  "deprecated.\n"
183  << "Please update your code to define startEvent(Event const &).\n"
184  << "In a future version of ART the old method will no longer be "
185  "called.";
186  need_warning = false;
187  }
188  t.startEvent();
189  }
190  };
191 
192  template <typename T>
194  void
196  {}
197  };
198 
199  template <typename T>
201  public:
203  void
205  {
209  maybe_call_old_startEvent;
210  maybe_call_old_startEvent(t);
211  }
212 
213  private:
214  };
216 
217  template <typename T, typename = void>
218  struct has_startEvent : std::false_type {
219  };
220 
221  template <typename T>
223  T,
224  enable_if_function_exists_t<void (T::*)(Event const&), &T::startEvent>>
225  : std::true_type {
226  };
227 
228  template <typename T>
230  public:
231  call_startEvent(Event const& e) : e_(e) {}
232  void
234  {
235  t.startEvent(e_);
236  }
237 
238  private:
239  Event const& e_;
240  };
241 
243 
245  // Does the detail object have a method size_t eventsToSkip() const?
246 
247  template <typename T, typename = void>
248  struct has_eventsToSkip : std::false_type {
249  };
250 
251  template <typename T>
253  T,
254  enable_if_function_exists_t<size_t (T::*)(), &T::eventsToSkip>>
255  : std::true_type {
256  };
257 
258  template <typename T>
260  T,
261  enable_if_function_exists_t<size_t (T::*)() const, &T::eventsToSkip>>
262  : std::true_type {
263  };
264 
265  template <typename T>
268  };
269 
270  template <typename T>
271  size_t
273  {
274  return t.eventsToSkip();
275  }
276 
277  template <typename T>
280  {
282  std::bind(&detail::call_eventsToSkip<T>, std::ref(t)));
283  }
284  };
285 
287 
289  // Does the detail object have a method void
290  // processEventIDs(EventIDSequence const &)?
291 
292  template <typename T, typename = void>
293  struct has_processEventIDs : std::false_type {
294  };
295 
296  template <typename T>
298  T,
299  enable_if_function_exists_t<void (T::*)(EventIDSequence const&),
300  &T::processEventIDs>> : std::true_type {
301  };
302 
303  template <typename T>
305  void
307  {}
308  };
309 
310  template <typename T>
312  void
313  operator()(T& t, EventIDSequence const& seq)
314  {
315  t.processEventIDs(seq);
316  }
317  };
318 
320 
322  // Does the detail object have a method void
323  // processEventAuxiliaries(EventAuxiliarySequence const &)?
324 
325  template <typename T, typename = void>
326  struct has_processEventAuxiliaries : std::false_type {
327  };
328 
329  template <typename T>
331  T,
332  enable_if_function_exists_t<void (T::*)(EventAuxiliarySequence const&),
333  &T::processEventAuxiliaries>>
334  : std::true_type {
335  };
336 
337  template <typename T>
339  void
341  {}
342  };
343 
344  template <typename T>
346  void
348  MixHelper& h,
349  EntryNumberSequence const& enseq,
350  size_t nSecondaries)
351  {
352  EventAuxiliarySequence auxseq;
353  auxseq.reserve(nSecondaries);
354  h.generateEventAuxiliarySequence(enseq, auxseq);
355  t.processEventAuxiliaries(auxseq);
356  }
357  };
358 
360 
362  // Does the detail object have a method void finalizeEvent(Event&)?
363  template <typename T, typename = void>
364  struct has_finalizeEvent : std::false_type {
365  };
366 
367  template <typename T>
369  T,
370  enable_if_function_exists_t<void (T::*)(Event&), &T::finalizeEvent>>
371  : std::true_type {
372  };
373 
374  template <typename T>
376  void
378  {}
379  };
380 
381  template <typename T>
383  void
385  {
386  t.finalizeEvent(e);
387  }
388  };
389 
391 
393  // Does the detail object have a method void beginSubRun(SubRun const &)?
394  template <typename T, typename = void>
395  struct has_beginSubRun : std::false_type {
396  };
397 
398  template <typename T>
400  T,
401  enable_if_function_exists_t<void (T::*)(SubRun const&), &T::beginSubRun>>
402  : std::true_type {
403  };
404 
405  template <typename T>
407  void
408  operator()(T&, SubRun const&)
409  {}
410  };
411 
412  template <typename T>
414  void
415  operator()(T& t, SubRun const& sr)
416  {
417  t.beginSubRun(sr);
418  }
419  };
420 
422 
424  // Does the detail object have a method void endSubRun(SubRun&)?
425  template <typename T, typename = void>
426  struct has_endSubRun : std::false_type {
427  };
428 
429  template <typename T>
431  T,
432  enable_if_function_exists_t<void (T::*)(SubRun&), &T::endSubRun>>
433  : std::true_type {
434  };
435 
436  template <typename T>
438  void
440  {}
441  };
442 
443  template <typename T>
444  struct call_endSubRun {
445  void
446  operator()(T& t, SubRun& sr)
447  {
448  t.endSubRun(sr);
449  }
450  };
451 
453 
455  // Does the detail object have a method void beginRun(Run const &)?
456  template <typename T, typename = void>
457  struct has_beginRun : std::false_type {
458  };
459 
460  template <typename T>
461  struct has_beginRun<
462  T,
463  enable_if_function_exists_t<void (T::*)(Run const&), &T::beginRun>>
464  : std::true_type {
465  };
466 
467  template <typename T>
469  void
470  operator()(T&, Run const&)
471  {}
472  };
473 
474  template <typename T>
475  struct call_beginRun {
476  void
477  operator()(T& t, Run const& r)
478  {
479  t.beginRun(r);
480  }
481  };
482 
484 
486  // Does the detail object have a method void endRun(Run&)?
487  template <typename T, typename = void>
488  struct has_endRun : std::false_type {
489  };
490 
491  template <typename T>
492  struct has_endRun<
493  T,
494  enable_if_function_exists_t<void (T::*)(Run&), &T::endRun>>
495  : std::true_type {
496  };
497 
498  template <typename T>
500  void
502  {}
503  };
504 
505  template <typename T>
506  struct call_endRun {
507  void
508  operator()(T& t, Run& r)
509  {
510  t.endRun(r);
511  }
512  };
513 
515 
517  // Does the detail object have respondToXXX methods()?
518  template <typename T>
519  using respond_to_file = void (T::*)(FileBlock const&);
520 
521  template <typename T, respond_to_file<T>>
523 
524  template <typename T>
527  };
528 
529  template <typename T>
532  {
533  t.respondToOpenInputFile(fb);
534  }
535  };
536 
537  template <typename T>
540  {
541  t.respondToCloseInputFile(fb);
542  }
543  };
544 
545  template <typename T>
548  {
549  t.respondToOpenOutputFiles(fb);
550  }
551  };
552 
553  template <typename T>
556  {
557  t.respondToCloseOutputFiles(fb);
558  }
559  };
560 
561  // has_respondToOpenInputFile
562  template <typename T, typename = void>
563  struct has_respondToOpenInputFile : std::false_type {
564  };
565 
566  template <typename T>
568  T,
569  enable_if_function_exists_t<respond_to_file<T>,
570  &T::respondToOpenInputFile>>
571  : std::true_type {
572  };
573 
574  // has_respondToCloseInputFile
575  template <typename T, typename = void>
576  struct has_respondToCloseInputFile : std::false_type {
577  };
578 
579  template <typename T>
581  T,
582  enable_if_function_exists_t<respond_to_file<T>,
583  &T::respondToCloseInputFile>>
584  : std::true_type {
585  };
586 
587  // has_respondToOpenOutputFiles
588  template <typename T, typename = void>
589  struct has_respondToOpenOutputFiles : std::false_type {
590  };
591 
592  template <typename T>
594  T,
595  enable_if_function_exists_t<respond_to_file<T>,
596  &T::respondToOpenOutputFiles>>
597  : std::true_type {
598  };
599 
600  // has_respondToCloseOutputFiles
601  template <typename T, typename = void>
602  struct has_respondToCloseOutputFiles : std::false_type {
603  };
604 
605  template <typename T>
607  T,
608  enable_if_function_exists_t<respond_to_file<T>,
609  &T::respondToCloseOutputFiles>>
610  : std::true_type {
611  };
612 
614 
615  } // detail namespace
616 
617 } // art namespace
618 
619 template <class T>
620 class art::MixFilter : public EDFilter {
621 public:
622  typedef T MixDetail;
623  explicit MixFilter(fhicl::ParameterSet const& p);
624 
625  void beginJob() override;
626  void respondToOpenInputFile(FileBlock const& fb) override;
627  void respondToCloseInputFile(FileBlock const& fb) override;
628  void respondToOpenOutputFiles(FileBlock const& fb) override;
629  void respondToCloseOutputFiles(FileBlock const& fb) override;
630  bool filter(Event& e) override;
631  bool beginSubRun(SubRun& sr) override;
632  bool endSubRun(SubRun& sr) override;
633  bool beginRun(Run& r) override;
634  bool endRun(Run& r) override;
635 
636 private:
637  fhicl::ParameterSet const& initEngine_(fhicl::ParameterSet const& p);
639  MixDetail detail_;
640 };
641 
642 template <class T>
644  : helper_(initEngine_(p), *this)
645  , // See note below
646  detail_(p, helper_)
647 {
648  // Note that the random number engine is created in the initializer
649  // list by calling initEngine(). This enables the engine to be
650  // obtained by the helper and or detail objects in their constructors
651  // via a service handle to the random number generator service. The
652  // initEngine() function returns a ParameterSet simply so that it may
653  // be called in this place without having to resort to comma-separated
654  // bundles to do the job.
658  maybe_setup_skipper(helper_, detail_);
659 }
660 
661 template <class T>
662 void
664 {}
665 
666 template <class T>
667 void
669 {
673 }
674 
675 template <class T>
676 void
678 {
682 }
683 
684 template <class T>
685 void
687 {
691 }
692 
693 template <class T>
694 void
696 {
700 }
701 
702 template <class T>
703 bool
705 {
706  // 1. Call detail object's startEvent() if it exists.
710  maybe_call_startEvent(e);
711  maybe_call_startEvent(detail_);
712  // 2. Ask detail object how many events to read.
713  size_t nSecondaries = detail_.nSecondaries();
714  // 3. Decide which events we're reading and prime the event tree cache.
715  EntryNumberSequence enSeq;
716  EventIDSequence eIDseq;
717  enSeq.reserve(nSecondaries);
718  eIDseq.reserve(nSecondaries);
719  if (!helper_.generateEventSequence(nSecondaries, enSeq, eIDseq)) {
721  << "Insufficient secondary events available to mix.\n";
722  }
723  // 4. Give the event ID sequence to the detail object.
727  maybe_call_processEventIDs;
728  maybe_call_processEventIDs(detail_, eIDseq);
729  // 5. Give the event auxiliary sequence to the detail object.
733  maybe_call_processEventAuxiliaries;
734  maybe_call_processEventAuxiliaries(detail_, helper_, enSeq, nSecondaries);
735  // 6. Make the MixHelper read info into all the products, invoke the
736  // mix functions and put the products into the event.
737  helper_.mixAndPut(enSeq, eIDseq, e);
738  // 7. Call detail object's finalizeEvent() if it exists.
742  maybe_call_finalizeEvent;
743  maybe_call_finalizeEvent(detail_, e);
744  return true;
745 }
746 
747 template <class T>
748 bool
750 {
754  maybe_call_beginSubRun;
755  maybe_call_beginSubRun(detail_, sr);
756  return true;
757 }
758 
759 template <class T>
760 bool
762 {
766  maybe_call_endSubRun;
767  maybe_call_endSubRun(detail_, sr);
768  return true;
769 }
770 
771 template <class T>
772 bool
774 {
778  maybe_call_beginRun;
779  maybe_call_beginRun(detail_, r);
780  return true;
781 }
782 
783 template <class T>
784 bool
786 {
790  maybe_call_endRun;
791  maybe_call_endRun(detail_, r);
792  return true;
793 }
794 
795 template <class T>
796 fhicl::ParameterSet const&
798 {
799  // If we can't create one of these, the helper will deal with the
800  // situation accordingly.
801  if (ServiceRegistry::isAvailable<RandomNumberGenerator>()) {
803  }
804  return p;
805 }
806 
807 #endif /* art_Framework_Modules_MixFilter_h */
808 
809 // Local Variables:
810 // mode: c++
811 // End:
seed_t get_seed_value(fhicl::ParameterSet const &pset, char const key[]="seed", seed_t const implicit_seed=-1)
void operator()(T &t, SubRun &sr)
Definition: MixFilter.h:446
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:797
void mixAndPut(EntryNumberSequence const &enSeq, EventIDSequence const &eIDseq, Event &e)
Definition: MixHelper.cc:240
void setEventsToSkipFunction(std::function< size_t()> eventsToSkip)
Definition: MixHelper.cc:310
void operator()(T &, SubRun const &)
Definition: MixFilter.h:408
void operator()(T &t, Run &r)
Definition: MixFilter.h:508
MixDetail detail_
Definition: MixFilter.h:639
void operator()(T &, MixHelper &, EntryNumberSequence const &, size_t)
Definition: MixFilter.h:340
void operator()(T &, Run const &)
Definition: MixFilter.h:470
void operator()(T &t, SubRun const &sr)
Definition: MixFilter.h:415
void respondToOpenInputFile(FileBlock const &fb) override
Definition: MixFilter.h:668
void beginJob() override
Definition: MixFilter.h:663
Definition: Run.h:30
Framework includes.
void operator()(T &t, EventIDSequence const &seq)
Definition: MixFilter.h:313
bool generateEventSequence(size_t nSecondaries, EntryNumberSequence &enSeq, EventIDSequence &eIDseq)
Definition: MixHelper.cc:143
do_not_call_respondToXXX(T &, FileBlock const &)
Definition: MixFilter.h:526
base_engine_t & createEngine(seed_t seed)
void beginJob()
Definition: Breakpoints.cc:14
void operator()(T &t, Event &e)
Definition: MixFilter.h:384
do_not_setup_eventsToSkip(MixHelper &, T &)
Definition: MixFilter.h:267
void respondToCloseOutputFiles(FileBlock const &fb) override
Definition: MixFilter.h:695
TFile fb("Li6.root")
void respondToOpenOutputFiles(FileBlock const &fb) override
Definition: MixFilter.h:686
call_respondToOpenInputFile(T &t, FileBlock const &fb)
Definition: MixFilter.h:531
void generateEventAuxiliarySequence(EntryNumberSequence const &, EventAuxiliarySequence &)
Definition: MixHelper.cc:212
void operator()(T &, SubRun &)
Definition: MixFilter.h:439
call_startEvent(Event const &e)
Definition: MixFilter.h:231
std::vector< FileIndex::EntryNumber_t > EntryNumberSequence
Definition: MixTypes.h:23
void(T::*)(FileBlock const &) respond_to_file
Definition: MixFilter.h:519
bool beginSubRun(SubRun &sr) override
Definition: MixFilter.h:749
call_respondToCloseInputFile(T &t, FileBlock const &fb)
Definition: MixFilter.h:539
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
bool filter(Event &e) override
Definition: MixFilter.h:704
void respondToCloseInputFile(FileBlock const &fb) override
Definition: MixFilter.h:677
call_respondToOpenOutputFiles(T &t, FileBlock const &fb)
Definition: MixFilter.h:547
std::string value(boost::any const &)
MixFilter(fhicl::ParameterSet const &p)
Definition: MixFilter.h:643
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void operator()(T &t, MixHelper &h, EntryNumberSequence const &enseq, size_t nSecondaries)
Definition: MixFilter.h:347
HLT enums.
void operator()(T &, EventIDSequence const &)
Definition: MixFilter.h:306
void operator()(T &t, Run const &r)
Definition: MixFilter.h:477
bool beginRun(Run &r) override
Definition: MixFilter.h:773
bool endRun(Run &r) override
Definition: MixFilter.h:785
MixHelper helper_
Definition: MixFilter.h:638
Float_t e
Definition: plot.C:34
void operator()(T &, Run &)
Definition: MixFilter.h:501
size_t call_eventsToSkip(T &t)
Definition: MixFilter.h:272
bool endSubRun(SubRun &sr) override
Definition: MixFilter.h:761
setup_eventsToSkip(MixHelper &helper, T &t)
Definition: MixFilter.h:279
call_respondToCloseOutputFiles(T &t, FileBlock const &fb)
Definition: MixFilter.h:555