Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-03-17 11:16:18

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   ~PATObjectCrossLinker() override;
0050 
0051   static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0052 
0053 private:
0054   void beginStream(edm::StreamID) override;
0055   void produce(edm::Event&, const edm::EventSetup&) override;
0056   void endStream() override;
0057 
0058   template <class C1, class C2, class C3, class C4>
0059   void matchOneToMany(const C1& refProdOne,
0060                       C2& itemsOne,
0061                       const std::string& nameOne,
0062                       const C3& refProdMany,
0063                       C4& itemsMany,
0064                       const std::string& nameMany);
0065 
0066   template <class C1, class C2, class C3, class C4>
0067   void matchElectronToPhoton(const C1& refProdOne,
0068                              C2& itemsOne,
0069                              const std::string& nameOne,
0070                              const C3& refProdMany,
0071                              C4& itemsMany,
0072                              const std::string& nameMany);
0073 
0074   template <class C1, class C2, class C3, class C4>
0075   void matchLowPtToElectron(const C1& refProdOne,
0076                             C2& itemsOne,
0077                             const std::string& nameOne,
0078                             const C3& refProdMany,
0079                             C4& itemsMany,
0080                             const std::string& nameMany);
0081 
0082   template <class C1, class C2, class C3>
0083   void matchOneToVertices(C1& itemsOne, const C2& refProdVtx, C3& itemsVtx, const std::string& nameVtx);
0084 
0085   template <class C1, class C2, class C3>
0086   void matchVertexToMany(const C1& refProdVtx, C2& itemsVtx, const std::string& nameVtx, C3& itemsMany);
0087 
0088   //virtual void beginRun(edm::Run const&, edm::EventSetup const&) override;
0089   //virtual void endRun(edm::Run const&, edm::EventSetup const&) override;
0090   //virtual void beginLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override;
0091   //virtual void endLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override;
0092 
0093   // ----------member data ---------------------------
0094   const edm::EDGetTokenT<edm::View<pat::Jet>> jets_;
0095   const edm::EDGetTokenT<edm::View<pat::Muon>> muons_;
0096   const edm::EDGetTokenT<edm::View<pat::Electron>> electrons_;
0097   const edm::EDGetTokenT<edm::View<pat::Photon>> photons_;
0098   const edm::EDGetTokenT<edm::View<pat::Tau>> taus_;
0099   edm::InputTag lowPtElectronsTag_;
0100   edm::EDGetTokenT<edm::View<pat::Electron>> lowPtElectrons_;
0101   edm::InputTag boostedTausTag_;
0102   edm::EDGetTokenT<edm::View<pat::Tau>> boostedTaus_;
0103   edm::InputTag verticesTag_;
0104   edm::EDGetTokenT<edm::View<reco::VertexCompositePtrCandidate>> vertices_;
0105 };
0106 
0107 //
0108 // constructors and destructor
0109 //
0110 PATObjectCrossLinker::PATObjectCrossLinker(const edm::ParameterSet& params)
0111     : jets_(consumes<edm::View<pat::Jet>>(params.getParameter<edm::InputTag>("jets"))),
0112       muons_(consumes<edm::View<pat::Muon>>(params.getParameter<edm::InputTag>("muons"))),
0113       electrons_(consumes<edm::View<pat::Electron>>(params.getParameter<edm::InputTag>("electrons"))),
0114       photons_(consumes<edm::View<pat::Photon>>(params.getParameter<edm::InputTag>("photons"))),
0115       taus_(consumes<edm::View<pat::Tau>>(params.getParameter<edm::InputTag>("taus"))),
0116       lowPtElectronsTag_(params.getParameter<edm::InputTag>("lowPtElectrons")),
0117       boostedTausTag_(params.getParameter<edm::InputTag>("boostedTaus")),
0118       verticesTag_(params.getParameter<edm::InputTag>("vertices")) {
0119   produces<std::vector<pat::Jet>>("jets");
0120   produces<std::vector<pat::Muon>>("muons");
0121   produces<std::vector<pat::Electron>>("electrons");
0122   produces<std::vector<pat::Photon>>("photons");
0123   produces<std::vector<pat::Tau>>("taus");
0124   if (!lowPtElectronsTag_.label().empty()) {
0125     lowPtElectrons_ = consumes<edm::View<pat::Electron>>(lowPtElectronsTag_),
0126     produces<std::vector<pat::Electron>>("lowPtElectrons");
0127   }
0128   if (!boostedTausTag_.label().empty()) {
0129     boostedTaus_ = consumes<edm::View<pat::Tau>>(boostedTausTag_);
0130     produces<std::vector<pat::Tau>>("boostedTaus");
0131   }
0132   if (!verticesTag_.label().empty()) {
0133     vertices_ = consumes<edm::View<reco::VertexCompositePtrCandidate>>(verticesTag_);
0134     produces<std::vector<reco::VertexCompositePtrCandidate>>("vertices");
0135   }
0136 }
0137 
0138 PATObjectCrossLinker::~PATObjectCrossLinker() {
0139   // do anything here that needs to be done at destruction time
0140   // (e.g. close files, deallocate resources etc.)
0141 }
0142 
0143 //
0144 // member functions
0145 //
0146 
0147 // ------------ method called to produce the data  ------------
0148 
0149 ///
0150 template <class C1, class C2, class C3, class C4>
0151 void PATObjectCrossLinker::matchOneToMany(const C1& refProdOne,
0152                                           C2& itemsOne,
0153                                           const std::string& nameOne,
0154                                           const C3& refProdMany,
0155                                           C4& itemsMany,
0156                                           const std::string& nameMany) {
0157   size_t ji = 0;
0158   for (auto& j : itemsOne) {
0159     edm::PtrVector<reco::Candidate> overlaps(refProdMany.id());
0160     size_t mi = 0;
0161     for (auto& m : itemsMany) {
0162       if (matchByCommonSourceCandidatePtr(j, m) && (!m.hasUserCand(nameOne))) {
0163         m.addUserCand(nameOne, reco::CandidatePtr(refProdOne.id(), ji, refProdOne.productGetter()));
0164         overlaps.push_back(reco::CandidatePtr(refProdMany.id(), mi, refProdMany.productGetter()));
0165       }
0166       mi++;
0167     }
0168     j.setOverlaps(nameMany, overlaps);
0169     ji++;
0170   }
0171 }
0172 
0173 // one electron can be matched to several photons
0174 template <class C1, class C2, class C3, class C4>
0175 void PATObjectCrossLinker::matchElectronToPhoton(const C1& refProdOne,
0176                                                  C2& itemsOne,
0177                                                  const std::string& nameOne,
0178                                                  const C3& refProdMany,
0179                                                  C4& itemsMany,
0180                                                  const std::string& nameMany) {
0181   size_t ji = 0;
0182   for (auto& j : itemsOne) {
0183     edm::PtrVector<reco::Candidate> overlaps(refProdMany.id());
0184     size_t mi = 0;
0185     for (auto& m : itemsMany) {
0186       if (matchByCommonParentSuperClusterRef(j, m) && (!m.hasUserCand(nameOne))) {
0187         m.addUserCand(nameOne, reco::CandidatePtr(refProdOne.id(), ji, refProdOne.productGetter()));
0188         overlaps.push_back(reco::CandidatePtr(refProdMany.id(), mi, refProdMany.productGetter()));
0189       }
0190       mi++;
0191     }
0192     j.setOverlaps(nameMany, overlaps);
0193     ji++;
0194   }
0195 }
0196 
0197 // one low pt electron can be matched to several electrons
0198 template <class C1, class C2, class C3, class C4>
0199 void PATObjectCrossLinker::matchLowPtToElectron(const C1& refProdOne,
0200                                                 C2& itemsOne,
0201                                                 const std::string& nameOne,
0202                                                 const C3& refProdMany,
0203                                                 C4& itemsMany,
0204                                                 const std::string& nameMany) {
0205   size_t ji = 0;
0206   for (auto& j : itemsOne) {
0207     std::vector<std::pair<size_t, float>> idxs;
0208     size_t mi = 0;
0209     for (auto& m : itemsMany) {
0210       float dr2 = deltaR2(m, j);
0211       if (dr2 < 1.e-6) {  // deltaR < 1.e-3
0212         m.addUserCand(nameOne, reco::CandidatePtr(refProdOne.id(), ji, refProdOne.productGetter()));
0213         idxs.push_back(std::make_pair(mi, dr2));
0214       }
0215       mi++;
0216     }
0217     std::sort(idxs.begin(), idxs.end(), [](auto& left, auto& right) { return left.second < right.second; });
0218 
0219     edm::PtrVector<reco::Candidate> overlaps(refProdMany.id());
0220     for (auto idx : idxs) {
0221       overlaps.push_back(reco::CandidatePtr(refProdMany.id(), idx.first, refProdMany.productGetter()));
0222     }
0223     j.setOverlaps(nameMany, overlaps);
0224     ji++;
0225   }
0226 }
0227 
0228 // several vertices stored as overlap with a jet
0229 // (reco vertices have no userCands)
0230 template <class C1, class C2, class C3>
0231 void PATObjectCrossLinker::matchOneToVertices(C1& itemsOne,
0232                                               const C2& refProdVtx,
0233                                               C3& itemsVtx,
0234                                               const std::string& nameVtx) {
0235   for (auto& j : itemsOne) {
0236     edm::PtrVector<reco::Candidate> overlaps(refProdVtx.id());
0237     size_t vi = 0;
0238     for (auto& v : itemsVtx) {
0239       if (matchByCommonSourceCandidatePtr(j, v)) {
0240         overlaps.push_back(reco::CandidatePtr(refProdVtx.id(), vi, refProdVtx.productGetter()));
0241       }
0242       vi++;
0243     }
0244     j.setOverlaps(nameVtx, overlaps);
0245   }
0246 }
0247 
0248 // vertex stored as userCand to matched object
0249 // (reco vertices have no overlaps)
0250 template <class C1, class C2, class C3>
0251 void PATObjectCrossLinker::matchVertexToMany(const C1& refProdVtx,
0252                                              C2& itemsVtx,
0253                                              const std::string& nameVtx,
0254                                              C3& itemsMany) {
0255   size_t vi = 0;
0256   for (auto& v : itemsVtx) {
0257     for (auto& m : itemsMany) {
0258       if (matchByCommonSourceCandidatePtr(v, m) && (!m.hasUserCand(nameVtx))) {
0259         m.addUserCand(nameVtx, reco::CandidatePtr(refProdVtx.id(), vi, refProdVtx.productGetter()));
0260       }
0261     }
0262     vi++;
0263   }
0264 }
0265 
0266 void PATObjectCrossLinker::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0267   using namespace edm;
0268   const auto& jetsIn = iEvent.get(jets_);
0269   auto jets = std::make_unique<std::vector<pat::Jet>>();
0270   jets->reserve(jetsIn.size());
0271   for (const auto& j : jetsIn)
0272     jets->push_back(j);
0273   auto jetRefProd = iEvent.getRefBeforePut<std::vector<pat::Jet>>("jets");
0274 
0275   const auto& muonsIn = iEvent.get(muons_);
0276   auto muons = std::make_unique<std::vector<pat::Muon>>();
0277   muons->reserve(muonsIn.size());
0278   for (const auto& m : muonsIn)
0279     muons->push_back(m);
0280   auto muRefProd = iEvent.getRefBeforePut<std::vector<pat::Muon>>("muons");
0281 
0282   const auto& electronsIn = iEvent.get(electrons_);
0283   auto electrons = std::make_unique<std::vector<pat::Electron>>();
0284   electrons->reserve(electronsIn.size());
0285   for (const auto& e : electronsIn)
0286     electrons->push_back(e);
0287   auto eleRefProd = iEvent.getRefBeforePut<std::vector<pat::Electron>>("electrons");
0288 
0289   const auto& tausIn = iEvent.get(taus_);
0290   auto taus = std::make_unique<std::vector<pat::Tau>>();
0291   taus->reserve(tausIn.size());
0292   for (const auto& t : tausIn)
0293     taus->push_back(t);
0294   auto tauRefProd = iEvent.getRefBeforePut<std::vector<pat::Tau>>("taus");
0295 
0296   const auto& photonsIn = iEvent.get(photons_);
0297   auto photons = std::make_unique<std::vector<pat::Photon>>();
0298   photons->reserve(photonsIn.size());
0299   for (const auto& p : photonsIn)
0300     photons->push_back(p);
0301   auto phRefProd = iEvent.getRefBeforePut<std::vector<pat::Photon>>("photons");
0302 
0303   auto lowPtElectrons = std::make_unique<std::vector<pat::Electron>>();
0304   if (!lowPtElectronsTag_.label().empty()) {
0305     const auto& lowPtElectronsIn = iEvent.get(lowPtElectrons_);
0306     lowPtElectrons->reserve(lowPtElectronsIn.size());
0307     for (const auto& e : lowPtElectronsIn) {
0308       lowPtElectrons->push_back(e);
0309     }
0310   }
0311 
0312   auto boostedTaus = std::make_unique<std::vector<pat::Tau>>();
0313   if (!boostedTausTag_.label().empty()) {
0314     const auto& boostedTausIn = iEvent.get(boostedTaus_);
0315     boostedTaus->reserve(boostedTausIn.size());
0316     for (const auto& e : boostedTausIn) {
0317       boostedTaus->push_back(e);
0318     }
0319   }
0320 
0321   auto vertices = std::make_unique<std::vector<reco::VertexCompositePtrCandidate>>();
0322   if (!verticesTag_.label().empty()) {
0323     const auto& verticesIn = iEvent.get(vertices_);
0324     vertices->reserve(verticesIn.size());
0325     for (const auto& e : verticesIn) {
0326       vertices->push_back(e);
0327     }
0328   }
0329 
0330   matchOneToMany(jetRefProd, *jets, "jet", muRefProd, *muons, "muons");
0331   matchOneToMany(jetRefProd, *jets, "jet", eleRefProd, *electrons, "electrons");
0332   matchOneToMany(jetRefProd, *jets, "jet", tauRefProd, *taus, "taus");
0333   matchOneToMany(jetRefProd, *jets, "jet", phRefProd, *photons, "photons");
0334 
0335   matchOneToMany(tauRefProd, *taus, "tau", muRefProd, *muons, "muons");
0336   matchOneToMany(tauRefProd, *taus, "tau", eleRefProd, *electrons, "electrons");
0337 
0338   matchElectronToPhoton(eleRefProd, *electrons, "electron", phRefProd, *photons, "photons");
0339 
0340   if (!lowPtElectronsTag_.label().empty()) {
0341     auto lowPtEleRefProd = iEvent.getRefBeforePut<std::vector<pat::Electron>>("lowPtElectrons");
0342     matchLowPtToElectron(lowPtEleRefProd, *lowPtElectrons, "lowPtElectron", eleRefProd, *electrons, "electrons");
0343     matchElectronToPhoton(lowPtEleRefProd, *lowPtElectrons, "lowPtElectron", phRefProd, *photons, "photons");
0344   }
0345 
0346   if (!boostedTausTag_.label().empty()) {
0347     auto boostedTauRefProd = iEvent.getRefBeforePut<std::vector<pat::Tau>>("boostedTaus");
0348     matchOneToMany(jetRefProd, *jets, "jet", boostedTauRefProd, *boostedTaus, "boostedTaus");
0349   }
0350 
0351   if (!verticesTag_.label().empty()) {
0352     auto vtxRefProd = iEvent.getRefBeforePut<std::vector<reco::VertexCompositePtrCandidate>>("vertices");
0353     matchOneToVertices(*jets, vtxRefProd, *vertices, "vertices");
0354     matchOneToVertices(*taus, vtxRefProd, *vertices, "vertices");
0355     matchVertexToMany(vtxRefProd, *vertices, "vertex", *muons);
0356     matchVertexToMany(vtxRefProd, *vertices, "vertex", *electrons);
0357   }
0358 
0359   iEvent.put(std::move(jets), "jets");
0360   iEvent.put(std::move(muons), "muons");
0361   iEvent.put(std::move(electrons), "electrons");
0362   iEvent.put(std::move(taus), "taus");
0363   iEvent.put(std::move(photons), "photons");
0364   if (!lowPtElectronsTag_.label().empty())
0365     iEvent.put(std::move(lowPtElectrons), "lowPtElectrons");
0366   if (!boostedTausTag_.label().empty())
0367     iEvent.put(std::move(boostedTaus), "boostedTaus");
0368   if (!verticesTag_.label().empty())
0369     iEvent.put(std::move(vertices), "vertices");
0370 }
0371 
0372 // ------------ method called once each stream before processing any runs, lumis or events  ------------
0373 void PATObjectCrossLinker::beginStream(edm::StreamID) {}
0374 
0375 // ------------ method called once each stream after processing all runs, lumis and events  ------------
0376 void PATObjectCrossLinker::endStream() {}
0377 
0378 // ------------ method fills 'descriptions' with the allowed parameters for the module  ------------
0379 void PATObjectCrossLinker::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0380   edm::ParameterSetDescription desc;
0381   desc.add<edm::InputTag>("jets")->setComment("a jet collection derived from pat::Jet");
0382   desc.add<edm::InputTag>("muons")->setComment("a muon collection derived from pat::Muon");
0383   desc.add<edm::InputTag>("electrons")->setComment("an electron collection derived from pat::Electron");
0384   desc.add<edm::InputTag>("photons")->setComment("a photon collection derived from pat::Photon");
0385   desc.add<edm::InputTag>("taus")->setComment("a tau collection derived from pat::Tau");
0386   desc.add<edm::InputTag>("lowPtElectrons", edm::InputTag(""))
0387       ->setComment("an optional electron collection derived from pat::Electron, empty=>not used");
0388   desc.add<edm::InputTag>("boostedTaus", edm::InputTag(""))
0389       ->setComment("an optional boosted tau collection derived from pat::Tau, empty=>not used");
0390   desc.add<edm::InputTag>("vertices", edm::InputTag(""))
0391       ->setComment("an optional vertex collection derived from reco::VertexCompositePtrCandidate,empty=>not used");
0392   descriptions.add("patObjectCrossLinker", desc);
0393 }
0394 
0395 //define this as a plug-in
0396 DEFINE_FWK_MODULE(PATObjectCrossLinker);