Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:27:46

0001 #ifndef FWCore_Framework_GetterOfProducts_h
0002 #define FWCore_Framework_GetterOfProducts_h
0003 
0004 /** \class edm::GetterOfProducts
0005 
0006 Intended to be used by EDProducers, EDFilters, and
0007 EDAnalyzers to get products from the Event, Run, LuminosityBlock
0008 or ProcessBlock. In most cases, the preferred
0009 method to get products is not to use this class. In
0010 most cases the preferred method is to use the function
0011 getByToken with a token obtained from a consumes call
0012 which was passed a configurable InputTag. But
0013 occasionally getByToken will not work because one
0014 wants to select the product based on the data that is
0015 available and not have to modify the
0016 configuration as the data content changes. A real
0017 example would be a module that collects HLT trigger
0018 information from products written by the many HLT
0019 filters. The number and labels of those products vary
0020 so much that it would not be reasonable to modify
0021 the configuration to get all of them each time a
0022 different HLT trigger table was used. This class
0023 handles that and similar cases.
0024 
0025 This class is preferred over using getManyByType
0026 where it is possible to use it.
0027 
0028 This method can select by type and branch type.
0029 There exists a predicate (in ProcessMatch.h)
0030 to also select on process name.  It is possible
0031 to write other predicates which will select on
0032 anything in the BranchDescription. The selection
0033 is done during the initialization of the process.
0034 During this initialization a list of tokens
0035 is filled with all matching products from the
0036 ProductRegistry. This list of tokens is accessible
0037 to the module.
0038 
0039 The fillHandles functions will get a handle
0040 for each product on the list of tokens that
0041 is actually present in the current Event,
0042 LuminosityBlock, Run, or ProcessBlock. Internally,
0043 this function uses tokens and depends on the same
0044 things as getByToken and benefits from
0045 performance optimizations of getByToken.
0046 
0047 Typically one would use this as follows:
0048 
0049 Add these headers:
0050 
0051 #include "FWCore/Framework/interface/GetterOfProducts.h"
0052 #include "FWCore/Framework/interface/ProcessMatch.h"
0053 
0054 Add this data member:
0055 
0056     edm::GetterOfProducts<YourDataType> getterOfProducts_;
0057 
0058 
0059 Add these to the constructor (1st line is usually in the
0060 data member initializer list and the 2nd line in the body
0061 of the constructor)
0062 
0063     getterOfProducts_(edm::ProcessMatch(processName_), this) {
0064     callWhenNewProductsRegistered(getterOfProducts_);
0065 
0066 Add this to the method called for each event:
0067 
0068     std::vector<edm::Handle<YourDataType> > handles;
0069     getterOfProducts_.fillHandles(event, handles);
0070 
0071 And that is all you need in most cases. In the above example,
0072 "YourDataType" is the type of the product you want to get.
0073 There are some variants for special cases
0074 
0075   - Use an extra argument to the constructor for products
0076   in a Run, LuminosityBlock or ProcessBlock For example:
0077 
0078     getterOfProducts_ = edm::GetterOfProducts<Thing>(edm::ProcessMatch(processName_), this, edm::InRun);
0079 
0080   - You can use multiple GetterOfProducts's in the same module. The
0081   only tricky part is to use a lambda as follows to register the
0082   callbacks:
0083 
0084     callWhenNewProductsRegistered([this](edm::BranchDescription const& bd) {
0085       getterOfProducts1_(bd);
0086       getterOfProducts2_(bd);
0087     });
0088 
0089   - One can use "*" for the processName_ to select from all
0090   processes (this will just select based on type).
0091 
0092   - You can define your own predicate to replace ProcessMatch
0093   in the above example and select based on anything in the
0094   BranchDescription. See ProcessMatch.h for an example of how
0095   to write this predicate.
0096 
0097 \author W. David Dagenhart, created 6 August, 2012
0098 
0099 */
0100 
0101 #include "DataFormats/Common/interface/Handle.h"
0102 #include "DataFormats/Provenance/interface/BranchDescription.h"
0103 #include "FWCore/Framework/interface/Event.h"
0104 #include "FWCore/Framework/interface/LuminosityBlock.h"
0105 #include "FWCore/Framework/interface/ProcessBlock.h"
0106 #include "FWCore/Framework/interface/Run.h"
0107 #include "FWCore/Framework/interface/WillGetIfMatch.h"
0108 #include "FWCore/Utilities/interface/BranchType.h"
0109 #include "FWCore/Utilities/interface/EDGetToken.h"
0110 #include "FWCore/Utilities/interface/TypeID.h"
0111 
0112 #include <functional>
0113 #include <memory>
0114 #include <string>
0115 #include <vector>
0116 
0117 namespace edm {
0118 
0119   template <typename T>
0120   class GetterOfProducts {
0121   public:
0122     GetterOfProducts() : branchType_(edm::InEvent) {}
0123 
0124     template <typename U, typename M>
0125     GetterOfProducts(U const& match, M* module, edm::BranchType branchType = edm::InEvent)
0126         : matcher_(WillGetIfMatch<T>(match, module)),
0127           tokens_(new std::vector<edm::EDGetTokenT<T>>),
0128           branchType_(branchType) {}
0129 
0130     void operator()(edm::BranchDescription const& branchDescription) {
0131       if (branchDescription.dropped())
0132         return;
0133       if (branchDescription.branchType() == branchType_ &&
0134           branchDescription.unwrappedTypeID() == edm::TypeID(typeid(T))) {
0135         auto const& token = matcher_(branchDescription);
0136         if (not token.isUninitialized()) {
0137           tokens_->push_back(token);
0138         }
0139       }
0140     }
0141 
0142     void fillHandles(edm::Event const& event, std::vector<edm::Handle<T>>& handles) const {
0143       handles.clear();
0144       if (branchType_ == edm::InEvent) {
0145         handles.reserve(tokens_->size());
0146         for (auto const& token : *tokens_) {
0147           if (auto handle = event.getHandle(token)) {
0148             handles.push_back(handle);
0149           }
0150         }
0151       }
0152     }
0153 
0154     void fillHandles(edm::LuminosityBlock const& lumi, std::vector<edm::Handle<T>>& handles) const {
0155       handles.clear();
0156       if (branchType_ == edm::InLumi) {
0157         handles.reserve(tokens_->size());
0158         for (auto const& token : *tokens_) {
0159           if (auto handle = lumi.getHandle(token)) {
0160             handles.push_back(handle);
0161           }
0162         }
0163       }
0164     }
0165 
0166     void fillHandles(edm::Run const& run, std::vector<edm::Handle<T>>& handles) const {
0167       handles.clear();
0168       if (branchType_ == edm::InRun) {
0169         handles.reserve(tokens_->size());
0170         for (auto const& token : *tokens_) {
0171           if (auto handle = run.getHandle(token)) {
0172             handles.push_back(handle);
0173           }
0174         }
0175       }
0176     }
0177 
0178     void fillHandles(edm::ProcessBlock const& processBlock, std::vector<edm::Handle<T>>& handles) const {
0179       handles.clear();
0180       if (branchType_ == edm::InProcess) {
0181         handles.reserve(tokens_->size());
0182         for (auto const& token : *tokens_) {
0183           if (auto handle = processBlock.getHandle(token)) {
0184             handles.push_back(handle);
0185           }
0186         }
0187       }
0188     }
0189 
0190     std::vector<edm::EDGetTokenT<T>> const& tokens() const { return *tokens_; }
0191     edm::BranchType branchType() const { return branchType_; }
0192 
0193   private:
0194     std::function<EDGetTokenT<T>(BranchDescription const&)> matcher_;
0195     // A shared pointer is needed because objects of this type get assigned
0196     // to std::function's and we want the copies in those to share the same vector.
0197     std::shared_ptr<std::vector<edm::EDGetTokenT<T>>> tokens_;
0198     edm::BranchType branchType_;
0199   };
0200 }  // namespace edm
0201 #endif