Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-07 04:35:52

0001 // -*- C++ -*-
0002 //
0003 // Package:     FWLite
0004 // Class  :     Event
0005 //
0006 // Implementation:
0007 //     <Notes on implementation>
0008 //
0009 // Original Author:  Chris Jones
0010 //         Created:  Tue May  8 15:07:03 EDT 2007
0011 //
0012 
0013 // system include files
0014 #include <iostream>
0015 
0016 // user include files
0017 #include "DataFormats/FWLite/interface/Event.h"
0018 #include "TFile.h"
0019 #include "TTree.h"
0020 #include "FWCore/Utilities/interface/Exception.h"
0021 #include "DataFormats/Provenance/interface/BranchType.h"
0022 #include "DataFormats/Common/interface/EDProductGetter.h"
0023 
0024 #include "DataFormats/Provenance/interface/FileFormatVersion.h"
0025 #include "DataFormats/Provenance/interface/History.h"
0026 #include "DataFormats/Provenance/interface/ProcessHistoryID.h"
0027 
0028 #include "FWCore/FWLite/interface/setRefStreamer.h"
0029 
0030 #include "DataFormats/Provenance/interface/ParameterSetBlob.h"
0031 #include "DataFormats/Provenance/interface/ParameterSetID.h"
0032 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0033 #include "FWCore/ParameterSet/interface/Registry.h"
0034 #include "FWCore/ParameterSet/interface/ParameterSetConverter.h"
0035 #include "DataFormats/FWLite/interface/Handle.h"
0036 #include "DataFormats/Common/interface/TriggerResults.h"
0037 #include "FWCore/Common/interface/TriggerResultsByName.h"
0038 #include "DataFormats/FWLite/interface/EventHistoryGetter.h"
0039 #include "DataFormats/FWLite/interface/RunFactory.h"
0040 
0041 //used for backwards compatability
0042 #include "DataFormats/Provenance/interface/EventAux.h"
0043 
0044 //
0045 // constants, enums and typedefs
0046 //
0047 namespace {
0048   struct NoDelete {
0049     void operator()(void*) {}
0050   };
0051 }  // namespace
0052 
0053 namespace fwlite {
0054   //
0055   // static data member definitions
0056   //
0057   namespace internal {
0058     class ProductGetter : public edm::EDProductGetter {
0059     public:
0060       ProductGetter(Event* iEvent) : event_(iEvent) {}
0061 
0062       edm::WrapperBase const* getIt(edm::ProductID const& iID) const override { return event_->getByProductID(iID); }
0063 
0064       // getThinnedProduct assumes getIt was already called and failed to find
0065       // the product. The input key is the index of the desired element in the
0066       // container identified by ProductID (which cannot be found).
0067       // If the return value is not null, then the desired element was
0068       // found in a thinned container. If the desired element is not
0069       // found, then an optional without a value is returned.
0070       std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> getThinnedProduct(
0071           edm::ProductID const& pid, unsigned int key) const override {
0072         return event_->getThinnedProduct(pid, key);
0073       }
0074 
0075       // getThinnedProducts assumes getIt was already called and failed to find
0076       // the product. The input keys are the indexes into the container identified
0077       // by ProductID (which cannot be found). On input the WrapperBase pointers
0078       // must all be set to nullptr (except when the function calls itself
0079       // recursively where non-null pointers mark already found elements).
0080       // Thinned containers derived from the product are searched to see
0081       // if they contain the desired elements. For each that is
0082       // found, the corresponding WrapperBase pointer is set and the key
0083       // is modified to be the key into the container where the element
0084       // was found. The WrapperBase pointers might or might not all point
0085       // to the same thinned container.
0086       void getThinnedProducts(edm::ProductID const& pid,
0087                               std::vector<edm::WrapperBase const*>& foundContainers,
0088                               std::vector<unsigned int>& keys) const override {
0089         event_->getThinnedProducts(pid, foundContainers, keys);
0090       }
0091 
0092       // This overload is allowed to be called also without getIt()
0093       // being called first, but the thinned ProductID must come from an
0094       // existing RefCore. The input key is the index of the desired
0095       // element in the container identified by the parent ProductID.
0096       // If the return value is not null, then the desired element was found
0097       // in a thinned container. If the desired element is not found, then
0098       // an optional without a value is returned.
0099       edm::OptionalThinnedKey getThinnedKeyFrom(edm::ProductID const& parent,
0100                                                 unsigned int key,
0101                                                 edm::ProductID const& thinned) const override {
0102         return event_->getThinnedKeyFrom(parent, key, thinned);
0103       }
0104 
0105     private:
0106       unsigned int transitionIndex_() const override { return 0U; }
0107 
0108       Event const* event_;
0109     };
0110   }  // namespace internal
0111   //
0112   // constructors and destructor
0113   //
0114   Event::Event(TFile* iFile, bool useCache, std::function<void(TBranch const&)> baFunc)
0115       : file_(iFile),
0116         //  eventTree_(nullptr),
0117         eventHistoryTree_(nullptr),
0118         //  eventIndex_(-1),
0119         branchMap_(iFile),
0120         pAux_(&aux_),
0121         pOldAux_(nullptr),
0122         fileVersion_(-1),
0123         parameterSetRegistryFilled_(false),
0124         dataHelper_(branchMap_.getEventTree(),
0125                     std::make_shared<EventHistoryGetter>(this),
0126                     std::shared_ptr<BranchMapReader>(&branchMap_, NoDelete()),
0127                     std::make_shared<internal::ProductGetter>(this),
0128                     useCache,
0129                     baFunc) {
0130     if (nullptr == iFile) {
0131       throw cms::Exception("NoFile") << "The TFile pointer passed to the constructor was null";
0132     }
0133 
0134     if (nullptr == branchMap_.getEventTree()) {
0135       throw cms::Exception("NoEventTree") << "The TFile contains no TTree named " << edm::poolNames::eventTreeName();
0136     }
0137     //need to know file version in order to determine how to read the basic event info
0138     fileVersion_ = branchMap_.getFileVersion(iFile);
0139 
0140     //got this logic from IOPool/Input/src/RootFile.cc
0141 
0142     TTree* eventTree = branchMap_.getEventTree();
0143     if (fileVersion_ >= 3) {
0144       auxBranch_ = eventTree->GetBranch(edm::BranchTypeToAuxiliaryBranchName(edm::InEvent).c_str());
0145       if (nullptr == auxBranch_) {
0146         throw cms::Exception("NoEventAuxilliary")
0147             << "The TTree " << edm::poolNames::eventTreeName() << " does not contain a branch named 'EventAuxiliary'";
0148       }
0149       auxBranch_->SetAddress(&pAux_);
0150     } else {
0151       pOldAux_ = new edm::EventAux();
0152       auxBranch_ = eventTree->GetBranch(edm::BranchTypeToAuxBranchName(edm::InEvent).c_str());
0153       if (nullptr == auxBranch_) {
0154         throw cms::Exception("NoEventAux")
0155             << "The TTree " << edm::poolNames::eventTreeName() << " does not contain a branch named 'EventAux'";
0156       }
0157       auxBranch_->SetAddress(&pOldAux_);
0158     }
0159     branchMap_.updateEvent(0);
0160 
0161     if (fileVersion_ >= 7 && fileVersion_ < 17) {
0162       eventHistoryTree_ = dynamic_cast<TTree*>(iFile->Get(edm::poolNames::eventHistoryTreeName().c_str()));
0163     }
0164     runFactory_ = std::make_shared<RunFactory>();
0165   }
0166 
0167   // Event::Event(Event const& rhs)
0168   // {
0169   //    // do actual copying here;
0170   // }
0171 
0172   Event::~Event() {
0173     for (auto const& label : labels_) {
0174       delete[] label;
0175     }
0176     delete pOldAux_;
0177   }
0178 
0179   //
0180   // assignment operators
0181   //
0182   // Event const& Event::operator=(Event const& rhs) {
0183   //   //An exception safe implementation is
0184   //   Event temp(rhs);
0185   //   swap(rhs);
0186   //
0187   //   return *this;
0188   // }
0189 
0190   //
0191   // member functions
0192   //
0193 
0194   Event const& Event::operator++() {
0195     Long_t eventIndex = branchMap_.getEventEntry();
0196     if (eventIndex < size()) {
0197       branchMap_.updateEvent(++eventIndex);
0198     }
0199     return *this;
0200   }
0201 
0202   Long64_t Event::indexFromEventId(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, edm::EventNumber_t event) {
0203     entryFinder_.fillIndex(branchMap_);
0204     EntryFinder::EntryNumber_t entry = entryFinder_.findEvent(run, lumi, event);
0205     return (entry == EntryFinder::invalidEntry) ? -1 : entry;
0206   }
0207 
0208   bool Event::to(Long64_t iEntry) {
0209     if (iEntry < size()) {
0210       // this is a valid entry
0211       return branchMap_.updateEvent(iEntry);
0212     }
0213     // if we're here, then iEntry was not valid
0214     return false;
0215   }
0216 
0217   bool Event::to(edm::RunNumber_t run, edm::EventNumber_t event) { return to(run, 0U, event); }
0218 
0219   bool Event::to(edm::RunNumber_t run, edm::LuminosityBlockNumber_t lumi, edm::EventNumber_t event) {
0220     entryFinder_.fillIndex(branchMap_);
0221     EntryFinder::EntryNumber_t entry = entryFinder_.findEvent(run, lumi, event);
0222     if (entry == EntryFinder::invalidEntry) {
0223       return false;
0224     }
0225     return branchMap_.updateEvent(entry);
0226   }
0227 
0228   bool Event::to(const edm::EventID& id) { return to(id.run(), id.luminosityBlock(), id.event()); }
0229 
0230   Event const& Event::toBegin() {
0231     branchMap_.updateEvent(0);
0232     return *this;
0233   }
0234 
0235   //
0236   // const member functions
0237   //
0238   void Event::draw(Option_t* opt) {
0239     GetterOperate op(dataHelper_.getter());
0240     branchMap_.getEventTree()->Draw(opt);
0241   }
0242   Long64_t Event::draw(
0243       char const* varexp, const TCut& selection, Option_t* option, Long64_t nentries, Long64_t firstentry) {
0244     GetterOperate op(dataHelper_.getter());
0245     return branchMap_.getEventTree()->Draw(varexp, selection, option, nentries, firstentry);
0246   }
0247   Long64_t Event::draw(
0248       char const* varexp, char const* selection, Option_t* option, Long64_t nentries, Long64_t firstentry) {
0249     GetterOperate op(dataHelper_.getter());
0250     return branchMap_.getEventTree()->Draw(varexp, selection, option, nentries, firstentry);
0251   }
0252   Long64_t Event::scan(
0253       char const* varexp, char const* selection, Option_t* option, Long64_t nentries, Long64_t firstentry) {
0254     GetterOperate op(dataHelper_.getter());
0255     return branchMap_.getEventTree()->Scan(varexp, selection, option, nentries, firstentry);
0256   }
0257 
0258   Long64_t Event::size() const { return branchMap_.getEventTree()->GetEntries(); }
0259 
0260   bool Event::isValid() const {
0261     Long_t eventIndex = branchMap_.getEventEntry();
0262     return eventIndex != -1 and eventIndex < size();
0263   }
0264 
0265   Event::operator bool() const { return isValid(); }
0266 
0267   bool Event::atEnd() const {
0268     Long_t eventIndex = branchMap_.getEventEntry();
0269     return eventIndex == -1 or eventIndex == size();
0270   }
0271 
0272   std::vector<std::string> const& Event::getProcessHistory() const {
0273     if (procHistoryNames_.empty()) {
0274       for (auto const& proc : history()) {
0275         procHistoryNames_.push_back(proc.processName());
0276       }
0277     }
0278     return procHistoryNames_;
0279   }
0280 
0281   std::string const Event::getBranchNameFor(std::type_info const& iInfo,
0282                                             char const* iModuleLabel,
0283                                             char const* iProductInstanceLabel,
0284                                             char const* iProcessLabel) const {
0285     return dataHelper_.getBranchNameFor(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel);
0286   }
0287 
0288   bool Event::getByLabel(std::type_info const& iInfo,
0289                          char const* iModuleLabel,
0290                          char const* iProductInstanceLabel,
0291                          char const* iProcessLabel,
0292                          void* oData) const {
0293     if (atEnd()) {
0294       throw cms::Exception("OffEnd") << "You have requested data past the last event";
0295     }
0296     Long_t eventIndex = branchMap_.getEventEntry();
0297     return dataHelper_.getByLabel(iInfo, iModuleLabel, iProductInstanceLabel, iProcessLabel, oData, eventIndex);
0298   }
0299 
0300   bool Event::getByTokenImp(edm::EDGetToken iToken, edm::WrapperBase const*& oData) const {
0301     if (atEnd()) {
0302       throw cms::Exception("OffEnd") << "You have requested data past the last event";
0303     }
0304     Long_t eventIndex = branchMap_.getEventEntry();
0305     oData = dataHelper_.getByBranchID(edm::BranchID(iToken.index()), eventIndex);
0306     return oData != nullptr;
0307   }
0308 
0309   edm::EventAuxiliary const& Event::eventAuxiliary() const {
0310     Long_t eventIndex = branchMap_.getEventEntry();
0311     updateAux(eventIndex);
0312     return aux_;
0313   }
0314 
0315   void Event::updateAux(Long_t eventIndex) const {
0316     if (auxBranch_->GetEntryNumber() != eventIndex) {
0317       auxBranch_->GetEntry(eventIndex);
0318       //handling dealing with old version
0319       if (nullptr != pOldAux_) {
0320         conversion(*pOldAux_, aux_);
0321       }
0322     }
0323   }
0324 
0325   const edm::ProcessHistory& Event::history() const {
0326     edm::ProcessHistoryID processHistoryID;
0327 
0328     bool newFormat = (fileVersion_ >= 5);
0329 
0330     Long_t eventIndex = branchMap_.getEventEntry();
0331     updateAux(eventIndex);
0332     if (!newFormat) {
0333       processHistoryID = aux_.processHistoryID();
0334     }
0335     if (historyMap_.empty() || newFormat) {
0336       procHistoryNames_.clear();
0337       TTree* meta = dynamic_cast<TTree*>(branchMap_.getFile()->Get(edm::poolNames::metaDataTreeName().c_str()));
0338       if (nullptr == meta) {
0339         throw cms::Exception("NoMetaTree")
0340             << "The TFile does not appear to contain a TTree named " << edm::poolNames::metaDataTreeName();
0341       }
0342       if (historyMap_.empty()) {
0343         if (fileVersion_ < 11) {
0344           edm::ProcessHistoryMap* pPhm = &historyMap_;
0345           TBranch* b = meta->GetBranch(edm::poolNames::processHistoryMapBranchName().c_str());
0346           b->SetAddress(&pPhm);
0347           b->GetEntry(0);
0348         } else {
0349           edm::ProcessHistoryVector historyVector;
0350           edm::ProcessHistoryVector* pPhv = &historyVector;
0351           TBranch* b = meta->GetBranch(edm::poolNames::processHistoryBranchName().c_str());
0352           b->SetAddress(&pPhv);
0353           b->GetEntry(0);
0354           for (auto& history : historyVector) {
0355             historyMap_.insert(std::make_pair(history.setProcessHistoryID(), history));
0356           }
0357         }
0358       }
0359       if (newFormat) {
0360         if (fileVersion_ >= 17) {
0361           processHistoryID = aux_.processHistoryID();
0362         } else if (fileVersion_ >= 7) {
0363           edm::History history;
0364           edm::History* pHistory = &history;
0365           TBranch* eventHistoryBranch = eventHistoryTree_->GetBranch(edm::poolNames::eventHistoryBranchName().c_str());
0366           if (!eventHistoryBranch)
0367             throw edm::Exception(edm::errors::FatalRootError) << "Failed to find history branch in event history tree";
0368           eventHistoryBranch->SetAddress(&pHistory);
0369           eventHistoryTree_->GetEntry(eventIndex);
0370           processHistoryID = history.processHistoryID();
0371         } else {
0372           std::vector<edm::EventProcessHistoryID>* pEventProcessHistoryIDs = &eventProcessHistoryIDs_;
0373           TBranch* b = meta->GetBranch(edm::poolNames::eventHistoryBranchName().c_str());
0374           b->SetAddress(&pEventProcessHistoryIDs);
0375           b->GetEntry(0);
0376           edm::EventProcessHistoryID target(aux_.id(), edm::ProcessHistoryID());
0377           processHistoryID = std::lower_bound(eventProcessHistoryIDs_.begin(), eventProcessHistoryIDs_.end(), target)
0378                                  ->processHistoryID();
0379         }
0380       }
0381     }
0382 
0383     return historyMap_[processHistoryID];
0384   }
0385 
0386   edm::WrapperBase const* Event::getByProductID(edm::ProductID const& iID) const {
0387     Long_t eventEntry = branchMap_.getEventEntry();
0388     return dataHelper_.getByProductID(iID, eventEntry);
0389   }
0390 
0391   std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> Event::getThinnedProduct(edm::ProductID const& pid,
0392                                                                                             unsigned int key) const {
0393     Long_t eventEntry = branchMap_.getEventEntry();
0394     return dataHelper_.getThinnedProduct(pid, key, eventEntry);
0395   }
0396 
0397   void Event::getThinnedProducts(edm::ProductID const& pid,
0398                                  std::vector<edm::WrapperBase const*>& foundContainers,
0399                                  std::vector<unsigned int>& keys) const {
0400     Long_t eventEntry = branchMap_.getEventEntry();
0401     return dataHelper_.getThinnedProducts(pid, foundContainers, keys, eventEntry);
0402   }
0403 
0404   edm::OptionalThinnedKey Event::getThinnedKeyFrom(edm::ProductID const& parent,
0405                                                    unsigned int key,
0406                                                    edm::ProductID const& thinned) const {
0407     Long_t eventEntry = branchMap_.getEventEntry();
0408     return dataHelper_.getThinnedKeyFrom(parent, key, thinned, eventEntry);
0409   }
0410 
0411   edm::TriggerNames const& Event::triggerNames(edm::TriggerResults const& triggerResults) const {
0412     edm::TriggerNames const* names = triggerNames_(triggerResults);
0413     if (names != nullptr)
0414       return *names;
0415 
0416     if (!parameterSetRegistryFilled_) {
0417       fillParameterSetRegistry();
0418       names = triggerNames_(triggerResults);
0419     }
0420     if (names != nullptr)
0421       return *names;
0422 
0423     throw cms::Exception("TriggerNamesNotFound") << "TriggerNames not found in ParameterSet registry";
0424     return *names;
0425   }
0426 
0427   void Event::fillParameterSetRegistry() const {
0428     if (parameterSetRegistryFilled_)
0429       return;
0430     parameterSetRegistryFilled_ = true;
0431 
0432     TTree* meta = dynamic_cast<TTree*>(branchMap_.getFile()->Get(edm::poolNames::metaDataTreeName().c_str()));
0433     if (nullptr == meta) {
0434       throw cms::Exception("NoMetaTree") << "The TFile does not contain a TTree named "
0435                                          << edm::poolNames::metaDataTreeName();
0436     }
0437 
0438     edm::FileFormatVersion fileFormatVersion;
0439     edm::FileFormatVersion* fftPtr = &fileFormatVersion;
0440     if (meta->FindBranch(edm::poolNames::fileFormatVersionBranchName().c_str()) != nullptr) {
0441       TBranch* fft = meta->GetBranch(edm::poolNames::fileFormatVersionBranchName().c_str());
0442       fft->SetAddress(&fftPtr);
0443       fft->GetEntry(0);
0444     }
0445 
0446     typedef std::map<edm::ParameterSetID, edm::ParameterSetBlob> PsetMap;
0447     PsetMap psetMap;
0448     TTree* psetTree(nullptr);
0449     if (meta->FindBranch(edm::poolNames::parameterSetMapBranchName().c_str()) != nullptr) {
0450       PsetMap* psetMapPtr = &psetMap;
0451       TBranch* b = meta->GetBranch(edm::poolNames::parameterSetMapBranchName().c_str());
0452       b->SetAddress(&psetMapPtr);
0453       b->GetEntry(0);
0454     } else if (nullptr == (psetTree = dynamic_cast<TTree*>(
0455                                branchMap_.getFile()->Get(edm::poolNames::parameterSetsTreeName().c_str())))) {
0456       throw cms::Exception("NoParameterSetMapTree")
0457           << "The TTree " << edm::poolNames::parameterSetsTreeName() << " could not be found in the file.";
0458     } else {
0459       typedef std::pair<edm::ParameterSetID, edm::ParameterSetBlob> IdToBlobs;
0460       IdToBlobs idToBlob;
0461       IdToBlobs* pIdToBlob = &idToBlob;
0462       psetTree->SetBranchAddress(edm::poolNames::idToParameterSetBlobsBranchName().c_str(), &pIdToBlob);
0463       for (long long i = 0; i != psetTree->GetEntries(); ++i) {
0464         psetTree->GetEntry(i);
0465         psetMap.insert(idToBlob);
0466       }
0467     }
0468     edm::ParameterSetConverter::ParameterSetIdConverter psetIdConverter;
0469     if (!fileFormatVersion.triggerPathsTracked()) {
0470       edm::ParameterSetConverter converter(psetMap, psetIdConverter, fileFormatVersion.parameterSetsByReference());
0471     } else {
0472       // Merge into the parameter set registry.
0473       edm::pset::Registry& psetRegistry = *edm::pset::Registry::instance();
0474       for (auto const& item : psetMap) {
0475         edm::ParameterSet pset(item.second.pset());
0476         pset.setID(item.first);
0477         psetRegistry.insertMapped(pset);
0478       }
0479     }
0480   }
0481 
0482   edm::ParameterSet const* Event::parameterSet(edm::ParameterSetID const& psID) const {
0483     if (!parameterSetRegistryFilled_) {
0484       fillParameterSetRegistry();
0485     }
0486     return parameterSetForID_(psID);
0487   }
0488 
0489   edm::TriggerResultsByName Event::triggerResultsByName(edm::TriggerResults const& triggerResults) const {
0490     edm::TriggerNames const* names = triggerNames_(triggerResults);
0491     if (names == nullptr && !parameterSetRegistryFilled_) {
0492       fillParameterSetRegistry();
0493       names = triggerNames_(triggerResults);
0494     }
0495     return edm::TriggerResultsByName(&triggerResults, names);
0496   }
0497 
0498   //
0499   // static member functions
0500   //
0501   void Event::throwProductNotFoundException(std::type_info const& iType,
0502                                             char const* iModule,
0503                                             char const* iProduct,
0504                                             char const* iProcess) {
0505     edm::TypeID type(iType);
0506     throw edm::Exception(edm::errors::ProductNotFound)
0507         << "A branch was found for \n  type ='" << type.className() << "'\n  module='" << iModule
0508         << "'\n  productInstance='" << ((nullptr != iProduct) ? iProduct : "") << "'\n  process='"
0509         << ((nullptr != iProcess) ? iProcess : "")
0510         << "'\n"
0511            "but no data is available for this Event";
0512   }
0513 
0514   fwlite::LuminosityBlock const& Event::getLuminosityBlock() const {
0515     if (not lumi_) {
0516       // Branch map pointer not really being shared, owned by event, have to trick Lumi
0517       lumi_ = std::make_shared<fwlite::LuminosityBlock>(std::shared_ptr<BranchMapReader>(&branchMap_, NoDelete()),
0518                                                         runFactory_);
0519     }
0520     edm::RunNumber_t run = eventAuxiliary().run();
0521     edm::LuminosityBlockNumber_t lumi = eventAuxiliary().luminosityBlock();
0522     lumi_->to(run, lumi);
0523     return *lumi_;
0524   }
0525 
0526   fwlite::Run const& Event::getRun() const {
0527     run_ = runFactory_->makeRun(std::shared_ptr<BranchMapReader>(&branchMap_, NoDelete()));
0528     edm::RunNumber_t run = eventAuxiliary().run();
0529     run_->to(run);
0530     return *run_;
0531   }
0532 
0533 }  // namespace fwlite