File indexing completed on 2024-04-06 12:26:43
0001 #include <memory>
0002
0003 #include "FWCore/Framework/interface/Event.h"
0004 #include "FWCore/Framework/interface/global/EDFilter.h"
0005 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0006 #include "FWCore/Utilities/interface/InputTag.h"
0007
0008 #include "DataFormats/Math/interface/deltaR.h"
0009 #include "DataFormats/Common/interface/View.h"
0010 #include "DataFormats/Common/interface/PtrVector.h"
0011
0012 #include "DataFormats/MuonReco/interface/Muon.h"
0013 #include "DataFormats/MuonReco/interface/MuonSelectors.h"
0014 #include "DataFormats/VertexReco/interface/Vertex.h"
0015
0016 class BadGlobalMuonTagger : public edm::global::EDFilter<> {
0017 public:
0018 explicit BadGlobalMuonTagger(const edm::ParameterSet &iConfig);
0019 ~BadGlobalMuonTagger() override {}
0020
0021 bool filter(edm::StreamID iID, edm::Event &iEvent, const edm::EventSetup &iSetup) const override;
0022
0023 private:
0024 edm::EDGetTokenT<edm::View<reco::Muon>> muons_;
0025 edm::EDGetTokenT<std::vector<reco::Vertex>> vtx_;
0026 double ptCut_;
0027 bool selectClones_, taggingMode_, verbose_;
0028
0029 bool outInOnly(const reco::Muon &mu) const {
0030 const reco::Track &tk = *mu.innerTrack();
0031 return tk.algoMask().count() == 1 && tk.isAlgoInMask(reco::Track::muonSeededStepOutIn);
0032 }
0033 bool preselection(const reco::Muon &mu) const { return (!selectClones_ || outInOnly(mu)); }
0034 bool tighterId(const reco::Muon &mu) const { return muon::isMediumMuon(mu) && mu.numberOfMatchedStations() >= 2; }
0035 bool tightGlobal(const reco::Muon &mu) const {
0036 return mu.isGlobalMuon() && (mu.globalTrack()->hitPattern().muonStationsWithValidHits() >= 3 &&
0037 mu.globalTrack()->normalizedChi2() <= 20);
0038 }
0039 bool safeId(const reco::Muon &mu) const {
0040 if (mu.muonBestTrack()->ptError() > 0.2 * mu.muonBestTrack()->pt()) {
0041 return false;
0042 }
0043 return mu.numberOfMatchedStations() >= 1 || tightGlobal(mu);
0044 }
0045 bool partnerId(const reco::Muon &mu) const { return mu.pt() >= 10 && mu.numberOfMatchedStations() >= 1; }
0046 };
0047
0048 BadGlobalMuonTagger::BadGlobalMuonTagger(const edm::ParameterSet &iConfig)
0049 : muons_(consumes<edm::View<reco::Muon>>(iConfig.getParameter<edm::InputTag>("muons"))),
0050 vtx_(consumes<std::vector<reco::Vertex>>(iConfig.getParameter<edm::InputTag>("vtx"))),
0051 ptCut_(iConfig.getParameter<double>("muonPtCut")),
0052 selectClones_(iConfig.getParameter<bool>("selectClones")),
0053 taggingMode_(iConfig.getParameter<bool>("taggingMode")),
0054 verbose_(iConfig.getUntrackedParameter<bool>("verbose", false)) {
0055 produces<edm::PtrVector<reco::Muon>>("bad");
0056 produces<bool>("notBadEvent");
0057 }
0058
0059 bool BadGlobalMuonTagger::filter(edm::StreamID iID, edm::Event &iEvent, const edm::EventSetup &iSetup) const {
0060 using namespace edm;
0061
0062
0063 Handle<edm::View<reco::Muon>> hmuons;
0064 Handle<std::vector<reco::Vertex>> vtx;
0065 std::vector<int> goodMuon;
0066
0067 iEvent.getByToken(vtx_, vtx);
0068 assert(!vtx->empty());
0069 const auto &PV = vtx->front().position();
0070
0071 std::unique_ptr<edm::PtrVector<reco::Muon>> out(new edm::PtrVector<reco::Muon>());
0072 iEvent.getByToken(muons_, hmuons);
0073 const edm::View<reco::Muon> &muons = *hmuons;
0074 for (const reco::Muon &mu : muons) {
0075 if (!mu.isPFMuon() || mu.innerTrack().isNull()) {
0076 goodMuon.push_back(-1);
0077 continue;
0078 }
0079 if (preselection(mu)) {
0080 float dxypv = std::abs(mu.innerTrack()->dxy(PV));
0081 float dzpv = std::abs(mu.innerTrack()->dz(PV));
0082 if (tighterId(mu)) {
0083 bool ipLoose = ((dxypv < 0.5 && dzpv < 2.0) || mu.innerTrack()->hitPattern().pixelLayersWithMeasurement() >= 2);
0084 goodMuon.push_back(ipLoose || (!selectClones_ && tightGlobal(mu)));
0085 } else if (safeId(mu)) {
0086 bool ipTight = (dxypv < 0.2 && dzpv < 0.5);
0087 goodMuon.push_back(ipTight);
0088 } else {
0089 goodMuon.push_back(0);
0090 }
0091 } else {
0092 goodMuon.push_back(3);
0093 }
0094 }
0095
0096 bool found = false;
0097 for (unsigned int i = 0, n = muons.size(); i < n; ++i) {
0098 if (muons[i].pt() < ptCut_ || goodMuon[i] != 0)
0099 continue;
0100 if (verbose_)
0101 printf("potentially bad muon %d of pt %.1f eta %+.3f phi %+.3f\n",
0102 int(i + 1),
0103 muons[i].pt(),
0104 muons[i].eta(),
0105 muons[i].phi());
0106 bool bad = true;
0107 if (selectClones_) {
0108 bad = false;
0109 unsigned int n1 = muons[i].numberOfMatches(reco::Muon::SegmentArbitration);
0110 for (unsigned int j = 0; j < n; ++j) {
0111 if (j == i || goodMuon[j] <= 0 || !partnerId(muons[j]))
0112 continue;
0113 unsigned int n2 = muons[j].numberOfMatches(reco::Muon::SegmentArbitration);
0114 if (deltaR2(muons[i], muons[j]) < 0.16 ||
0115 (n1 > 0 && n2 > 0 && muon::sharedSegments(muons[i], muons[j]) >= 0.5 * std::min(n1, n2))) {
0116 if (verbose_)
0117 printf(" tagged as clone of muon %d of pt %.1f eta %+.3f phi %+.3f\n",
0118 int(j + 1),
0119 muons[j].pt(),
0120 muons[j].eta(),
0121 muons[j].phi());
0122 bad = true;
0123 break;
0124 }
0125 }
0126 }
0127 if (bad) {
0128 found = true;
0129 out->push_back(muons.ptrAt(i));
0130 }
0131 }
0132
0133 iEvent.put(std::move(out), "bad");
0134 iEvent.put(std::make_unique<bool>(!found), "notBadEvent");
0135 return taggingMode_ || found;
0136 }
0137
0138 #include "FWCore/Framework/interface/MakerMacros.h"
0139 DEFINE_FWK_MODULE(BadGlobalMuonTagger);