Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:50:13

0001 #ifndef UtilAlgos_UniqueMerger_h
0002 #define UtilAlgos_UniqueMerger_h
0003 /** \class UniqueMerger
0004  *
0005  * Merges an arbitrary number of collections
0006  * into a single collection, without duplicates. Based on logic from Merger.h.
0007  * This class template differs from Merger.h in that it uses a set instead of std::vector.
0008  * This requires the OutputCollection type to be sortable, 
0009  * which allows us to search for elements downstream efficiently.
0010  *
0011  * Template parameters:
0012  * - C : collection type
0013  * - P : policy class that specifies how objects
0014  *       in the collection are are cloned
0015  *
0016  * \author Lauren Hay
0017  *
0018  * \version $Revision: 1.2 $
0019  *
0020  * 
0021  */
0022 
0023 #include "FWCore/Framework/interface/global/EDProducer.h"
0024 #include "FWCore/Framework/interface/Event.h"
0025 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0026 #include "FWCore/Utilities/interface/transform.h"
0027 #include "FWCore/Utilities/interface/InputTag.h"
0028 #include "DataFormats/Common/interface/CloneTrait.h"
0029 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0030 #include <vector>
0031 
0032 template <typename InputCollection,
0033           typename OutputCollection = InputCollection,
0034           typename P = typename edm::clonehelper::CloneTrait<InputCollection>::type>
0035 class UniqueMerger : public edm::global::EDProducer<> {
0036 public:
0037   typedef std::set<typename OutputCollection::value_type> set_type;
0038   /// constructor from parameter set
0039   explicit UniqueMerger(const edm::ParameterSet&);
0040   /// destructor
0041   ~UniqueMerger() override;
0042 
0043 private:
0044   /// process an event
0045   void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
0046   /// vector of strings
0047   typedef std::vector<edm::EDGetTokenT<InputCollection> > vtoken;
0048   /// labels of the collections to be merged
0049   vtoken srcToken_;
0050   /// choose whether to skip null/invalid pointers
0051   bool skipNulls_;
0052   /// choose whether to warn when skipping pointers
0053   bool warnOnSkip_;
0054 };
0055 
0056 template <typename InputCollection, typename OutputCollection, typename P>
0057 UniqueMerger<InputCollection, OutputCollection, P>::UniqueMerger(const edm::ParameterSet& par)
0058     : srcToken_(edm::vector_transform(par.template getParameter<std::vector<edm::InputTag> >("src"),
0059                                       [this](edm::InputTag const& tag) { return consumes<InputCollection>(tag); })),
0060       skipNulls_(par.getParameter<bool>("skipNulls")),
0061       warnOnSkip_(par.getParameter<bool>("warnOnSkip")) {
0062   produces<OutputCollection>();
0063 }
0064 
0065 template <typename InputCollection, typename OutputCollection, typename P>
0066 UniqueMerger<InputCollection, OutputCollection, P>::~UniqueMerger() {}
0067 
0068 template <typename InputCollection, typename OutputCollection, typename P>
0069 void UniqueMerger<InputCollection, OutputCollection, P>::produce(edm::StreamID,
0070                                                                  edm::Event& evt,
0071                                                                  const edm::EventSetup&) const {
0072   set_type coll_set;
0073   for (auto const& s : srcToken_) {
0074     for (auto const& c : evt.get(s)) {
0075       if (!skipNulls_ || (c.isNonnull() && c.isAvailable())) {
0076         coll_set.emplace(P::clone(c));
0077       } else if (warnOnSkip_) {
0078         edm::LogWarning("InvalidPointer") << "Found an invalid pointer. Will not merge to collection.";
0079       }
0080     }
0081   }
0082   std::unique_ptr<OutputCollection> coll(new OutputCollection(coll_set.size()));
0083   std::copy(coll_set.begin(), coll_set.end(), coll->begin());
0084   evt.put(std::move(coll));
0085 }
0086 
0087 #endif