LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
MixHelper.h
Go to the documentation of this file.
1 #ifndef art_Framework_IO_ProductMix_MixHelper_h
2 #define art_Framework_IO_ProductMix_MixHelper_h
3 // MixHelper
5 //
6 // Class providing, at construction time, registration services to
7 // users' "detail" mixing classes. (A "detail" class is the template
8 // argument to the instantiation of the "MixFilter" module template.)
9 //
11 // Configuration.
12 //
13 // MixHelper will be passed the configuration of the module. The
14 // following items are significant:
15 //
16 // fileNames (default empty)
17 //
18 // Sequence of secondary files for mixing. However, see the function
19 // registerSecondaryFileNameProvider(...) below. If a secondary file
20 // name provider is *not* registered, it is an error to have an
21 // empty fileNames.
22 //
23 // readMode (default sequential).
24 //
25 // Specify how events should be chosen from each file. Valid values
26 // are:
27 //
28 // sequential -- read the secondary events in order
29 // randomReplace -- random with replacement
30 // randomLimReplace -- events unique within a primary event
31 // randomNoReplace -- events guaranteed to be used once only.
32 //
33 // coverageFraction (default 1.0).
34 //
35 // Ratio of sampled to total events in a file. Used by randomReplace
36 // and randomLimReplace modes only.
37 //
38 // wrapFiles (default false).
39 //
40 // Re-start from fileNames[0] after secondary events are exhausted. If
41 // this is false, exhausting the secondary file stream will result in
42 // the filter returning false for the remainder of the job.
43 //
44 // compactMissingProducts (default false).
45 //
46 // In the case of a secondary event missing a particular product,
47 // the sequence of product pointers passed to the MixOp will be
48 // compacted to remove nullptrs.
49 //
51 // readMode()
52 //
53 // Return the enumerated value representing the event mixing strategy.
54 //
56 // registerSecondaryFileNameProvider(<function> func)
57 //
58 // Register the provided function as a provider of file names for
59 // mixing. This should be called from the constructor of your detail
60 // object.
61 //
62 // <function> must be convertible to std::function<std::string ()>. A
63 // free function taking no arguments and returning std::string, a
64 // functor whose operator () has the same signature, or a bound free or
65 // member function whose signature after binding is std::string () are
66 // all convertible to std::function<std::string()>.
67 //
68 // E.g. for a detail class with member function std::string getMixFile():
69 //
70 // registerSecondaryFileNameProvider(std::bind(&Detail::getMixFile, this));
71 //
72 // Notes:
73 //
74 // 1. It is a configuration error to provide a non-empty fileNames
75 // parameter to a module which registers a file name provider.
76 //
77 // 2. If the file name provider returns a string which is empty, the
78 // MixFilter shall thenceforth return false.
79 //
80 // 3. If the file name provider returns a non-empty string that does not
81 // correspond to a readable file, an exception shall be thrown.
82 //
84 // declareMixOp templates.
85 //
86 // These function templates should be used by writers of product-mixing
87 // "detail" classes to declare each product mix operation.
88 //
89 // All of the declareMixOp(...) function templates have the following
90 // template arguments:
91 //
92 // 1. The BranchType (defaults to art::InEvent). Specify explicitly if
93 // you wish to mix subrun or run products, or if you need to specify
94 // explicitly any of the other template arguments.
95 //
96 // 2. The incoming product type (deduced from the provided callable
97 // mixer argument).
98 //
99 // 3. The outgoing product type (deduced from the provided callable
100 // mixer argument).
101 //
102 // A product mixing operation should be specified by providing:
103 //
104 // 1. an InputTag specifying which secondary products should be mixed;
105 //
106 // 2. an optional instance label for the mixed product (defaulting to
107 // the instance label of the incoming product if unspecified); and
108 //
109 // 3. a callable mixer such as:
110 //
111 // bool mixfunc(std::vector<PROD const*> const&,
112 // OPROD&,
113 // PtrRemapper const&),
114 //
115 // As the user may prefer, the mixer may take the form of:
116 // a) an arbitrarily-named free function, or
117 // b) a function object whose operator() must have a signature
118 // whose arguments match those above, or
119 // c) an arbitrarily-named member function of any class.
120 // In each case, the mixer must have the same type (i.e.,
121 // the same return type and the same parameter types) illustrated
122 // by "mixfunc" above. The return value of the mix function is
123 // taken to indicate whether the product should be placed in the
124 // event.
125 //
126 // Generally speaking the PROD and OPROD template arguments are
127 // deducible from the callable mixer function which, once bound
128 // (if appropriate) to any provided class instance, should be
129 // convertible to an instantiation of the template instance
130 // art::MixFunc<PROD, OPROD>. See
131 // art/Framework/IO/ProductMix/MixTypes.h for more details.
132 //
133 // If the provided function is a member function it may be
134 // provided bound to the object upon which it is to be called by
135 // the user (in which case it is treated as a free function by the
136 // registration method) or by specifying the member function
137 // followed by the object to which it should be bound (in which
138 // case the bind will be done for the user). In this latter case
139 // the template argument specifying the product type need *not* be
140 // specified usually as it may be deduced from the signature of
141 // the provided function. If one specifies an overload set however
142 // (e.g. in the case where a class has several mix() member
143 // functions, each one with a different mix function) then the
144 // template argument must be specified in order to constrain the
145 // overload set to a single function.
146 //
147 // See also the description of the template alias
148 // art::MixFunc<PROD, OPROD> defined in
149 // art/Framework/IO/ProductMix/MixTypes.h.
150 //
151 // 4. An optional boolean, "outputProduct," defaulting to, "true." A
152 // false value for this parameter indicates that the mix product
153 // will *never* be put into the event and should therefore not be
154 // declared. If the mix operation so declared ever returns true an
155 // exception will be thrown.
156 //
157 // declareMixOp() may be called with any of the following argument
158 // combinations:
159 //
160 // 1. Provide an InputTag and a mixer that is a free function or
161 // function object.
162 //
163 // 2. Provide an InputTag, an output instance label, and a mixer that
164 // is a free function or function object.
165 //
166 // 3. Provide an InputTag, a mixer that is a non-const member function
167 // (of any class), and an object to which that member function should
168 // be bound.
169 //
170 // 4. Provide an InputTag, an output instance label, a mixer that is a
171 // non-const member function (of any class), and an object to which
172 // that member function should be bound.
173 //
174 // 5. Same as 3, but providing a mixer that is a const member function.
175 //
176 // 6. Same as 4, but providing a mixer that is a const member function.
177 //
178 // Note: For signatures 3-6, if the compiler complains about an
179 // unresolved overload your first move should be to specify the
180 // product type(s) as template argument (to do this you must specify
181 // explicitly the BranchType template argument first). If that does
182 // not resolve the problem, try an explicit:
183 //
184 // const_cast<T const&>(t)
185 //
186 // or
187 //
188 // const_cast<T&>(t)
189 //
190 // as appropriate.
191 //
193 // produces() templates.
194 //
195 // Call as you would from the constructor of a module to declare
196 // (e.g., bookkeeping) products to be put into the event that are
197 // *not* direct results of a single product mix operation. For the
198 // latter case, see the declareMixOp() templates above.
199 //
200 // Signatures for produces():
201 //
202 // 1. produces<PROD>(optional_instance_name);
203 //
204 // Register a product to go into the event.
205 //
206 // 2. produces<PROD, art::InRun>(optional_instance_name);
207 // produces<PROD, art::InSubRun>(optional_instance_name);
208 //
209 // Register a product to go into the run or subrun.
210 //
212 
213 #include "CLHEP/Random/RandFlat.h"
220 #include "art/Utilities/fwd.h"
223 #include "canvas/Persistency/Provenance/Compatibility/BranchIDList.h"
227 #include "cetlib/exempt_ptr.h"
228 #include "cetlib/value_ptr.h"
229 #include "fhiclcpp/ParameterSet.h"
230 
231 #include <functional>
232 #include <memory>
233 #include <string>
234 #include <vector>
235 
236 #include "Rtypes.h"
237 #include "TFile.h"
238 #include "TTree.h"
239 
240 namespace art {
241  class MixHelper;
242 }
243 
245 private:
246  typedef std::function<std::string()> ProviderFunc_;
247 
248 public:
249  enum class Mode {
250  SEQUENTIAL = 0,
254  UKNOWN
255  };
256 
257  // Constructor.
258  MixHelper(fhicl::ParameterSet const& pset, ProducerBase& producesProvider);
259 
260  // Returns the current mixing mode.
261  Mode readMode() const;
262 
263  // Registers a callback to the detail object to determine the next
264  // secondary file to read.
265  void registerSecondaryFileNameProvider(ProviderFunc_ func);
266 
267  // A.
268  template <class P>
269  void produces(std::string const& instanceName = {});
270 
271  // B.
272  template <class P, BranchType B>
273  void produces(std::string const& instanceName = {});
274 
275  // 1.
276  template <art::BranchType B = art::InEvent, typename PROD, typename OPROD>
277  void declareMixOp(InputTag const& inputTag,
278  MixFunc<PROD, OPROD> mixFunc,
279  bool outputProduct = true);
280 
281  // 2.
282  template <art::BranchType B = art::InEvent, typename PROD, typename OPROD>
283  void declareMixOp(InputTag const& inputTag,
284  std::string const& outputInstanceLabel,
285  MixFunc<PROD, OPROD> mixFunc,
286  bool outputProduct = true);
287 
288  // 3.
289  template <art::BranchType B = art::InEvent,
290  typename PROD,
291  typename OPROD,
292  typename T>
293  void declareMixOp(InputTag const& inputTag,
294  bool (T::*mixfunc)(std::vector<PROD const*> const&,
295  OPROD&,
296  PtrRemapper const&),
297  T& t,
298  bool outputProduct = true);
299 
300  // 4.
301  template <art::BranchType B = art::InEvent,
302  typename PROD,
303  typename OPROD,
304  typename T>
305  void declareMixOp(InputTag const& inputTag,
306  std::string const& outputInstanceLabel,
307  bool (T::*mixfunc)(std::vector<PROD const*> const&,
308  OPROD&,
309  PtrRemapper const&),
310  T& t,
311  bool outputProduct = true);
312 
313  // 5.
314  template <art::BranchType B = art::InEvent,
315  typename PROD,
316  typename OPROD,
317  typename T>
318  void declareMixOp(InputTag const& inputTag,
319  bool (T::*mixfunc)(std::vector<PROD const*> const&,
320  OPROD&,
321  PtrRemapper const&) const,
322  T const& t,
323  bool outputProduct = true);
324 
325  // 6.
326  template <art::BranchType B = art::InEvent,
327  typename PROD,
328  typename OPROD,
329  typename T>
330  void declareMixOp(InputTag const& inputTag,
331  std::string const& outputInstanceLabel,
332  bool (T::*mixfunc)(std::vector<PROD const*> const&,
333  OPROD&,
334  PtrRemapper const&) const,
335  T const& t,
336  bool outputProduct = true);
337 
339  // Mix module writers should not need anything below this point.
341  bool generateEventSequence(size_t nSecondaries,
342  EntryNumberSequence& enSeq,
343  EventIDSequence& eIDseq);
346  void mixAndPut(EntryNumberSequence const& enSeq,
347  EventIDSequence const& eIDseq,
348  Event& e);
349  void setEventsToSkipFunction(std::function<size_t()> eventsToSkip);
350 
351 private:
352  MixHelper(MixHelper const&) = delete;
353  MixHelper& operator=(MixHelper const&) = delete;
354 
355  using MixOpList = std::vector<std::unique_ptr<MixOpBase>>;
356 
357  Mode initReadMode_(std::string const& mode) const;
358 
359  void openAndReadMetaData_(std::string fileName);
360  bool openNextFile_();
363 
365  std::vector<std::string> const filenames_;
367  ProviderFunc_ providerFunc_{};
372  double const coverageFraction_;
374  Long64_t nEventsInFile_{};
375  Long64_t totalEventsRead_{};
376  bool const canWrapFiles_;
378  std::unique_ptr<art::BranchIDLists> branchIDLists_{
379  nullptr}; // For backwards compatibility
381  std::unique_ptr<CLHEP::RandFlat> dist_;
382  std::function<size_t()> eventsToSkip_{};
383  EntryNumberSequence shuffledSequence_{}; // RANDOM_NO_REPLACE only.
384  bool haveSubRunMixOps_{false};
385  bool haveRunMixOps_{false};
386 
387  // Root-specific state.
388  cet::value_ptr<TFile> currentFile_{};
389  cet::exempt_ptr<TTree> currentMetaDataTree_{nullptr};
390  std::array<cet::exempt_ptr<TTree>, art::BranchType::NumBranchTypes>
391  currentDataTrees_{{nullptr}};
393  std::array<RootBranchInfoList, art::BranchType::NumBranchTypes> dataBranches_{
394  {}};
396 };
397 
398 inline auto
400 {
401  return readMode_;
402 }
403 
404 // A.
405 template <class P>
406 inline void
407 art::MixHelper::produces(std::string const& instanceName)
408 {
409  producesProvider_.produces<P>(instanceName);
410 }
411 
412 // B.
413 template <class P, art::BranchType B>
414 inline void
415 art::MixHelper::produces(std::string const& instanceName)
416 {
417  producesProvider_.produces<P, B>(instanceName);
418 }
419 
420 // 1.
421 template <art::BranchType B, typename PROD, typename OPROD>
422 inline void
424  MixFunc<PROD, OPROD> mixFunc,
425  bool outputProduct)
426 {
427  declareMixOp<B>(inputTag, inputTag.instance(), mixFunc, outputProduct); // 2.
428 }
429 
430 // 2.
431 template <art::BranchType B, typename PROD, typename OPROD>
432 void
434  std::string const& outputInstanceLabel,
435  MixFunc<PROD, OPROD> mixFunc,
436  bool outputProduct)
437 {
438  if (outputProduct) {
439  produces<OPROD>(outputInstanceLabel);
440  }
441  if (B == art::InSubRun) {
442  haveSubRunMixOps_ = true;
443  } else if (B == art::InRun) {
444  haveRunMixOps_ = true;
445  }
446  mixOps_.emplace_back(new MixOp<PROD, OPROD>(inputTag,
447  outputInstanceLabel,
448  mixFunc,
449  outputProduct,
451  B));
452 }
453 
454 // 3.
455 template <art::BranchType B, typename PROD, typename OPROD, typename T>
456 inline void
458  bool (T::*mixFunc)(std::vector<PROD const*> const&,
459  OPROD&,
460  PtrRemapper const&),
461  T& t,
462  bool outputProduct)
463 {
464  declareMixOp<B>(
465  inputTag, inputTag.instance(), mixFunc, t, outputProduct); // 4.
466 }
467 
468 // 4.
469 template <art::BranchType B, typename PROD, typename OPROD, typename T>
470 void
472  std::string const& outputInstanceLabel,
473  bool (T::*mixFunc)(std::vector<PROD const*> const&,
474  OPROD&,
475  PtrRemapper const&),
476  T& t,
477  bool outputProduct)
478 {
479  using std::placeholders::_1;
480  using std::placeholders::_2;
481  using std::placeholders::_3;
482  declareMixOp<B>(
483  inputTag,
484  outputInstanceLabel,
485  static_cast<MixFunc<PROD, OPROD>>(std::bind(mixFunc, &t, _1, _2, _3)),
486  outputProduct); // 2.
487 }
488 
489 // 5.
490 template <art::BranchType B, typename PROD, typename OPROD, typename T>
491 inline void
493  bool (T::*mixFunc)(std::vector<PROD const*> const&,
494  OPROD&,
495  PtrRemapper const&) const,
496  T const& t,
497  bool outputProduct)
498 {
499  declareMixOp<B>(
500  inputTag, inputTag.instance(), mixFunc, t, outputProduct); // 6.
501 }
502 
503 // 6.
504 template <art::BranchType B, typename PROD, typename OPROD, typename T>
505 void
507  std::string const& outputInstanceLabel,
508  bool (T::*mixFunc)(std::vector<PROD const*> const&,
509  OPROD&,
510  PtrRemapper const&) const,
511  T const& t,
512  bool outputProduct)
513 {
514  using std::placeholders::_1;
515  using std::placeholders::_2;
516  using std::placeholders::_3;
517  declareMixOp<B>(
518  inputTag,
519  outputInstanceLabel,
520  static_cast<MixFunc<PROD, OPROD>>(std::bind(mixFunc, &t, _1, _2, _3)),
521  outputProduct); // 2.
522 }
523 
524 #endif /* art_Framework_IO_ProductMix_MixHelper_h */
525 
526 // Local Variables:
527 // mode: c++
528 // End:
void registerSecondaryFileNameProvider(ProviderFunc_ func)
Definition: MixHelper.cc:132
std::vector< std::string >::const_iterator fileIter_
Definition: MixHelper.h:370
std::vector< EventAuxiliary > EventAuxiliarySequence
Definition: MixTypes.h:24
std::function< size_t()> eventsToSkip_
Definition: MixHelper.h:382
ProducerBase & producesProvider_
Definition: MixHelper.h:364
std::vector< EventID > EventIDSequence
Definition: MixTypes.h:22
cet::value_ptr< TFile > currentFile_
Definition: MixHelper.h:388
ProviderFunc_ providerFunc_
Definition: MixHelper.h:367
Mode initReadMode_(std::string const &mode) const
Definition: MixHelper.cc:316
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
MixHelper(fhicl::ParameterSet const &pset, ProducerBase &producesProvider)
Definition: MixHelper.cc:119
std::array< cet::exempt_ptr< TTree >, art::BranchType::NumBranchTypes > currentDataTrees_
Definition: MixHelper.h:391
Int_t B
Definition: plot.C:25
std::map< ProductID, ProductID > ProductIDTransMap
FileFormatVersion ffVersion_
Definition: MixHelper.h:377
std::vector< std::unique_ptr< MixOpBase >> MixOpList
Definition: MixHelper.h:355
void produces(std::string const &instanceName={}, Persistable const persistable=Persistable::Yes)
MixOpList mixOps_
Definition: MixHelper.h:368
bool haveSubRunMixOps_
Definition: MixHelper.h:384
EntryNumberSequence shuffledSequence_
Definition: MixHelper.h:383
std::unique_ptr< art::BranchIDLists > branchIDLists_
Definition: MixHelper.h:378
std::vector< std::string > const filenames_
Definition: MixHelper.h:365
void produces(std::string const &instanceName={})
Definition: MixHelper.h:407
std::unique_ptr< CLHEP::RandFlat > dist_
Definition: MixHelper.h:381
double const coverageFraction_
Definition: MixHelper.h:372
Mode const readMode_
Definition: MixHelper.h:371
std::array< RootBranchInfoList, art::BranchType::NumBranchTypes > dataBranches_
Definition: MixHelper.h:393
Long64_t nEventsReadThisFile_
Definition: MixHelper.h:373
bool generateEventSequence(size_t nSecondaries, EntryNumberSequence &enSeq, EventIDSequence &eIDseq)
Definition: MixHelper.cc:143
bool const canWrapFiles_
Definition: MixHelper.h:376
intermediate_table::const_iterator const_iterator
FileIndex currentFileIndex_
Definition: MixHelper.h:392
void declareMixOp(InputTag const &inputTag, MixFunc< PROD, OPROD > mixFunc, bool outputProduct=true)
Definition: MixHelper.h:423
cet::exempt_ptr< TTree > currentMetaDataTree_
Definition: MixHelper.h:389
bool openNextFile_()
Definition: MixHelper.cc:422
bool compactMissingProducts_
Definition: MixHelper.h:366
std::string const & instance() const noexcept
Definition: InputTag.h:60
void generateEventAuxiliarySequence(EntryNumberSequence const &, EventAuxiliarySequence &)
Definition: MixHelper.cc:212
std::function< bool(std::vector< PROD const * > const &, OPROD &, PtrRemapper const &)> MixFunc
Definition: MixTypes.h:17
std::vector< FileIndex::EntryNumber_t > EntryNumberSequence
Definition: MixTypes.h:23
void buildProductIDTransMap_(ProdToProdMapBuilder::ProductIDTransMap &transMap)
Definition: MixHelper.cc:456
PtrRemapper ptrRemapper_
Definition: MixHelper.h:369
void openAndReadMetaData_(std::string fileName)
Definition: MixHelper.cc:343
std::map< FileIndex::EntryNumber_t, EventID > EventIDIndex
Definition: MixTypes.h:19
Mode readMode() const
Definition: MixHelper.h:399
bool haveRunMixOps_
Definition: MixHelper.h:385
std::function< std::string()> ProviderFunc_
Definition: MixHelper.h:246
MixHelper & operator=(MixHelper const &)=delete
EventIDIndex eventIDIndex_
Definition: MixHelper.h:395
Long64_t nEventsInFile_
Definition: MixHelper.h:374
BranchType
Definition: BranchType.h:18
HLT enums.
Float_t e
Definition: plot.C:34
ProdToProdMapBuilder ptpBuilder_
Definition: MixHelper.h:380
Long64_t totalEventsRead_
Definition: MixHelper.h:375