Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:12:03

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