MixFilterTestNoStartEvent_module.cc
Go to the documentation of this file.
2 
14 #include "cetlib/map_vector.h"
16 
17 #include "boost/noncopyable.hpp"
18 
19 #include <algorithm>
20 #include <iterator>
21 #include <memory>
22 #include <unordered_set>
23 
24 namespace arttest {
25  class MixFilterTestDetail;
26 #if ART_TEST_EVENTS_TO_SKIP_CONST
27 #define ART_MFT MixFilterTestETSc
28 #define ART_TEST_EVENTS_TO_SKIP_CONST_TXT const
29 #elif defined ART_TEST_EVENTS_TO_SKIP_CONST
30 #define ART_MFT MixFilterTestETS
31 #define ART_TEST_EVENTS_TO_SKIP_CONST_TXT
32 #elif defined ART_TEST_OLD_STARTEVENT
33 #define ART_MT MixFilterTestOldStartEvent
34 #elif defined ART_TEST_NO_STARTEVENT
35 #define ART_MT MixFilterTestNoStartEvent
36 #else
37 // Normal case
38 #define ART_MFT MixFilterTest
39 #endif
41 }
42 
43 namespace {
44  class SecondaryFileNameProvider {
45  public:
46  SecondaryFileNameProvider(std::vector<std::string>&& fileNames)
47  : fileNames_(std::move(fileNames)), fileNameIter_(fileNames_.cbegin())
48  {}
49  SecondaryFileNameProvider(SecondaryFileNameProvider&&) = default;
50 
51  SecondaryFileNameProvider& operator=(SecondaryFileNameProvider&&) = default;
52 
53  SecondaryFileNameProvider(SecondaryFileNameProvider const& other)
54  : fileNames_(other.fileNames_)
55  , fileNameIter_(fileNames_.cbegin() +
56  (other.fileNameIter_ - other.fileNames_.cbegin()))
57  {}
58 
59  SecondaryFileNameProvider&
60  operator=(SecondaryFileNameProvider const& other)
61  {
62  SecondaryFileNameProvider tmp(other);
63  std::swap(tmp, *this);
64  return *this;
65  }
66 
67  ~SecondaryFileNameProvider() noexcept = default;
68 
70  operator()()
71  {
72  if (fileNameIter_ == fileNames_.end()) {
73  return std::string();
74  } else {
75  return *(fileNameIter_++);
76  }
77  }
78 
79  private:
80  std::vector<std::string> fileNames_;
81  decltype(fileNames_.cbegin()) fileNameIter_;
82  };
83 } // namespace
84 
86 public:
88  using mvv_t = typename mv_t::value_type;
89  using mvm_t = typename mv_t::mapped_type;
90 
91  // Constructor is responsible for registering mix operations with
92  // MixHelper::declareMixOp() and bookkeeping products with
93  // MixHelperproduces().
95 
98 
100 
101 #ifdef ART_TEST_OLD_STARTEVENT
102  // Old startEvent signature -- check it still works
103  void startEvent();
104 #elif !defined ART_TEST_NO_STARTEVENT
105  // Optional startEvent(Event const &): initialize state for each event,
106  void startEvent(art::Event const&);
107 #endif
108 
109  // Return the number of secondaries to read this time. Declare const
110  // if you don't plan to change your class' state.
111  size_t nSecondaries() const;
112 
113  // Optional eventsToSkip(): number of events to skip at the start of
114  // the file.
115 #ifdef ART_TEST_EVENTS_TO_SKIP_CONST
116  size_t
117  eventsToSkip() ART_TEST_EVENTS_TO_SKIP_CONST_TXT
118  {
119  return 7;
120  }
121 #endif
122 
123  // Optional processEventIDs(): after the generation of the event
124  // sequence, this function will be called if it exists to provide the
125  // sequence of EventIDs.
126  void processEventIDs(art::EventIDSequence const& seq);
127 
128  // Optional.finalizeEvent(): (eg) put bookkeping products in event. Do
129  // *not* place mix products into the event: this will already have
130  // been done for you.
131  void finalizeEvent(art::Event& t);
132 
133  // Optional respondToXXXfunctions, called at the right time if they
134  // exist.
135  void respondToOpenInputFile(art::FileBlock const& fb);
136  void respondToCloseInputFile(art::FileBlock const& fb);
139 
140  // Mixing functions. Note that they do not *have* to be member
141  // functions of this detail class: they may be member functions of a
142  // completely unrelated class; free functions or function objects
143  // provided they (or the function object's operator()) have the
144  // expected signature.
145  template <typename T>
146  bool mixByAddition(std::vector<T const*> const&, T&, art::PtrRemapper const&);
147 
149  std::vector<std::vector<double> const*> const& in,
150  std::vector<double>& out,
151  art::PtrRemapper const&);
152 
153  bool aggregate_map_vector(std::vector<mv_t const*> const& in,
154  mv_t& out,
155  art::PtrRemapper const&);
156 
157  bool mixPtrs(std::vector<std::vector<art::Ptr<double>> const*> const& in,
159  art::PtrRemapper const& remap);
160 
161 #ifndef ART_NO_MIX_PTRVECTOR
162  bool mixPtrVectors(std::vector<art::PtrVector<double> const*> const& in,
164  art::PtrRemapper const& remap);
165 #endif
166 
167  bool mixProductWithPtrs(
168  std::vector<arttest::ProductWithPtrs const*> const& in,
170  art::PtrRemapper const& remap);
171 
172  bool mixmap_vectorPtrs(
176  art::PtrRemapper const& remap);
177 
178  template <typename COLL>
179  void verifyInSize(COLL const& in) const;
180 
181 private:
182  size_t const nSecondaries_;
183  bool const testRemapper_;
184  std::vector<size_t> doubleVectorOffsets_, map_vectorOffsets_;
185  std::unique_ptr<art::EventIDSequence> eIDs_;
186  bool startEvent_called_
187 #ifdef __clang__
188  [[gnu::unused]]
189 #endif
190  ;
192  int currentEvent_;
193  bool const testZeroSecondaries_;
194  bool const testPtrFailure_;
195  bool const testEventOrdering_;
196  bool const testNoLimEventDupes_;
197  bool const compactMissingProducts_;
199 
200  size_t respondFunctionsSeen_;
201 
202  // For testing no_replace mode only:
203  std::vector<int> allEvents_;
204  std::unordered_set<int> uniqueEvents_;
205 };
206 
207 template <typename COLL>
208 inline void
209 arttest::MixFilterTestDetail::verifyInSize(COLL const& in) const
210 {
211  BOOST_REQUIRE_EQUAL(
212  in.size(),
214 }
215 
217  art::MixHelper& helper)
218  : nSecondaries_(p.get<size_t>("numSecondaries", 1))
219  , testRemapper_(p.get<bool>("testRemapper", true))
222  , eIDs_()
223  , startEvent_called_(false)
224  , processEventIDs_called_(false)
225  , currentEvent_(-1)
226  , testZeroSecondaries_(p.get<bool>("testZeroSecondaries", false))
227  , testPtrFailure_(p.get<bool>("testPtrFailure", false))
228  , testEventOrdering_(p.get<bool>("testEventOrdering", false))
229  , testNoLimEventDupes_(p.get<bool>("testNoLimEventDupes", false))
230  , compactMissingProducts_(p.get<bool>("compactMissingProducts", false))
231  , readMode_(helper.readMode())
233  , allEvents_()
234  , uniqueEvents_()
235 {
236  std::vector<std::string> fnToProvide;
237  if (p.get_if_present("fileNamesToProvide", fnToProvide)) {
238  std::cerr << "Calling registerSecondaryFileNameProvider.\n";
239  std::copy(fnToProvide.cbegin(),
240  fnToProvide.cend(),
241  std::ostream_iterator<std::string>(std::cerr, ", "));
242  std::cerr << "\n";
244  SecondaryFileNameProvider(std::move(fnToProvide)));
245  }
246 
247  std::string mixProducerLabel(
248  p.get<std::string>("mixProducerLabel", "mixProducer"));
249  helper.produces<std::string>(); // "Bookkeeping"
250  helper.produces<art::EventIDSequence>(); // "Bookkeeping"
251  helper.declareMixOp(art::InputTag(mixProducerLabel, "doubleLabel"),
252  &MixFilterTestDetail::mixByAddition<double>,
253  *this);
254  helper.declareMixOp(art::InputTag(mixProducerLabel, "IntProductLabel"),
255  &MixFilterTestDetail::mixByAddition<arttest::IntProduct>,
256  *this);
257  helper.declareMixOp(art::InputTag(mixProducerLabel, "stringLabel", "SWRITE"),
258  &MixFilterTestDetail::mixByAddition<std::string>,
259  *this);
260  helper.declareMixOp(art::InputTag(mixProducerLabel, "doubleCollectionLabel"),
262  *this);
263  helper.declareMixOp(art::InputTag(mixProducerLabel, "doubleVectorPtrLabel"),
265  *this);
266 #ifndef ART_NO_MIX_PTRVECTOR
267  helper.declareMixOp(art::InputTag(mixProducerLabel, "doublePtrVectorLabel"),
269  *this);
270 #endif
271  helper.declareMixOp(art::InputTag(mixProducerLabel, "ProductWithPtrsLabel"),
273  *this);
274  helper.declareMixOp(art::InputTag(mixProducerLabel, "mapVectorLabel"),
276  *this);
277  helper.declareMixOp(art::InputTag(mixProducerLabel, "intVectorPtrLabel"),
279  *this);
280  std::function<bool(std::vector<IntProduct const*> const&,
281  IntProduct&,
282  art::PtrRemapper const&)>
283  mixfunc([this](std::vector<IntProduct const*> const& in,
284  IntProduct,
285  art::PtrRemapper const&) -> bool {
286  auto const sz = in.size();
287  auto expected = nSecondaries_;
289  expected -= std::count_if(
290  eIDs_->begin(), eIDs_->end(), [](art::EventID const& eID) {
291  return (eID.event() % 100) == 0;
292  });
293  }
294  for (auto i = 0ul; i < sz; ++i) {
295  if (!compactMissingProducts_ && ((*eIDs_)[i].event() % 100) == 0) {
296  // Product missing
297  BOOST_REQUIRE(in[i] == nullptr);
298  } else {
299  BOOST_REQUIRE(in[i] != nullptr);
300  }
301  }
302  BOOST_REQUIRE_EQUAL(
303  sz, (currentEvent_ == 2 && testZeroSecondaries_) ? 0ul : expected);
304  return false;
305  });
306  helper.declareMixOp(
307  art::InputTag(mixProducerLabel, "SpottyProductLabel"), mixfunc, false);
308 }
309 
311 {
313  testNoLimEventDupes_ == false) {
314  // Require dupes across the job.
315  BOOST_CHECK_GT(allEvents_.size(), uniqueEvents_.size());
317  // Require no dupes across the job.
318  BOOST_CHECK_EQUAL(allEvents_.size(), uniqueEvents_.size());
319  }
320  BOOST_CHECK_EQUAL(respondFunctionsSeen_, 4ul);
321 }
322 
323 #ifndef ART_TEST_NO_STARTEVENT
324 void
326 #ifdef ART_TEST_OLD_STARTEVENT
327  startEvent()
328 #else
329  // Normal case
331 #endif
332 {
333  startEvent_called_ = true;
334  eIDs_.reset();
335  ++currentEvent_;
336 }
337 #endif
338 
339 size_t
341 {
342  return (currentEvent_ == 2 && testZeroSecondaries_) ? 0 : nSecondaries_;
343 }
344 
345 void
347 {
348 #ifdef ART_TEST_NO_STARTEVENT
349  // Need to deal with this here
350  ++currentEvent_;
351 #endif
353  eIDs_.reset(new art::EventIDSequence(seq));
354  if (!testEventOrdering_) {
355  return;
356  }
357  switch (readMode_) {
359  auto count(1);
360  for (auto const& eid : seq) {
361  BOOST_REQUIRE_EQUAL(eid.event(),
362  currentEvent_ * nSecondaries() + count++);
363  }
364  } break;
366  // We should have a duplicate within the secondaries.
367  std::unordered_set<int> s;
368  std::transform(seq.cbegin(),
369  seq.cend(),
370  std::inserter(s, s.begin()),
371  [](art::EventID const& eid) { return eid.event(); });
372  BOOST_CHECK_GT(seq.size(), s.size());
373  } break;
375  if (testNoLimEventDupes_) {
376  // We should have no duplicate within the secondaries.
377  std::unordered_set<int> s;
378  std::transform(seq.cbegin(),
379  seq.cend(),
380  std::inserter(s, s.begin()),
381  [](art::EventID const& eid) { return eid.event(); });
382  BOOST_CHECK_EQUAL(seq.size(), s.size());
383  } else { // Require dupes over 2 events.
384  auto checkpoint(allEvents_.size());
385  std::transform(seq.cbegin(),
386  seq.cend(),
387  std::back_inserter(allEvents_),
388  [](art::EventID const& eid) { return eid.event(); });
389  uniqueEvents_.insert(allEvents_.cbegin() + checkpoint,
390  allEvents_.cend());
391  // Test at end job for duplicates.
392  }
393  break;
395  auto checkpoint(allEvents_.size());
396  std::transform(seq.cbegin(),
397  seq.cend(),
398  std::back_inserter(allEvents_),
399  [](art::EventID const& eid) { return eid.event(); });
400  uniqueEvents_.insert(allEvents_.cbegin() + checkpoint, allEvents_.cend());
401  // Test at end job for no duplicates.
402  } break;
403  default:;
404  }
405 }
406 
407 void
409 {
410  e.put(std::unique_ptr<std::string>(new std::string("BlahBlahBlah")));
411  e.put(std::move(eIDs_));
412 #ifndef ART_TEST_NO_STARTEVENT
414  startEvent_called_ = false;
415 #endif
417  processEventIDs_called_ = false;
418 }
419 
420 void
422 {
424 }
425 
426 void
428 {
430 }
431 
432 void
434 {
436 }
437 
438 void
440 {
442 }
443 
444 template <typename T>
445 bool
446 arttest::MixFilterTestDetail::mixByAddition(std::vector<T const*> const& in,
447  T& out,
448  art::PtrRemapper const&)
449 {
450  verifyInSize(in);
451  for (auto const* prod : in) {
452  if (prod != nullptr) {
453  out += *prod;
454  }
455  }
456  return true; // Always want product in event.
457 }
458 
459 bool
461  std::vector<std::vector<double> const*> const& in,
462  std::vector<double>& out,
463  art::PtrRemapper const&)
464 {
465  verifyInSize(in);
467  return true; // Always want product in event.
468 }
469 
470 bool
472  std::vector<mv_t const*> const& in,
473  mv_t& out,
474  art::PtrRemapper const&)
475 {
476  verifyInSize(in);
478  return true; // Always want product in event.
479 }
480 
481 bool
483  std::vector<std::vector<art::Ptr<double>> const*> const& in,
485  art::PtrRemapper const& remap)
486 {
487  verifyInSize(in);
488  remap(in, std::back_inserter(out), doubleVectorOffsets_);
489  if (testPtrFailure_) {
490  BOOST_REQUIRE_THROW(*out.front(), art::Exception);
491  }
492  return true; // Always want product in event.
493 }
494 
495 #ifndef ART_NO_MIX_PTRVECTOR
496 bool
498  std::vector<art::PtrVector<double> const*> const& in,
500  art::PtrRemapper const& remap)
501 {
502  verifyInSize(in);
503  remap(in, std::back_inserter(out), doubleVectorOffsets_);
504  return true; // Always want product in event.
505 }
506 #endif
507 
508 bool
510  std::vector<arttest::ProductWithPtrs const*> const& in,
512  art::PtrRemapper const& remap)
513 {
514  verifyInSize(in);
515 #ifndef ART_NO_MIX_PTRVECTOR
516  remap(in,
517  std::back_inserter(out.ptrVectorDouble()),
520 #endif
521  remap(in,
522  std::back_inserter(out.vectorPtrDouble()),
525  // Throw-away object to test non-standard remap interface.
527  remap(in,
528  std::back_inserter(tmp.vectorPtrDouble()),
531  return true; // Always want product in event.
532 }
533 
534 bool
539  art::PtrRemapper const& remap)
540 {
541  verifyInSize(in);
542  remap(in, std::back_inserter(out), map_vectorOffsets_);
543  return true; // Always want product in event.
544 }
545 
546 namespace arttest {
548 }
void startEvent(art::Event const &)
void registerSecondaryFileNameProvider(ProviderFunc_ func)
Definition: MixHelper.cc:146
void respondToCloseInputFile(art::FileBlock const &fb)
std::vector< EventID > EventIDSequence
Definition: MixTypes.h:22
art::PtrVector< double > const & ptrVectorDouble() const
std::vector< art::Ptr< double > > const & vectorPtrDouble() const
bool mixPtrs(std::vector< std::vector< art::Ptr< double >> const * > const &in, std::vector< art::Ptr< double >> &out, art::PtrRemapper const &remap)
const char expected[]
Definition: Exception_t.cc:22
void respondToCloseOutputFiles(art::FileBlock const &fb)
std::string string
Definition: nybbler.cc:12
bool mixByAddition(std::vector< PROD const * > const &, OPROD &, art::PtrRemapper const &)
std::pair< key_type, mapped_type > value_type
Definition: map_vector.h:89
MixFilterTestDetail(Parameters const &p, art::MixHelper &helper)
bool mixPtrVectors(std::vector< art::PtrVector< double > const * > const &in, art::PtrVector< double > &out, art::PtrRemapper const &remap)
bool mixmap_vectorPtrs(std::vector< std::vector< art::Ptr< cet::map_vector< unsigned int >::value_type >> const * > const &in, std::vector< art::Ptr< cet::map_vector< unsigned int >::value_type >> &out, art::PtrRemapper const &remap)
void produces(std::string const &instanceName={})
Definition: MixHelper.h:455
bool aggregateDoubleCollection(std::vector< std::vector< double > const * > const &in, std::vector< double > &out, art::PtrRemapper const &)
Value mapped_type
Definition: map_vector.h:88
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
void flattenCollections(std::vector< COLLECTION const * > const &in, COLLECTION &out)
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:68
void declareMixOp(InputTag const &inputTag, MixFunc< PROD, OPROD > mixFunc, bool outputProduct=true)
Definition: MixHelper.h:471
void swap(Handle< T > &a, Handle< T > &b)
void verifyInSize(COLL const &in) const
T get(std::string const &key) const
Definition: ParameterSet.h:231
std::vector< size_t > map_vectorOffsets_
bool get_if_present(std::string const &key, T &value) const
Definition: ParameterSet.h:208
art::MixFilter< MixFilterTestDetail > ART_MFT
art::MixHelper::Mode const readMode_
MixFilterTestDetail & operator=(MixFilterTestDetail const &)=delete
BOOST_REQUIRE(inFile)
std::unique_ptr< art::EventIDSequence > eIDs_
std::vector< art::Ptr< double > > vpd_
std::unordered_set< int > uniqueEvents_
p
Definition: test.py:228
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
bool aggregate_map_vector(std::vector< mv_t const * > const &in, mv_t &out, art::PtrRemapper const &)
void respondToOpenInputFile(art::FileBlock const &fb)
std::vector< size_t > doubleVectorOffsets_
T copy(T const &v)
void respondToOpenOutputFiles(art::FileBlock const &fb)
EventNumber_t event() const
Definition: EventID.h:117
static const double s
Definition: Units.h:99
cet::map_vector< unsigned int > mv_t
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
bool mixProductWithPtrs(std::vector< arttest::ProductWithPtrs const * > const &in, arttest::ProductWithPtrs &out, art::PtrRemapper const &remap)
ProductID put(std::unique_ptr< PROD > &&edp, FullSemantic< Level::Run > const semantic)
Definition: DataViewImpl.h:692
void processEventIDs(art::EventIDSequence const &seq)