6 #include "cetlib/container_algorithms.h" 8 #include "range/v3/view.hpp" 18 #include <unordered_set> 31 only_events(std::unique_ptr<art::MixOpBase>
const& mixOp)
40 for (
auto const& element : fileIndex | views::filter(event_entries)) {
50 for (
auto const& mixOp : mixOps | views::filter(only_events)) {
63 auto i = index_.find(entry);
64 if (i ==
cend(index_)) {
66 <<
"MixHelper could not find entry number " << entry
67 <<
" in its own lookup table.\n";
77 initCoverageFraction(
double fraction)
79 if (fraction > (1 + std::numeric_limits<double>::epsilon())) {
81 <<
"coverageFraction > 1: treating as a percentage.";
90 std::string
const& moduleLabel,
92 std::unique_ptr<MixIOPolicy> ioHandle)
96 ,
filenames_{pset.get<std::vector<std::string>>(
"fileNames", {})}
101 pset.get<
double>(
"coverageFraction", 1.0))}
109 std::string
const& moduleLabel,
111 std::unique_ptr<MixIOPolicy> ioHandle)
133 return os <<
"SEQUENTIAL";
135 return os <<
"RANDOM_REPLACE";
137 return os <<
"RANDOM_LIM_REPLACE";
139 return os <<
"RANDOM_NO_REPLACE";
141 return os <<
"UNKNOWN";
152 <<
"Provision of a secondary file name provider is incompatible" 153 <<
" with a\nnon-empty fileNames parameter to the mix filter.\n";
172 std::string
const& kind_of_engine_to_make)
182 std::string
const& kind_of_engine_to_make,
189 seed, kind_of_engine_to_make, engine_label);
197 assert(enSeq.empty());
198 assert(eIDseq.empty());
203 auto const nEventsInFile =
ioHandle_->nEventsInFile();
204 bool const over_threshold =
209 if (over_threshold) {
214 "An error occurred while preparing product-mixing for " 215 "the current event.\n"}
216 <<
"The number of requested secondaries (" << nSecondaries
217 <<
") exceeds the number of events in any\n" 218 <<
"of the files specified for product mixing. For a read mode of '" 220 <<
"the framework does not currently allow product-mixing to span " 221 "multiple secondary\n" 222 <<
"input files for a given event. Please contact artists@fnal.gov " 223 "for more information.\n";
236 enSeq.resize(nSecondaries);
241 std::back_inserter(enSeq), nSecondaries, [
this, nEventsInFile] {
242 return dist_.get()->fireInt(nEventsInFile);
244 std::sort(enSeq.begin(), enSeq.end());
247 std::unordered_set<EntryNumberSequence::value_type>
249 while (entries.size() < nSecondaries) {
251 std::inserter(entries, entries.begin()),
252 nSecondaries - entries.size(),
253 [
this, nEventsInFile] {
return dist_.get()->fireInt(nEventsInFile); });
256 std::sort(
begin(enSeq),
end(enSeq));
262 assert(enSeq.size() == nSecondaries);
266 enSeq.assign(i, i + nSecondaries);
270 <<
"Unrecognized read mode " <<
static_cast<int>(
readMode_)
271 <<
". Contact the art developers.\n";
281 return ioHandle_->generateEventAuxiliarySequence(enSeq);
296 auto const& fileIndex =
ioHandle_->fileIndex();
298 subRunEntries.reserve(eIDseq.size());
299 for (
auto const& eID : eIDseq) {
300 auto const it = fileIndex.
findPosition(eID.subRunID(),
true);
303 <<
"- Unable to find an entry in the SubRun tree corresponding to " 305 << eID <<
" in secondary mixing input file " << *
fileIter_ <<
".\n";
307 subRunEntries.emplace_back(it->entry);
311 runEntries.reserve(eIDseq.size());
312 for (
auto const& eID : eIDseq) {
313 auto const it = fileIndex.
findPosition(eID.runID(),
true);
316 <<
"- Unable to find an entry in the Run tree corresponding to " 318 << eID <<
" in secondary mixing input file " << *
fileIter_ <<
".\n";
320 runEntries.emplace_back(it->entry);
328 for (
auto const& op :
mixOps_) {
329 switch (op->branchType()) {
331 auto const inProducts =
ioHandle_->readFromFile(*op, eventEntries);
336 auto const inProducts =
ioHandle_->readFromFile(*op, subRunEntries);
338 op->mixAndPut(e, inProducts, nopRemapper);
342 auto const inProducts =
ioHandle_->readFromFile(*op, runEntries);
344 op->mixAndPut(e, inProducts, nopRemapper);
349 <<
"- MixHelper::mixAndPut() attempted to handle unsupported branch " 351 << op->branchType() <<
".\n";
370 static std::regex
const robjs[4]{
371 std::regex(
"^seq", std::regex_constants::icase),
372 std::regex(
"^random(replace)?$", std::regex_constants::icase),
373 std::regex(
"^randomlimreplace$", std::regex_constants::icase),
374 std::regex(
"^randomnoreplace$", std::regex_constants::icase)};
376 for (
auto const&
r : robjs) {
377 if (std::regex_search(mode,
r)) {
384 <<
"Unrecognized value of readMode parameter: \"" << mode
385 <<
"\". Valid values are:\n" 387 <<
" randomReplace (random is accepted for reasons of legacy),\n" 388 <<
" randomLimReplace,\n" 389 <<
" randomNoReplace.\n";
395 std::string filename;
398 if (filename.empty()) {
410 <<
"Wrapping around to initial input file for mixing after " 425 auto transMap = buildProductIDTransMap(
mixOps_);
432 std::random_device rd;
433 std::mt19937 g{rd()};
442 label_t const& engine_label)
const 444 auto const& default_engine_kind =
446 if (kind_of_engine_to_make == default_engine_kind && engine_label.empty()) {
447 mf::LogInfo{
"RANDOM"} <<
"A random number engine has already been created " 448 "since the read mode is " 453 "An error occurred while creating a random number engine " 454 "within a MixFilter detail class.\n"}
455 <<
"A random number engine with an empty label has already been created " 456 "with an engine type of " 457 << default_engine_kind <<
".\n" 458 <<
"If you would like to use a different engine type, please supply a " 459 "different engine label.\n";
462 cet::exempt_ptr<art::MixHelper::base_engine_t>
467 if (ServiceRegistry::isAvailable<RandomNumberGenerator>()) {
471 <<
"Random event mixing selected but RandomNumberGenerator service " 473 <<
"Ensure service is loaded with: \n" 474 <<
"services.RandomNumberGenerator: {}\n";
479 std::unique_ptr<CLHEP::RandFlat>
482 return engine ? std::make_unique<CLHEP::RandFlat>(*engine) :
nullptr;
base_engine_t & createEngine(seed_t seed)
void registerSecondaryFileNameProvider(ProviderFunc_ func)
std::vector< std::string >::const_iterator fileIter_
std::vector< EventAuxiliary > EventAuxiliarySequence
std::function< size_t()> eventsToSkip_
std::vector< EventID > EventIDSequence
decltype(auto) constexpr cend(T &&obj)
ADL-aware version of std::cend.
ProviderFunc_ providerFunc_
Mode initReadMode_(std::string const &mode) const
cet::exempt_ptr< base_engine_t > initEngine_(seed_t seed, Mode readMode)
void mixAndPut(EntryNumberSequence const &enSeq, EventIDSequence const &eIDseq, Event &e)
void setEventsToSkipFunction(std::function< size_t()> eventsToSkip)
bool consistentRequest_(std::string const &kind_of_engine_to_make, label_t const &engine_label) const
std::size_t totalEventsRead_
RNGsnapshot::label_t label_t
std::map< ProductID, ProductID > ProductIDTransMap
static constexpr ScheduleID first()
unsigned nOpensOverThreshold_
EntryNumberSequence shuffledSequence_
std::vector< std::string > const filenames_
base_engine_t & createEngine(seed_t seed)
std::unique_ptr< CLHEP::RandFlat > dist_
double const coverageFraction_
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
bool generateEventSequence(size_t nSecondaries, EntryNumberSequence &enSeq, EventIDSequence &eIDseq)
std::ostream & operator<<(std::ostream &os, const GroupSelector &gs)
virtual ProductID incomingProductID() const =0
virtual ProductID outgoingProductID() const =0
ProducesCollector & collector_
bool compactMissingProducts_
void prepareTranslationTables(ProductIDTransMap &transMap)
std::unique_ptr< MixIOPolicy > ioHandle_
MixHelper(Config const &config, std::string const &moduleLabel, ProducesCollector &collector, std::unique_ptr< MixIOPolicy > ioHandle)
CLHEP::HepRandomEngine base_engine_t
const_iterator findPosition(EventID const &eID) const
std::string const moduleLabel_
std::vector< FileIndex::EntryNumber_t > EntryNumberSequence
cet::exempt_ptr< base_engine_t > engine_
EntryType getEntryType() const
std::size_t nEventsReadThisFile_
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
std::function< std::string()> ProviderFunc_
std::map< FileIndex::EntryNumber_t, EventID > EventIDIndex
EventAuxiliarySequence generateEventAuxiliarySequence(EntryNumberSequence const &)
EventIDIndex eventIDIndex_
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
decltype(auto) constexpr cbegin(T &&obj)
ADL-aware version of std::cbegin.
PtrRemapper getRemapper(Event const &e) const
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
std::vector< std::unique_ptr< MixOpBase >> MixOpList
std::unique_ptr< CLHEP::RandFlat > initDist_(cet::exempt_ptr< base_engine_t > engine) const
ProdToProdMapBuilder ptpBuilder_
virtual BranchType branchType() const =0