Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:53:26

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   edm::EventAuxiliary const& Event::eventAuxiliary() const {
0301     Long_t eventIndex = branchMap_.getEventEntry();
0302     updateAux(eventIndex);
0303     return aux_;
0304   }
0305 
0306   void Event::updateAux(Long_t eventIndex) const {
0307     if (auxBranch_->GetEntryNumber() != eventIndex) {
0308       auxBranch_->GetEntry(eventIndex);
0309       //handling dealing with old version
0310       if (nullptr != pOldAux_) {
0311         conversion(*pOldAux_, aux_);
0312       }
0313     }
0314   }
0315 
0316   const edm::ProcessHistory& Event::history() const {
0317     edm::ProcessHistoryID processHistoryID;
0318 
0319     bool newFormat = (fileVersion_ >= 5);
0320 
0321     Long_t eventIndex = branchMap_.getEventEntry();
0322     updateAux(eventIndex);
0323     if (!newFormat) {
0324       processHistoryID = aux_.processHistoryID();
0325     }
0326     if (historyMap_.empty() || newFormat) {
0327       procHistoryNames_.clear();
0328       TTree* meta = dynamic_cast<TTree*>(branchMap_.getFile()->Get(edm::poolNames::metaDataTreeName().c_str()));
0329       if (nullptr == meta) {
0330         throw cms::Exception("NoMetaTree")
0331             << "The TFile does not appear to contain a TTree named " << edm::poolNames::metaDataTreeName();
0332       }
0333       if (historyMap_.empty()) {
0334         if (fileVersion_ < 11) {
0335           edm::ProcessHistoryMap* pPhm = &historyMap_;
0336           TBranch* b = meta->GetBranch(edm::poolNames::processHistoryMapBranchName().c_str());
0337           b->SetAddress(&pPhm);
0338           b->GetEntry(0);
0339         } else {
0340           edm::ProcessHistoryVector historyVector;
0341           edm::ProcessHistoryVector* pPhv = &historyVector;
0342           TBranch* b = meta->GetBranch(edm::poolNames::processHistoryBranchName().c_str());
0343           b->SetAddress(&pPhv);
0344           b->GetEntry(0);
0345           for (auto& history : historyVector) {
0346             historyMap_.insert(std::make_pair(history.setProcessHistoryID(), history));
0347           }
0348         }
0349       }
0350       if (newFormat) {
0351         if (fileVersion_ >= 17) {
0352           processHistoryID = aux_.processHistoryID();
0353         } else if (fileVersion_ >= 7) {
0354           edm::History history;
0355           edm::History* pHistory = &history;
0356           TBranch* eventHistoryBranch = eventHistoryTree_->GetBranch(edm::poolNames::eventHistoryBranchName().c_str());
0357           if (!eventHistoryBranch)
0358             throw edm::Exception(edm::errors::FatalRootError) << "Failed to find history branch in event history tree";
0359           eventHistoryBranch->SetAddress(&pHistory);
0360           eventHistoryTree_->GetEntry(eventIndex);
0361           processHistoryID = history.processHistoryID();
0362         } else {
0363           std::vector<edm::EventProcessHistoryID>* pEventProcessHistoryIDs = &eventProcessHistoryIDs_;
0364           TBranch* b = meta->GetBranch(edm::poolNames::eventHistoryBranchName().c_str());
0365           b->SetAddress(&pEventProcessHistoryIDs);
0366           b->GetEntry(0);
0367           edm::EventProcessHistoryID target(aux_.id(), edm::ProcessHistoryID());
0368           processHistoryID = std::lower_bound(eventProcessHistoryIDs_.begin(), eventProcessHistoryIDs_.end(), target)
0369                                  ->processHistoryID();
0370         }
0371       }
0372     }
0373 
0374     return historyMap_[processHistoryID];
0375   }
0376 
0377   edm::WrapperBase const* Event::getByProductID(edm::ProductID const& iID) const {
0378     Long_t eventEntry = branchMap_.getEventEntry();
0379     return dataHelper_.getByProductID(iID, eventEntry);
0380   }
0381 
0382   std::optional<std::tuple<edm::WrapperBase const*, unsigned int>> Event::getThinnedProduct(edm::ProductID const& pid,
0383                                                                                             unsigned int key) const {
0384     Long_t eventEntry = branchMap_.getEventEntry();
0385     return dataHelper_.getThinnedProduct(pid, key, eventEntry);
0386   }
0387 
0388   void Event::getThinnedProducts(edm::ProductID const& pid,
0389                                  std::vector<edm::WrapperBase const*>& foundContainers,
0390                                  std::vector<unsigned int>& keys) const {
0391     Long_t eventEntry = branchMap_.getEventEntry();
0392     return dataHelper_.getThinnedProducts(pid, foundContainers, keys, eventEntry);
0393   }
0394 
0395   edm::OptionalThinnedKey Event::getThinnedKeyFrom(edm::ProductID const& parent,
0396                                                    unsigned int key,
0397                                                    edm::ProductID const& thinned) const {
0398     Long_t eventEntry = branchMap_.getEventEntry();
0399     return dataHelper_.getThinnedKeyFrom(parent, key, thinned, eventEntry);
0400   }
0401 
0402   edm::TriggerNames const& Event::triggerNames(edm::TriggerResults const& triggerResults) const {
0403     edm::TriggerNames const* names = triggerNames_(triggerResults);
0404     if (names != nullptr)
0405       return *names;
0406 
0407     if (!parameterSetRegistryFilled_) {
0408       fillParameterSetRegistry();
0409       names = triggerNames_(triggerResults);
0410     }
0411     if (names != nullptr)
0412       return *names;
0413 
0414     throw cms::Exception("TriggerNamesNotFound") << "TriggerNames not found in ParameterSet registry";
0415     return *names;
0416   }
0417 
0418   void Event::fillParameterSetRegistry() const {
0419     if (parameterSetRegistryFilled_)
0420       return;
0421     parameterSetRegistryFilled_ = true;
0422 
0423     TTree* meta = dynamic_cast<TTree*>(branchMap_.getFile()->Get(edm::poolNames::metaDataTreeName().c_str()));
0424     if (nullptr == meta) {
0425       throw cms::Exception("NoMetaTree") << "The TFile does not contain a TTree named "
0426                                          << edm::poolNames::metaDataTreeName();
0427     }
0428 
0429     edm::FileFormatVersion fileFormatVersion;
0430     edm::FileFormatVersion* fftPtr = &fileFormatVersion;
0431     if (meta->FindBranch(edm::poolNames::fileFormatVersionBranchName().c_str()) != nullptr) {
0432       TBranch* fft = meta->GetBranch(edm::poolNames::fileFormatVersionBranchName().c_str());
0433       fft->SetAddress(&fftPtr);
0434       fft->GetEntry(0);
0435     }
0436 
0437     typedef std::map<edm::ParameterSetID, edm::ParameterSetBlob> PsetMap;
0438     PsetMap psetMap;
0439     TTree* psetTree(nullptr);
0440     if (meta->FindBranch(edm::poolNames::parameterSetMapBranchName().c_str()) != nullptr) {
0441       PsetMap* psetMapPtr = &psetMap;
0442       TBranch* b = meta->GetBranch(edm::poolNames::parameterSetMapBranchName().c_str());
0443       b->SetAddress(&psetMapPtr);
0444       b->GetEntry(0);
0445     } else if (nullptr == (psetTree = dynamic_cast<TTree*>(
0446                                branchMap_.getFile()->Get(edm::poolNames::parameterSetsTreeName().c_str())))) {
0447       throw cms::Exception("NoParameterSetMapTree")
0448           << "The TTree " << edm::poolNames::parameterSetsTreeName() << " could not be found in the file.";
0449     } else {
0450       typedef std::pair<edm::ParameterSetID, edm::ParameterSetBlob> IdToBlobs;
0451       IdToBlobs idToBlob;
0452       IdToBlobs* pIdToBlob = &idToBlob;
0453       psetTree->SetBranchAddress(edm::poolNames::idToParameterSetBlobsBranchName().c_str(), &pIdToBlob);
0454       for (long long i = 0; i != psetTree->GetEntries(); ++i) {
0455         psetTree->GetEntry(i);
0456         psetMap.insert(idToBlob);
0457       }
0458     }
0459     edm::ParameterSetConverter::ParameterSetIdConverter psetIdConverter;
0460     if (!fileFormatVersion.triggerPathsTracked()) {
0461       edm::ParameterSetConverter converter(psetMap, psetIdConverter, fileFormatVersion.parameterSetsByReference());
0462     } else {
0463       // Merge into the parameter set registry.
0464       edm::pset::Registry& psetRegistry = *edm::pset::Registry::instance();
0465       for (auto const& item : psetMap) {
0466         edm::ParameterSet pset(item.second.pset());
0467         pset.setID(item.first);
0468         psetRegistry.insertMapped(pset);
0469       }
0470     }
0471   }
0472 
0473   edm::ParameterSet const* Event::parameterSet(edm::ParameterSetID const& psID) const {
0474     if (!parameterSetRegistryFilled_) {
0475       fillParameterSetRegistry();
0476     }
0477     return parameterSetForID_(psID);
0478   }
0479 
0480   edm::TriggerResultsByName Event::triggerResultsByName(edm::TriggerResults const& triggerResults) const {
0481     edm::TriggerNames const* names = triggerNames_(triggerResults);
0482     if (names == nullptr && !parameterSetRegistryFilled_) {
0483       fillParameterSetRegistry();
0484       names = triggerNames_(triggerResults);
0485     }
0486     return edm::TriggerResultsByName(&triggerResults, names);
0487   }
0488 
0489   //
0490   // static member functions
0491   //
0492   void Event::throwProductNotFoundException(std::type_info const& iType,
0493                                             char const* iModule,
0494                                             char const* iProduct,
0495                                             char const* iProcess) {
0496     edm::TypeID type(iType);
0497     throw edm::Exception(edm::errors::ProductNotFound)
0498         << "A branch was found for \n  type ='" << type.className() << "'\n  module='" << iModule
0499         << "'\n  productInstance='" << ((nullptr != iProduct) ? iProduct : "") << "'\n  process='"
0500         << ((nullptr != iProcess) ? iProcess : "")
0501         << "'\n"
0502            "but no data is available for this Event";
0503   }
0504 
0505   fwlite::LuminosityBlock const& Event::getLuminosityBlock() const {
0506     if (not lumi_) {
0507       // Branch map pointer not really being shared, owned by event, have to trick Lumi
0508       lumi_ = std::make_shared<fwlite::LuminosityBlock>(std::shared_ptr<BranchMapReader>(&branchMap_, NoDelete()),
0509                                                         runFactory_);
0510     }
0511     edm::RunNumber_t run = eventAuxiliary().run();
0512     edm::LuminosityBlockNumber_t lumi = eventAuxiliary().luminosityBlock();
0513     lumi_->to(run, lumi);
0514     return *lumi_;
0515   }
0516 
0517   fwlite::Run const& Event::getRun() const {
0518     run_ = runFactory_->makeRun(std::shared_ptr<BranchMapReader>(&branchMap_, NoDelete()));
0519     edm::RunNumber_t run = eventAuxiliary().run();
0520     run_->to(run);
0521     return *run_;
0522   }
0523 
0524 }  // namespace fwlite