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 ////////////////////////////////////////////////////////////////////////
4 // 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 //
10 ////////////////////////////////////////////////////////////////////////
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 //
50 ////////////////////////////////////////////////////////////////////////
51 // readMode()
52 //
53 // Return the enumerated value representing the event mixing strategy.
54 //
55 ////////////////////////////////////////////////////////////////////////
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 //
83 ////////////////////////////////////////////////////////////////////////
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 (wrapped as a MixFunc<PROD, OPROD>).
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 //
192 ////////////////////////////////////
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 //
211 ////////////////////////////////////////////////////////////////////////
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 <iosfwd>
233 #include <memory>
234 #include <string>
235 #include <vector>
236 
237 #include "Rtypes.h"
238 #include "TFile.h"
239 #include "TTree.h"
240 
241 namespace art {
242  class MixHelper;
243 }
244 
246  using ProviderFunc_ = std::function<std::string()>;
247 
248 public:
249  enum class Mode {
250  SEQUENTIAL = 0,
254  UNKNOWN
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.
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 
338  //////////////////////////////////////////////////////////////////////
339  // Mix module writers should not need anything below this point.
340  //////////////////////////////////////////////////////////////////////
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 
360  bool openNextFile_();
363 
365  std::vector<std::string> const filenames_;
370  std::vector<std::string>::const_iterator fileIter_;
372  double const coverageFraction_;
374  Long64_t nEventsInFile_{};
375  Long64_t totalEventsRead_{};
376  bool const canWrapFiles_;
379  std::unique_ptr<art::BranchIDLists> branchIDLists_{
380  nullptr}; // For backwards compatibility
382  std::unique_ptr<CLHEP::RandFlat> dist_;
383  std::function<size_t()> eventsToSkip_{};
384  EntryNumberSequence shuffledSequence_{}; // RANDOM_NO_REPLACE only.
385  bool haveSubRunMixOps_{false};
386  bool haveRunMixOps_{false};
387 
388  // Root-specific state.
391  std::array<cet::exempt_ptr<TTree>, art::BranchType::NumBranchTypes>
392  currentDataTrees_{{nullptr}};
394  std::array<RootBranchInfoList, art::BranchType::NumBranchTypes> dataBranches_{
395  {}};
397 };
398 
399 namespace art {
400  std::ostream& operator<<(std::ostream& os, MixHelper::Mode);
401 }
402 
403 inline auto
405 {
406  return readMode_;
407 }
408 
409 // A.
410 template <class P>
411 inline void
413 {
414  producesProvider_.produces<P>(instanceName);
415 }
416 
417 // B.
418 template <class P, art::BranchType B>
419 inline void
421 {
422  producesProvider_.produces<P, B>(instanceName);
423 }
424 
425 // 1.
426 template <art::BranchType B, typename PROD, typename OPROD>
427 inline void
429  MixFunc<PROD, OPROD> mixFunc,
430  bool outputProduct)
431 {
432  declareMixOp<B>(inputTag, inputTag.instance(), mixFunc, outputProduct); // 2.
433 }
434 
435 // 2.
436 template <art::BranchType B, typename PROD, typename OPROD>
437 void
439  std::string const& outputInstanceLabel,
440  MixFunc<PROD, OPROD> mixFunc,
441  bool outputProduct)
442 {
443  if (outputProduct) {
444  produces<OPROD>(outputInstanceLabel);
445  }
446  if (B == art::InSubRun) {
447  haveSubRunMixOps_ = true;
448  } else if (B == art::InRun) {
449  haveRunMixOps_ = true;
450  }
451  mixOps_.emplace_back(new MixOp<PROD, OPROD>(inputTag,
452  outputInstanceLabel,
453  mixFunc,
454  outputProduct,
456  B));
457 }
458 
459 // 3.
460 template <art::BranchType B, typename PROD, typename OPROD, typename T>
461 inline void
463  bool (T::*mixFunc)(std::vector<PROD const*> const&,
464  OPROD&,
465  PtrRemapper const&),
466  T& t,
467  bool outputProduct)
468 {
469  declareMixOp<B>(
470  inputTag, inputTag.instance(), mixFunc, t, outputProduct); // 4.
471 }
472 
473 // 4.
474 template <art::BranchType B, typename PROD, typename OPROD, typename T>
475 void
477  std::string const& outputInstanceLabel,
478  bool (T::*mixFunc)(std::vector<PROD const*> const&,
479  OPROD&,
480  PtrRemapper const&),
481  T& t,
482  bool outputProduct)
483 {
484  using std::placeholders::_1;
485  using std::placeholders::_2;
486  using std::placeholders::_3;
487  declareMixOp<B>(
488  inputTag,
489  outputInstanceLabel,
490  static_cast<MixFunc<PROD, OPROD>>(std::bind(mixFunc, &t, _1, _2, _3)),
491  outputProduct); // 2.
492 }
493 
494 // 5.
495 template <art::BranchType B, typename PROD, typename OPROD, typename T>
496 inline void
498  bool (T::*mixFunc)(std::vector<PROD const*> const&,
499  OPROD&,
500  PtrRemapper const&) const,
501  T const& t,
502  bool outputProduct)
503 {
504  declareMixOp<B>(
505  inputTag, inputTag.instance(), mixFunc, t, outputProduct); // 6.
506 }
507 
508 // 6.
509 template <art::BranchType B, typename PROD, typename OPROD, typename T>
510 void
512  std::string const& outputInstanceLabel,
513  bool (T::*mixFunc)(std::vector<PROD const*> const&,
514  OPROD&,
515  PtrRemapper const&) const,
516  T const& t,
517  bool outputProduct)
518 {
519  using std::placeholders::_1;
520  using std::placeholders::_2;
521  using std::placeholders::_3;
522  declareMixOp<B>(
523  inputTag,
524  outputInstanceLabel,
525  static_cast<MixFunc<PROD, OPROD>>(std::bind(mixFunc, &t, _1, _2, _3)),
526  outputProduct); // 2.
527 }
528 
529 #endif /* art_Framework_IO_ProductMix_MixHelper_h */
530 
531 // Local Variables:
532 // mode: c++
533 // End:
std::ostream & operator<<(std::ostream &os, EDAnalyzer::Table< T > const &t)
Definition: EDAnalyzer.h:184
void registerSecondaryFileNameProvider(ProviderFunc_ func)
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:383
fileName
Definition: plotROC.py:78
ProducerBase & producesProvider_
Definition: MixHelper.h:364
std::vector< EventID > EventIDSequence
Definition: MixTypes.h:22
cet::value_ptr< TFile > currentFile_
Definition: MixHelper.h:389
ProviderFunc_ providerFunc_
Definition: MixHelper.h:367
void mixAndPut(EntryNumberSequence const &enSeq, EventIDSequence const &eIDseq, Event &e)
void setEventsToSkipFunction(std::function< size_t()> eventsToSkip)
MixHelper(fhicl::ParameterSet const &pset, ProducerBase &producesProvider)
std::array< cet::exempt_ptr< TTree >, art::BranchType::NumBranchTypes > currentDataTrees_
Definition: MixHelper.h:392
std::map< ProductID, ProductID > ProductIDTransMap
FileFormatVersion ffVersion_
Definition: MixHelper.h:378
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:385
unsigned nOpensOverThreshold_
Definition: MixHelper.h:377
EntryNumberSequence shuffledSequence_
Definition: MixHelper.h:384
std::unique_ptr< art::BranchIDLists > branchIDLists_
Definition: MixHelper.h:379
std::vector< std::string > const filenames_
Definition: MixHelper.h:365
void produces(std::string const &instanceName={})
Definition: MixHelper.h:412
std::unique_ptr< CLHEP::RandFlat > dist_
Definition: MixHelper.h:382
double const coverageFraction_
Definition: MixHelper.h:372
Mode const readMode_
Definition: MixHelper.h:371
std::array< RootBranchInfoList, art::BranchType::NumBranchTypes > dataBranches_
Definition: MixHelper.h:394
Long64_t nEventsReadThisFile_
Definition: MixHelper.h:373
#define P(a, b, c, d, e, x)
bool generateEventSequence(size_t nSecondaries, EntryNumberSequence &enSeq, EventIDSequence &eIDseq)
bool const canWrapFiles_
Definition: MixHelper.h:376
FileIndex currentFileIndex_
Definition: MixHelper.h:393
void declareMixOp(InputTag const &inputTag, MixFunc< PROD, OPROD > mixFunc, bool outputProduct=true)
Definition: MixHelper.h:428
cet::exempt_ptr< TTree > currentMetaDataTree_
Definition: MixHelper.h:390
bool openNextFile_()
bool compactMissingProducts_
Definition: MixHelper.h:366
std::string const & instance() const noexcept
Definition: InputTag.h:60
void generateEventAuxiliarySequence(EntryNumberSequence const &, EventAuxiliarySequence &)
std::function< bool(std::vector< PROD const * > const &, OPROD &, PtrRemapper const &)> MixFunc
Definition: MixTypes.h:17
double func(double x, double y)
std::vector< FileIndex::EntryNumber_t > EntryNumberSequence
Definition: MixTypes.h:23
Mode initReadMode_(std::string const &mode) const
void buildProductIDTransMap_(ProdToProdMapBuilder::ProductIDTransMap &transMap)
PtrRemapper ptrRemapper_
Definition: MixHelper.h:369
void openAndReadMetaData_(std::string fileName)
std::function< std::string()> ProviderFunc_
Definition: MixHelper.h:246
std::map< FileIndex::EntryNumber_t, EventID > EventIDIndex
Definition: MixTypes.h:19
Mode readMode() const
Definition: MixHelper.h:404
bool haveRunMixOps_
Definition: MixHelper.h:386
MixHelper & operator=(MixHelper const &)=delete
EventIDIndex eventIDIndex_
Definition: MixHelper.h:396
Long64_t nEventsInFile_
Definition: MixHelper.h:374
BranchType
Definition: BranchType.h:18
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
ProdToProdMapBuilder ptpBuilder_
Definition: MixHelper.h:381
Long64_t totalEventsRead_
Definition: MixHelper.h:375
enum BeamMode string