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 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 //
103 ////////////////////////////////////////////////////////////////////////
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 //
139 ////////////////////////////////////////////////////////////////////////
140 
146 #include "cetlib/metaprogramming.h"
149 
150 #include <functional>
151 #include <memory>
152 #include <type_traits>
153 
154 namespace art {
155  template <typename T, typename IOPolicy>
156  class MixFilter;
157 
158  template <typename T>
160  public:
161  using value_type = T;
162 
163  auto const&
164  operator()() const
165  {
166  return fragment_();
167  }
168 
169  private:
171  };
172 
173  namespace detail {
174  // Template metaprogramming.
176 
177  ////////////////////////////////////////////////////////////////////
178  // Does the detail object have a method void startEvent()?
179 
180  template <typename T, typename = void>
181  struct has_startEvent : std::false_type {};
182 
183  template <typename T>
185  T,
186  enable_if_function_exists_t<void (T::*)(Event const&), &T::startEvent>>
187  : std::true_type {};
188 
189  ////////////////////////////////////////////////////////////////////
190 
191  ////////////////////////////////////////////////////////////////////
192  // Does the detail object have a method size_t eventsToSkip() const?
193 
194  template <typename T, typename = void>
195  struct has_eventsToSkip : std::false_type {};
196 
197  template <typename T>
199  T,
200  enable_if_function_exists_t<size_t (T::*)(), &T::eventsToSkip>>
201  : std::true_type {};
202 
203  template <typename T>
205  T,
206  enable_if_function_exists_t<size_t (T::*)() const, &T::eventsToSkip>>
207  : std::true_type {};
208  ////////////////////////////////////////////////////////////////////
209 
210  ////////////////////////////////////////////////////////////////////
211  // Does the detail object have a method void
212  // processEventIDs(EventIDSequence const&)?
213 
214  template <typename T, typename = void>
215  struct has_processEventIDs : std::false_type {};
216 
217  template <typename T>
219  T,
220  enable_if_function_exists_t<void (T::*)(EventIDSequence const&),
221  &T::processEventIDs>> : std::true_type {};
222 
223  ////////////////////////////////////////////////////////////////////
224 
225  ////////////////////////////////////////////////////////////////////
226  // Does the detail object have a method void
227  // processEventAuxiliaries(EventAuxiliarySequence const&)?
228 
229  template <typename T, typename = void>
230  struct has_processEventAuxiliaries : std::false_type {};
231 
232  template <typename T>
234  T,
235  enable_if_function_exists_t<void (T::*)(EventAuxiliarySequence const&),
236  &T::processEventAuxiliaries>>
237  : std::true_type {};
238 
239  ////////////////////////////////////////////////////////////////////
240 
241  ////////////////////////////////////////////////////////////////////
242  // Does the detail object have a method void finalizeEvent(Event&)?
243  template <typename T, typename = void>
244  struct has_finalizeEvent : std::false_type {};
245 
246  template <typename T>
248  T,
249  enable_if_function_exists_t<void (T::*)(Event&), &T::finalizeEvent>>
250  : std::true_type {};
251 
252  ////////////////////////////////////////////////////////////////////
253 
254  ////////////////////////////////////////////////////////////////////
255  // Does the detail object have a method void beginSubRun(SubRun const&)?
256  template <typename T, typename = void>
257  struct has_beginSubRun : std::false_type {};
258 
259  template <typename T>
261  T,
262  enable_if_function_exists_t<void (T::*)(SubRun const&), &T::beginSubRun>>
263  : std::true_type {};
264 
265  ////////////////////////////////////////////////////////////////////
266 
267  ////////////////////////////////////////////////////////////////////
268  // Does the detail object have a method void endSubRun(SubRun&)?
269  template <typename T, typename = void>
270  struct has_endSubRun : std::false_type {};
271 
272  template <typename T>
274  T,
275  enable_if_function_exists_t<void (T::*)(SubRun&), &T::endSubRun>>
276  : std::true_type {};
277 
278  ////////////////////////////////////////////////////////////////////
279 
280  ////////////////////////////////////////////////////////////////////
281  // Does the detail object have a method void beginRun(Run const&)?
282  template <typename T, typename = void>
283  struct has_beginRun : std::false_type {};
284 
285  template <typename T>
286  struct has_beginRun<
287  T,
288  enable_if_function_exists_t<void (T::*)(Run const&), &T::beginRun>>
289  : std::true_type {};
290 
291  ////////////////////////////////////////////////////////////////////
292 
293  ////////////////////////////////////////////////////////////////////
294  // Does the detail object have a method void endRun(Run&)?
295  template <typename T, typename = void>
296  struct has_endRun : std::false_type {};
297 
298  template <typename T>
299  struct has_endRun<
300  T,
301  enable_if_function_exists_t<void (T::*)(Run&), &T::endRun>>
302  : std::true_type {};
303 
304  ////////////////////////////////////////////////////////////////////
305 
306  ////////////////////////////////////////////////////////////////////
307  // Does the detail object have respondToXXX methods()?
308  template <typename T>
309  using respond_to_file = void (T::*)(FileBlock const&);
310 
311  template <typename T, respond_to_file<T>>
313 
314  // has_respondToOpenInputFile
315  template <typename T, typename = void>
316  struct has_respondToOpenInputFile : std::false_type {};
317 
318  template <typename T>
320  T,
322  &T::respondToOpenInputFile>>
323  : std::true_type {};
324 
325  // has_respondToCloseInputFile
326  template <typename T, typename = void>
327  struct has_respondToCloseInputFile : std::false_type {};
328 
329  template <typename T>
331  T,
333  &T::respondToCloseInputFile>>
334  : std::true_type {};
335 
336  // has_respondToOpenOutputFiles
337  template <typename T, typename = void>
338  struct has_respondToOpenOutputFiles : std::false_type {};
339 
340  template <typename T>
342  T,
344  &T::respondToOpenOutputFiles>>
345  : std::true_type {};
346 
347  // has_respondToCloseOutputFiles
348  template <typename T, typename = void>
349  struct has_respondToCloseOutputFiles : std::false_type {};
350 
351  template <typename T>
353  T,
355  &T::respondToCloseOutputFiles>>
356  : std::true_type {};
357 
358  ////////////////////////////////////////////////////////////////////
359 
360  ////////////////////////////////////////////////////////////////////
361  // Does the detail object have a Parameters type?
362  template <typename T, typename = void>
363  struct maybe_has_Parameters : std::false_type {
365  };
366 
367  template <typename T>
368  struct maybe_has_Parameters<T, std::void_t<typename T::Parameters>>
369  : std::true_type {
370  using user_config_t = typename T::Parameters;
371  struct Config {
374  };
376  };
377 
378  } // namespace detail
379 
380 } // namespace art
381 
382 template <typename T, typename IOPolicy>
383 class art::MixFilter : public EDFilter {
384 public:
385  using MixDetail = T;
386 
388 
389  template <typename U = Parameters>
390  explicit MixFilter(std::enable_if_t<std::is_same_v<U, fhicl::ParameterSet>,
391  fhicl::ParameterSet> const& p);
392  template <typename U = Parameters>
393  explicit MixFilter(
394  std::enable_if_t<!std::is_same_v<U, fhicl::ParameterSet>, U> const& p);
395 
396 private:
397  void respondToOpenInputFile(FileBlock const& fb) override;
398  void respondToCloseInputFile(FileBlock const& fb) override;
399  void respondToOpenOutputFiles(FileBlock const& fb) override;
400  void respondToCloseOutputFiles(FileBlock const& fb) override;
401  bool filter(Event& e) override;
402  bool beginSubRun(SubRun& sr) override;
403  bool endSubRun(SubRun& sr) override;
404  bool beginRun(Run& r) override;
405  bool endRun(Run& r) override;
406 
409 };
410 
411 template <typename T, typename IOPolicy>
412 template <typename U>
414  std::enable_if_t<std::is_same_v<U, fhicl::ParameterSet>,
415  fhicl::ParameterSet> const& p)
416  : EDFilter{p}
417  , helper_{p,
418  p.template get<std::string>("module_label"),
420  std::make_unique<IOPolicy>()}
421  , detail_{p, helper_}
422 {
423  if constexpr (detail::has_eventsToSkip<T>::value) {
424  helper_.setEventsToSkipFunction([this] { return detail_.eventsToSkip(); });
425  }
426 }
427 
428 template <typename T, typename IOPolicy>
429 template <typename U>
431  std::enable_if_t<!std::is_same_v<U, fhicl::ParameterSet>, U> const& p)
432  : EDFilter{p}
433  , helper_{p().mixHelper(),
434  p.get_PSet().template get<std::string>("module_label"),
436  std::make_unique<IOPolicy>()}
437  , detail_{p().userConfig, helper_}
438 {
439  if constexpr (detail::has_eventsToSkip<T>::value) {
440  helper_.setEventsToSkipFunction([this] { return detail_.eventsToSkip(); });
441  }
442 }
443 
444 template <typename T, typename IOPolicy>
445 void
447 {
449  detail_.respondToOpenInputFile(fb);
450  }
451 }
452 
453 template <typename T, typename IOPolicy>
454 void
456 {
458  detail_.respondToCloseInputFile(fb);
459  }
460 }
461 
462 template <typename T, typename IOPolicy>
463 void
465 {
467  detail_.respondToOpenOutputFiles(fb);
468  }
469 }
470 
471 template <typename T, typename IOPolicy>
472 void
474 {
476  detail_.respondToCloseOutputFiles(fb);
477  }
478 }
479 
480 template <typename T, typename IOPolicy>
481 bool
483 {
484  // 1. Call detail object's startEvent() if it exists.
485  if constexpr (detail::has_startEvent<T>::value) {
486  detail_.startEvent(e);
487  }
488 
489  // 2. Ask detail object how many events to read.
490  size_t const nSecondaries = detail_.nSecondaries();
491 
492  // 3. Decide which events we're reading and prime the event tree
493  // cache.
494  EntryNumberSequence enSeq;
495  EventIDSequence eIDseq;
496  enSeq.reserve(nSecondaries);
497  eIDseq.reserve(nSecondaries);
498  if (!helper_.generateEventSequence(nSecondaries, enSeq, eIDseq)) {
500  << "Insufficient secondary events available to mix.\n";
501  }
502 
503  // 4. Give the event ID sequence to the detail object.
505  detail_.processEventIDs(eIDseq);
506  }
507 
508  // 5. Give the event auxiliary sequence to the detail object.
510  auto const auxseq = helper_.generateEventAuxiliarySequence(enSeq);
511  detail_.processEventAuxiliaries(auxseq);
512  }
513 
514  // 6. Make the MixHelper read info into all the products, invoke the
515  // mix functions and put the products into the event.
516  helper_.mixAndPut(enSeq, eIDseq, e);
517 
518  // 7. Call detail object's finalizeEvent() if it exists.
519  if constexpr (detail::has_finalizeEvent<T>::value) {
520  detail_.finalizeEvent(e);
521  }
522  return true;
523 }
524 
525 template <typename T, typename IOPolicy>
526 bool
528 {
529  if constexpr (detail::has_beginSubRun<T>::value) {
530  detail_.beginSubRun(sr);
531  }
532  return true;
533 }
534 
535 template <typename T, typename IOPolicy>
536 bool
538 {
539  if constexpr (detail::has_endSubRun<T>::value) {
540  detail_.endSubRun(sr);
541  }
542  return true;
543 }
544 
545 template <typename T, typename IOPolicy>
546 bool
548 {
549  if constexpr (detail::has_beginRun<T>::value) {
550  detail_.beginRun(r);
551  }
552  return true;
553 }
554 
555 template <typename T, typename IOPolicy>
556 bool
558 {
559  if constexpr (detail::has_endRun<T>::value) {
560  detail_.endRun(r);
561  }
562  return true;
563 }
564 
565 #endif /* art_Framework_Modules_MixFilter_h */
566 
567 // Local Variables:
568 // mode: c++
569 // End:
std::vector< EventID > EventIDSequence
Definition: MixTypes.h:26
void mixAndPut(EntryNumberSequence const &enSeq, EventIDSequence const &eIDseq, Event &e)
void setEventsToSkipFunction(std::function< size_t()> eventsToSkip)
typename detail::maybe_has_Parameters< T >::Parameters Parameters
Definition: MixFilter.h:387
bool beginRun(Run &r) override
Definition: MixFilter.h:547
const char * p
Definition: xmltok.h:285
void respondToOpenInputFile(FileBlock const &fb) override
Definition: MixFilter.h:446
void respondToCloseInputFile(FileBlock const &fb) override
Definition: MixFilter.h:455
enable_if_same_t< FT, decltype(f), R > enable_if_function_exists_t
bool endRun(Run &r) override
Definition: MixFilter.h:557
Definition: Run.h:21
bool generateEventSequence(size_t nSecondaries, EntryNumberSequence &enSeq, EventIDSequence &eIDseq)
void respondToCloseOutputFiles(FileBlock const &fb) override
Definition: MixFilter.h:473
typename config_impl< T >::type Config
Definition: ModuleMacros.h:54
void respondToOpenOutputFiles(FileBlock const &fb) override
Definition: MixFilter.h:464
bool filter(Event &e) override
Definition: MixFilter.h:482
caf::StandardRecord * sr
std::vector< FileIndex::EntryNumber_t > EntryNumberSequence
Definition: MixTypes.h:27
bool endSubRun(SubRun &sr) override
Definition: MixFilter.h:537
MixHelper helper_
Definition: MixFilter.h:407
MixFilter(std::enable_if_t< std::is_same_v< U, fhicl::ParameterSet >, fhicl::ParameterSet > const &p)
Definition: MixFilter.h:413
void(T::*)(FileBlock const &) respond_to_file
Definition: MixFilter.h:309
ProducesCollector & producesCollector() noexcept
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
bool beginSubRun(SubRun &sr) override
Definition: MixFilter.h:527
auto const & operator()() const
Definition: MixFilter.h:164
TRandom3 r(0)
Service to store calibration data products (CDP) in the SQLite3 metadatabase of a file...
Definition: FillParentInfo.h:8
double T
Definition: Xdiff_gwt.C:5
Float_t e
Definition: plot.C:35
typedef void(XMLCALL *XML_ElementDeclHandler)(void *userData
MixDetail detail_
Definition: MixFilter.h:408
fhicl::TableFragment< T > fragment_
Definition: MixFilter.h:170
EventAuxiliarySequence generateEventAuxiliarySequence(EntryNumberSequence const &)