File indexing completed on 2023-03-17 11:16:18
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <memory>
0021
0022
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
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
0089
0090
0091
0092
0093
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
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
0140
0141 }
0142
0143
0144
0145
0146
0147
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
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
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) {
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
0229
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
0249
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
0373 void PATObjectCrossLinker::beginStream(edm::StreamID) {}
0374
0375
0376 void PATObjectCrossLinker::endStream() {}
0377
0378
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
0396 DEFINE_FWK_MODULE(PATObjectCrossLinker);