Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:23:51

0001 // -*- C++ -*-
0002 //
0003 // Package:    PhysicsTools/NanoAOD
0004 // Class:      PATObjectCrossLinker
0005 //
0006 /**\class PATObjectCrossLinker PATObjectCrossLinker.cc PhysicsTools/PATObjectCrossLinker/plugins/PATObjectCrossLinker.cc
0007 
0008  Description: [one line class summary]
0009 
0010  Implementation:
0011      [Notes on implementation]
0012 */
0013 //
0014 // Original Author:  Andrea Rizzi
0015 //         Created:  Mon, 28 Aug 2017 09:26:39 GMT
0016 //
0017 //
0018 
0019 // system include files
0020 #include <memory>
0021 
0022 // user include files
0023 #include "FWCore/Framework/interface/Frameworkfwd.h"
0024 #include "FWCore/Framework/interface/stream/EDProducer.h"
0025 
0026 #include "FWCore/Framework/interface/Event.h"
0027 #include "FWCore/Framework/interface/MakerMacros.h"
0028 
0029 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0030 #include "FWCore/Utilities/interface/StreamID.h"
0031 
0032 #include "DataFormats/PatCandidates/interface/Muon.h"
0033 #include "DataFormats/PatCandidates/interface/Jet.h"
0034 #include "DataFormats/PatCandidates/interface/Electron.h"
0035 #include "DataFormats/PatCandidates/interface/Photon.h"
0036 #include "DataFormats/PatCandidates/interface/Tau.h"
0037 #include "DataFormats/Candidate/interface/VertexCompositePtrCandidate.h"
0038 
0039 #include "DataFormats/Common/interface/View.h"
0040 
0041 #include "PhysicsTools/NanoAOD/interface/MatchingUtils.h"
0042 //
0043 // class declaration
0044 //
0045 
0046 class PATObjectCrossLinker : public edm::stream::EDProducer<> {
0047 public:
0048   explicit PATObjectCrossLinker(const edm::ParameterSet&);
0049 
0050   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0051 
0052 private:
0053   void produce(edm::Event&, const edm::EventSetup&) override;
0054 
0055   template <class C1, class C2, class C3, class C4>
0056   void matchOneToMany(const C1& refProdOne,
0057                       C2& itemsOne,
0058                       const std::string& nameOne,
0059                       const C3& refProdMany,
0060                       C4& itemsMany,
0061                       const std::string& nameMany);
0062 
0063   template <class C1, class C2, class C3, class C4>
0064   void matchElectronToPhoton(const C1& refProdOne,
0065                              C2& itemsOne,
0066                              const std::string& nameOne,
0067                              const C3& refProdMany,
0068                              C4& itemsMany,
0069                              const std::string& nameMany);
0070 
0071   template <class C1, class C2, class C3, class C4>
0072   void matchLowPtToElectron(const C1& refProdOne,
0073                             C2& itemsOne,
0074                             const std::string& nameOne,
0075                             const C3& refProdMany,
0076                             C4& itemsMany,
0077                             const std::string& nameMany);
0078 
0079   template <class C1, class C2, class C3>
0080   void matchOneToVertices(C1& itemsOne, const C2& refProdVtx, C3& itemsVtx, const std::string& nameVtx);
0081 
0082   template <class C1, class C2, class C3>
0083   void matchVertexToMany(const C1& refProdVtx, C2& itemsVtx, const std::string& nameVtx, C3& itemsMany);
0084 
0085   // ----------member data ---------------------------
0086   const edm::EDGetTokenT<edm::View<pat::Jet>> jets_;
0087   const edm::EDGetTokenT<edm::View<pat::Muon>> muons_;
0088   const edm::EDGetTokenT<edm::View<pat::Electron>> electrons_;
0089   const edm::EDGetTokenT<edm::View<pat::Photon>> photons_;
0090   const edm::EDGetTokenT<edm::View<pat::Tau>> taus_;
0091   edm::InputTag lowPtElectronsTag_;
0092   edm::EDGetTokenT<edm::View<pat::Electron>> lowPtElectrons_;
0093   edm::InputTag boostedTausTag_;
0094   edm::EDGetTokenT<edm::View<pat::Tau>> boostedTaus_;
0095   edm::InputTag verticesTag_;
0096   edm::EDGetTokenT<edm::View<reco::VertexCompositePtrCandidate>> vertices_;
0097 };
0098 
0099 //
0100 // constructors and destructor
0101 //
0102 PATObjectCrossLinker::PATObjectCrossLinker(const edm::ParameterSet& params)
0103     : jets_(consumes<edm::View<pat::Jet>>(params.getParameter<edm::InputTag>("jets"))),
0104       muons_(consumes<edm::View<pat::Muon>>(params.getParameter<edm::InputTag>("muons"))),
0105       electrons_(consumes<edm::View<pat::Electron>>(params.getParameter<edm::InputTag>("electrons"))),
0106       photons_(consumes<edm::View<pat::Photon>>(params.getParameter<edm::InputTag>("photons"))),
0107       taus_(consumes<edm::View<pat::Tau>>(params.getParameter<edm::InputTag>("taus"))),
0108       lowPtElectronsTag_(params.getParameter<edm::InputTag>("lowPtElectrons")),
0109       boostedTausTag_(params.getParameter<edm::InputTag>("boostedTaus")),
0110       verticesTag_(params.getParameter<edm::InputTag>("vertices")) {
0111   produces<std::vector<pat::Jet>>("jets");
0112   produces<std::vector<pat::Muon>>("muons");
0113   produces<std::vector<pat::Electron>>("electrons");
0114   produces<std::vector<pat::Photon>>("photons");
0115   produces<std::vector<pat::Tau>>("taus");
0116   if (!lowPtElectronsTag_.label().empty()) {
0117     lowPtElectrons_ = consumes<edm::View<pat::Electron>>(lowPtElectronsTag_),
0118     produces<std::vector<pat::Electron>>("lowPtElectrons");
0119   }
0120   if (!boostedTausTag_.label().empty()) {
0121     boostedTaus_ = consumes<edm::View<pat::Tau>>(boostedTausTag_);
0122     produces<std::vector<pat::Tau>>("boostedTaus");
0123   }
0124   if (!verticesTag_.label().empty()) {
0125     vertices_ = consumes<edm::View<reco::VertexCompositePtrCandidate>>(verticesTag_);
0126     produces<std::vector<reco::VertexCompositePtrCandidate>>("vertices");
0127   }
0128 }
0129 
0130 //
0131 // member functions
0132 //
0133 
0134 // ------------ method called to produce the data  ------------
0135 
0136 ///
0137 template <class C1, class C2, class C3, class C4>
0138 void PATObjectCrossLinker::matchOneToMany(const C1& refProdOne,
0139                                           C2& itemsOne,
0140                                           const std::string& nameOne,
0141                                           const C3& refProdMany,
0142                                           C4& itemsMany,
0143                                           const std::string& nameMany) {
0144   size_t ji = 0;
0145   for (auto& j : itemsOne) {
0146     edm::PtrVector<reco::Candidate> overlaps(refProdMany.id());
0147     size_t mi = 0;
0148     for (auto& m : itemsMany) {
0149       if (matchByCommonSourceCandidatePtr(j, m) && (!m.hasUserCand(nameOne))) {
0150         m.addUserCand(nameOne, reco::CandidatePtr(refProdOne.id(), ji, refProdOne.productGetter()));
0151         overlaps.push_back(reco::CandidatePtr(refProdMany.id(), mi, refProdMany.productGetter()));
0152       }
0153       mi++;
0154     }
0155     j.setOverlaps(nameMany, overlaps);
0156     ji++;
0157   }
0158 }
0159 
0160 // one electron can be matched to several photons
0161 template <class C1, class C2, class C3, class C4>
0162 void PATObjectCrossLinker::matchElectronToPhoton(const C1& refProdOne,
0163                                                  C2& itemsOne,
0164                                                  const std::string& nameOne,
0165                                                  const C3& refProdMany,
0166                                                  C4& itemsMany,
0167                                                  const std::string& nameMany) {
0168   size_t ji = 0;
0169   for (auto& j : itemsOne) {
0170     edm::PtrVector<reco::Candidate> overlaps(refProdMany.id());
0171     size_t mi = 0;
0172     for (auto& m : itemsMany) {
0173       if (matchByCommonParentSuperClusterRef(j, m) && (!m.hasUserCand(nameOne))) {
0174         m.addUserCand(nameOne, reco::CandidatePtr(refProdOne.id(), ji, refProdOne.productGetter()));
0175         overlaps.push_back(reco::CandidatePtr(refProdMany.id(), mi, refProdMany.productGetter()));
0176       }
0177       mi++;
0178     }
0179     j.setOverlaps(nameMany, overlaps);
0180     ji++;
0181   }
0182 }
0183 
0184 // one low pt electron can be matched to several electrons
0185 template <class C1, class C2, class C3, class C4>
0186 void PATObjectCrossLinker::matchLowPtToElectron(const C1& refProdOne,
0187                                                 C2& itemsOne,
0188                                                 const std::string& nameOne,
0189                                                 const C3& refProdMany,
0190                                                 C4& itemsMany,
0191                                                 const std::string& nameMany) {
0192   size_t ji = 0;
0193   for (auto& j : itemsOne) {
0194     std::vector<std::pair<size_t, float>> idxs;
0195     size_t mi = 0;
0196     for (auto& m : itemsMany) {
0197       float dr2 = deltaR2(m, j);
0198       if (dr2 < 1.e-6) {  // deltaR < 1.e-3
0199         m.addUserCand(nameOne, reco::CandidatePtr(refProdOne.id(), ji, refProdOne.productGetter()));
0200         idxs.push_back(std::make_pair(mi, dr2));
0201       }
0202       mi++;
0203     }
0204     std::sort(idxs.begin(), idxs.end(), [](auto& left, auto& right) { return left.second < right.second; });
0205 
0206     edm::PtrVector<reco::Candidate> overlaps(refProdMany.id());
0207     for (auto idx : idxs) {
0208       overlaps.push_back(reco::CandidatePtr(refProdMany.id(), idx.first, refProdMany.productGetter()));
0209     }
0210     j.setOverlaps(nameMany, overlaps);
0211     ji++;
0212   }
0213 }
0214 
0215 // several vertices stored as overlap with a jet
0216 // (reco vertices have no userCands)
0217 template <class C1, class C2, class C3>
0218 void PATObjectCrossLinker::matchOneToVertices(C1& itemsOne,
0219                                               const C2& refProdVtx,
0220                                               C3& itemsVtx,
0221                                               const std::string& nameVtx) {
0222   for (auto& j : itemsOne) {
0223     edm::PtrVector<reco::Candidate> overlaps(refProdVtx.id());
0224     size_t vi = 0;
0225     for (auto& v : itemsVtx) {
0226       if (matchByCommonSourceCandidatePtr(j, v)) {
0227         overlaps.push_back(reco::CandidatePtr(refProdVtx.id(), vi, refProdVtx.productGetter()));
0228       }
0229       vi++;
0230     }
0231     j.setOverlaps(nameVtx, overlaps);
0232   }
0233 }
0234 
0235 // vertex stored as userCand to matched object
0236 // (reco vertices have no overlaps)
0237 template <class C1, class C2, class C3>
0238 void PATObjectCrossLinker::matchVertexToMany(const C1& refProdVtx,
0239                                              C2& itemsVtx,
0240                                              const std::string& nameVtx,
0241                                              C3& itemsMany) {
0242   size_t vi = 0;
0243   for (auto& v : itemsVtx) {
0244     for (auto& m : itemsMany) {
0245       if (matchByCommonSourceCandidatePtr(v, m) && (!m.hasUserCand(nameVtx))) {
0246         m.addUserCand(nameVtx, reco::CandidatePtr(refProdVtx.id(), vi, refProdVtx.productGetter()));
0247       }
0248     }
0249     vi++;
0250   }
0251 }
0252 
0253 void PATObjectCrossLinker::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0254   using namespace edm;
0255   const auto& jetsIn = iEvent.get(jets_);
0256   auto jets = std::make_unique<std::vector<pat::Jet>>();
0257   jets->reserve(jetsIn.size());
0258   for (const auto& j : jetsIn)
0259     jets->push_back(j);
0260   auto jetRefProd = iEvent.getRefBeforePut<std::vector<pat::Jet>>("jets");
0261 
0262   const auto& muonsIn = iEvent.get(muons_);
0263   auto muons = std::make_unique<std::vector<pat::Muon>>();
0264   muons->reserve(muonsIn.size());
0265   for (const auto& m : muonsIn)
0266     muons->push_back(m);
0267   auto muRefProd = iEvent.getRefBeforePut<std::vector<pat::Muon>>("muons");
0268 
0269   const auto& electronsIn = iEvent.get(electrons_);
0270   auto electrons = std::make_unique<std::vector<pat::Electron>>();
0271   electrons->reserve(electronsIn.size());
0272   for (const auto& e : electronsIn)
0273     electrons->push_back(e);
0274   auto eleRefProd = iEvent.getRefBeforePut<std::vector<pat::Electron>>("electrons");
0275 
0276   const auto& tausIn = iEvent.get(taus_);
0277   auto taus = std::make_unique<std::vector<pat::Tau>>();
0278   taus->reserve(tausIn.size());
0279   for (const auto& t : tausIn)
0280     taus->push_back(t);
0281   auto tauRefProd = iEvent.getRefBeforePut<std::vector<pat::Tau>>("taus");
0282 
0283   const auto& photonsIn = iEvent.get(photons_);
0284   auto photons = std::make_unique<std::vector<pat::Photon>>();
0285   photons->reserve(photonsIn.size());
0286   for (const auto& p : photonsIn)
0287     photons->push_back(p);
0288   auto phRefProd = iEvent.getRefBeforePut<std::vector<pat::Photon>>("photons");
0289 
0290   auto lowPtElectrons = std::make_unique<std::vector<pat::Electron>>();
0291   if (!lowPtElectronsTag_.label().empty()) {
0292     const auto& lowPtElectronsIn = iEvent.get(lowPtElectrons_);
0293     lowPtElectrons->reserve(lowPtElectronsIn.size());
0294     for (const auto& e : lowPtElectronsIn) {
0295       lowPtElectrons->push_back(e);
0296     }
0297   }
0298 
0299   auto boostedTaus = std::make_unique<std::vector<pat::Tau>>();
0300   if (!boostedTausTag_.label().empty()) {
0301     const auto& boostedTausIn = iEvent.get(boostedTaus_);
0302     boostedTaus->reserve(boostedTausIn.size());
0303     for (const auto& e : boostedTausIn) {
0304       boostedTaus->push_back(e);
0305     }
0306   }
0307 
0308   auto vertices = std::make_unique<std::vector<reco::VertexCompositePtrCandidate>>();
0309   if (!verticesTag_.label().empty()) {
0310     const auto& verticesIn = iEvent.get(vertices_);
0311     vertices->reserve(verticesIn.size());
0312     for (const auto& e : verticesIn) {
0313       vertices->push_back(e);
0314     }
0315   }
0316 
0317   matchOneToMany(jetRefProd, *jets, "jet", muRefProd, *muons, "muons");
0318   matchOneToMany(jetRefProd, *jets, "jet", eleRefProd, *electrons, "electrons");
0319   matchOneToMany(jetRefProd, *jets, "jet", tauRefProd, *taus, "taus");
0320   matchOneToMany(jetRefProd, *jets, "jet", phRefProd, *photons, "photons");
0321 
0322   matchOneToMany(tauRefProd, *taus, "tau", muRefProd, *muons, "muons");
0323   matchOneToMany(tauRefProd, *taus, "tau", eleRefProd, *electrons, "electrons");
0324 
0325   matchElectronToPhoton(eleRefProd, *electrons, "electron", phRefProd, *photons, "photons");
0326 
0327   if (!lowPtElectronsTag_.label().empty()) {
0328     auto lowPtEleRefProd = iEvent.getRefBeforePut<std::vector<pat::Electron>>("lowPtElectrons");
0329     matchLowPtToElectron(lowPtEleRefProd, *lowPtElectrons, "lowPtElectron", eleRefProd, *electrons, "electrons");
0330     matchElectronToPhoton(lowPtEleRefProd, *lowPtElectrons, "lowPtElectron", phRefProd, *photons, "photons");
0331   }
0332 
0333   if (!boostedTausTag_.label().empty()) {
0334     auto boostedTauRefProd = iEvent.getRefBeforePut<std::vector<pat::Tau>>("boostedTaus");
0335     matchOneToMany(jetRefProd, *jets, "jet", boostedTauRefProd, *boostedTaus, "boostedTaus");
0336   }
0337 
0338   if (!verticesTag_.label().empty()) {
0339     auto vtxRefProd = iEvent.getRefBeforePut<std::vector<reco::VertexCompositePtrCandidate>>("vertices");
0340     matchOneToVertices(*jets, vtxRefProd, *vertices, "vertices");
0341     matchOneToVertices(*taus, vtxRefProd, *vertices, "vertices");
0342     matchVertexToMany(vtxRefProd, *vertices, "vertex", *muons);
0343     matchVertexToMany(vtxRefProd, *vertices, "vertex", *electrons);
0344   }
0345 
0346   iEvent.put(std::move(jets), "jets");
0347   iEvent.put(std::move(muons), "muons");
0348   iEvent.put(std::move(electrons), "electrons");
0349   iEvent.put(std::move(taus), "taus");
0350   iEvent.put(std::move(photons), "photons");
0351   if (!lowPtElectronsTag_.label().empty())
0352     iEvent.put(std::move(lowPtElectrons), "lowPtElectrons");
0353   if (!boostedTausTag_.label().empty())
0354     iEvent.put(std::move(boostedTaus), "boostedTaus");
0355   if (!verticesTag_.label().empty())
0356     iEvent.put(std::move(vertices), "vertices");
0357 }
0358 
0359 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0360 void PATObjectCrossLinker::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0361   edm::ParameterSetDescription desc;
0362   desc.add<edm::InputTag>("jets")->setComment("a jet collection derived from pat::Jet");
0363   desc.add<edm::InputTag>("muons")->setComment("a muon collection derived from pat::Muon");
0364   desc.add<edm::InputTag>("electrons")->setComment("an electron collection derived from pat::Electron");
0365   desc.add<edm::InputTag>("photons")->setComment("a photon collection derived from pat::Photon");
0366   desc.add<edm::InputTag>("taus")->setComment("a tau collection derived from pat::Tau");
0367   desc.add<edm::InputTag>("lowPtElectrons", edm::InputTag(""))
0368       ->setComment("an optional electron collection derived from pat::Electron, empty=>not used");
0369   desc.add<edm::InputTag>("boostedTaus", edm::InputTag(""))
0370       ->setComment("an optional boosted tau collection derived from pat::Tau, empty=>not used");
0371   desc.add<edm::InputTag>("vertices", edm::InputTag(""))
0372       ->setComment("an optional vertex collection derived from reco::VertexCompositePtrCandidate,empty=>not used");
0373   descriptions.add("patObjectCrossLinker", desc);
0374 }
0375 
0376 //define this as a plug-in
0377 DEFINE_FWK_MODULE(PATObjectCrossLinker);