14 #include "canvas_root_io/Streamers/ProductIDStreamer.h" 15 #include "cetlib/container_algorithms.h" 24 #include <unordered_set> 34 for (
auto const& element : fileIndex) {
37 result.emplace(element.entry_, element.eventID_);
42 class EventIDLookup :
public std::unary_function<Long64_t, art::EventID> {
45 result_type operator()(argument_type entry)
const;
52 initDataTrees(cet::value_ptr<TFile>
const& currentFile)
56 result[bt].reset(static_cast<TTree*>(currentFile->Get(
61 <<
"Unable to read event tree from secondary event stream file " 62 << currentFile->GetName() <<
".\n";
73 EventIDLookup::result_type
74 EventIDLookup::operator()(argument_type entry)
const 76 auto i = index_.find(entry);
77 if (i == cend(index_)) {
79 <<
"MixHelper could not find entry number " << entry
80 <<
" in its own lookup table.\n";
89 auto result = pset.
get<
double>(
"coverageFraction", 1.0);
90 if (result > (1 + std::numeric_limits<double>::epsilon())) {
92 <<
"coverageFraction > 1: treating as a percentage.\n";
98 std::unique_ptr<CLHEP::RandFlat>
102 std::unique_ptr<CLHEP::RandFlat> result;
104 if (ServiceRegistry::isAvailable<RandomNumberGenerator>()) {
105 result = std::make_unique<CLHEP::RandFlat>(
109 <<
"Random event mixing selected but RandomNumberGenerator service " 111 <<
"Ensure service is loaded with: \n" 112 <<
"services.RandomNumberGenerator: {}\n";
121 : producesProvider_{producesProvider}
122 ,
filenames_{pset.get<std::vector<std::string>>(
"fileNames", {})}
136 <<
"Provision of a secondary file name provider is incompatible" 137 <<
" with a\nnon-empty fileNames parameter to the mix filter.\n";
147 assert(enSeq.empty());
148 assert(eIDseq.empty());
150 bool over_threshold =
165 enSeq.reserve(nSecondaries);
174 std::generate_n(std::back_inserter(enSeq), nSecondaries, [
this] {
177 std::sort(enSeq.begin(), enSeq.end());
180 std::unordered_set<EntryNumberSequence::value_type>
182 while (entries.size() < nSecondaries) {
184 std::inserter(entries, entries.begin()),
185 nSecondaries - entries.size(),
188 enSeq.assign(cbegin(entries), cend(entries));
189 std::sort(
begin(enSeq),
end(enSeq));
195 assert(enSeq.size() == nSecondaries);
199 enSeq.assign(i, i + nSecondaries);
203 <<
"Unrecognized read mode " <<
static_cast<int>(
readMode_)
204 <<
". Contact the art developers.\n";
207 enSeq, std::back_inserter(eIDseq), EventIDLookup{
eventIDIndex_});
218 auto aux = std::make_unique<EventAuxiliary>();
219 auto pAux = aux.get();
220 auxBranch->SetAddress(&pAux);
221 for (
auto const entry : enseq) {
222 auto err = eventTree->LoadTree(entry);
233 auxseq.push_back(*pAux);
236 auxBranch->SetAddress(
nullptr);
252 subRunEntries.reserve(eIDseq.size());
253 for (
auto const& eID : eIDseq) {
256 subRunEntries.emplace_back(it->entry_);
259 <<
"- Unable to find an entry in the SubRun tree corresponding to " 261 << eID <<
" in secondary mixing input file " 267 runEntries.reserve(eIDseq.size());
268 for (
auto const& eID : eIDseq) {
271 runEntries.emplace_back(it->entry_);
274 <<
"- Unable to find an entry in the Run tree corresponding to event " 276 << eID <<
" in secondary mixing input file " 282 for (
auto const& op :
mixOps_) {
283 switch (op->branchType()) {
289 op->readFromFile(subRunEntries,
nullptr);
291 op->mixAndPut(e, nopRemapper);
294 op->readFromFile(runEntries,
nullptr);
296 op->mixAndPut(e, nopRemapper);
300 <<
"- MixHelper::mixAndPut() attempted to handle unsupported branch " 302 << op->branchType() <<
".\n";
320 static std::regex
const robjs[4]{
321 std::regex(
"^seq", std::regex_constants::icase),
322 std::regex(
"^random(replace)?$", std::regex_constants::icase),
323 std::regex(
"^randomlimreplace$", std::regex_constants::icase),
324 std::regex(
"^randomnoreplace$", std::regex_constants::icase)};
326 for (
auto const& r : robjs) {
327 if (std::regex_search(mode, r)) {
334 <<
"Unrecognized value of readMode parameter: \"" << mode
335 <<
"\". Valid values are:\n" 337 <<
" randomReplace (random is accepted for reasons of legacy),\n" 338 <<
" randomLimReplace,\n" 339 <<
" randomNoReplace.\n";
351 <<
"Unable to open specified secondary event stream file " << filename
356 <<
"Unable to open specified secondary event stream file " << filename
364 <<
"Unable to read meta data tree from secondary event stream file " 365 << filename <<
".\n";
379 BranchIDLists branchIDLists{};
381 branchIDLists_ = std::make_unique<BranchIDLists>(std::move(branchIDLists));
389 <<
"Can only read files written during the \"" << expected_era
392 <<
"\"" << filename <<
"\" was " 415 [
this](EntryNumberSequence::difference_type
const&
n) {
416 return dist_.get()->fireInt(
n);
424 std::string filename;
427 if (filename.empty()) {
439 <<
"Wrapping around to initial input file for mixing after " 460 auto const bt = mixOp->branchType();
462 #if ART_DEBUG_PTRREMAPPER 463 std::cerr <<
"BranchIDTransMap: " << std::hex << std::setfill(
'0')
464 << std::setw(8) << mixOp->incomingProductID() <<
" -> " 465 << std::setw(8) << mixOp->outgoingProductID() << std::dec
469 transMap[mixOp->incomingProductID()] = mixOp->outgoingProductID();
void registerSecondaryFileNameProvider(ProviderFunc_ func)
std::vector< std::string >::const_iterator fileIter_
std::vector< EventAuxiliary > EventAuxiliarySequence
std::function< size_t()> eventsToSkip_
std::vector< EventID > EventIDSequence
cet::value_ptr< TFile > currentFile_
ProviderFunc_ providerFunc_
Mode initReadMode_(std::string const &mode) const
void mixAndPut(EntryNumberSequence const &enSeq, EventIDSequence const &eIDseq, Event &e)
void setEventsToSkipFunction(std::function< size_t()> eventsToSkip)
void readFileIndex(TFile *file, TTree *metaDataTree, FileIndex *&findexPtr)
MixHelper(fhicl::ParameterSet const &pset, ProducerBase &producesProvider)
std::array< cet::exempt_ptr< TTree >, art::BranchType::NumBranchTypes > currentDataTrees_
std::string const & dataTreeName(BranchType bt)
std::map< ProductID, ProductID > ProductIDTransMap
FileFormatVersion ffVersion_
EntryNumberSequence shuffledSequence_
std::unique_ptr< art::BranchIDLists > branchIDLists_
std::string const & BranchTypeToAuxiliaryBranchName(BranchType const bt)
std::vector< std::string > const filenames_
std::unique_ptr< CLHEP::RandFlat > dist_
double const coverageFraction_
std::array< RootBranchInfoList, art::BranchType::NumBranchTypes > dataBranches_
Long64_t nEventsReadThisFile_
bool generateEventSequence(size_t nSecondaries, EntryNumberSequence &enSeq, EventIDSequence &eIDseq)
std::string const & metaDataTreeName()
FileIndex currentFileIndex_
cet::exempt_ptr< TTree > currentMetaDataTree_
bool compactMissingProducts_
void prepareTranslationTables(ProductIDTransMap &transMap)
T get(std::string const &key) const
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
void generateEventAuxiliarySequence(EntryNumberSequence const &, EventAuxiliarySequence &)
const_iterator cend() const
const_iterator findPosition(EventID const &eID) const
std::vector< FileIndex::EntryNumber_t > EntryNumberSequence
void buildProductIDTransMap_(ProdToProdMapBuilder::ProductIDTransMap &transMap)
std::string const & getFileFormatEra()
void openAndReadMetaData_(std::string fileName)
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
std::map< FileIndex::EntryNumber_t, EventID > EventIDIndex
std::function< std::string()> ProviderFunc_
EventIDIndex eventIDIndex_
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
ProdToProdMapBuilder ptpBuilder_
void populateRemapper(PtrRemapper &mapper, Event &e) const
T readMetadata(TTree *md, bool const requireDict=true)
cet::coded_exception< error, detail::translate > exception
Long64_t totalEventsRead_