diff --git a/DataFormats/L1TCorrelator/interface/TkMuon.h b/DataFormats/L1TCorrelator/interface/TkMuon.h index 841738c4609b8..c0401b34ea1cc 100644 --- a/DataFormats/L1TCorrelator/interface/TkMuon.h +++ b/DataFormats/L1TCorrelator/interface/TkMuon.h @@ -7,6 +7,7 @@ #include "DataFormats/L1TrackTrigger/interface/TTTypes.h" #include "DataFormats/L1TMuon/interface/RegionalMuonCand.h" #include "DataFormats/L1TMuon/interface/RegionalMuonCandFwd.h" +#include "DataFormats/L1TMuon/interface/EMTFTrack.h" namespace l1t { class TkMuon : public L1Candidate { @@ -21,6 +22,11 @@ namespace l1t { const edm::Ptr& trkPtr, float tkisol = -999.); + TkMuon(const LorentzVector& p4, + const edm::Ref& emtfTrk, + const edm::Ptr& trkPtr, + float tkisol = -999.); + //One more constructor for Tracker+ Stubs algorithm not requiring the Muon candidate TkMuon(const LorentzVector& p4, const edm::Ptr& trkPtr, float tkisol = -999.); @@ -30,6 +36,7 @@ namespace l1t { const edm::Ptr& trkPtr() const { return trkPtr_; } const edm::Ref& muRef() const { return muRef_; } + const edm::Ref& emtfTrk() const { return emtfTrk_; } float trkIsol() const { return theIsolation; } float trkzVtx() const { return TrkzVtx_; } @@ -58,6 +65,7 @@ namespace l1t { private: // used for the Naive producer edm::Ref muRef_; + edm::Ref emtfTrk_; edm::Ptr trkPtr_; diff --git a/DataFormats/L1TCorrelator/src/TkMuon.cc b/DataFormats/L1TCorrelator/src/TkMuon.cc index ff85b4f2da8b7..4395d722c1cc8 100644 --- a/DataFormats/L1TCorrelator/src/TkMuon.cc +++ b/DataFormats/L1TCorrelator/src/TkMuon.cc @@ -17,6 +17,16 @@ TkMuon::TkMuon(const LorentzVector& p4, } } +TkMuon::TkMuon(const LorentzVector& p4, + const edm::Ref& emtfRef, + const edm::Ptr& trackPtr, + float tkisol) + : L1Candidate(p4), emtfTrk_(emtfRef), trkPtr_(trackPtr), theIsolation(tkisol), TrkzVtx_(999), quality_(999) { + if (trkPtr_.isNonnull()) { + setTrkzVtx(trkPtr()->POCA().z()); + } +} + TkMuon::TkMuon(const LorentzVector& p4, const edm::Ptr& trackPtr, float tkisol) : L1Candidate(p4), trkPtr_(trackPtr), theIsolation(tkisol), TrkzVtx_(999), quality_(999) { if (trkPtr_.isNonnull()) { diff --git a/DataFormats/L1TCorrelator/src/classes_def.xml b/DataFormats/L1TCorrelator/src/classes_def.xml index 9db8c9f70a617..a9c156c248963 100644 --- a/DataFormats/L1TCorrelator/src/classes_def.xml +++ b/DataFormats/L1TCorrelator/src/classes_def.xml @@ -1,20 +1,19 @@ - - - - - - - - + + + + + + + - + @@ -25,7 +24,6 @@ - @@ -71,13 +69,16 @@ - + + + + diff --git a/L1Trigger/L1TTrackMatch/plugins/L1TkFastVertexProducer.cc b/L1Trigger/L1TTrackMatch/plugins/L1TkFastVertexProducer.cc index 1d06ecd7bde7f..a01dcfe847661 100644 --- a/L1Trigger/L1TTrackMatch/plugins/L1TkFastVertexProducer.cc +++ b/L1Trigger/L1TTrackMatch/plugins/L1TkFastVertexProducer.cc @@ -69,6 +69,7 @@ class L1TkFastVertexProducer : public edm::global::EDProducer<> { float pTMax_; // in GeV, saturation / truncation value int highPtTracks_; // saturate or truncate + int nVtx_; // the number of vertices to return int nStubsmin_; // minimum number of stubs int nStubsPSmin_; // minimum number of stubs in PS modules @@ -116,6 +117,7 @@ L1TkFastVertexProducer::L1TkFastVertexProducer(const edm::ParameterSet& iConfig) pTMax_ = (float)iConfig.getParameter("PTMAX"); highPtTracks_ = iConfig.getParameter("HighPtTracks"); + nVtx_ = iConfig.getParameter("nVtx"); nStubsmin_ = iConfig.getParameter("nStubsmin"); nStubsPSmin_ = iConfig.getParameter("nStubsPSmin"); nBinning_ = iConfig.getParameter("nBinning"); @@ -309,6 +311,7 @@ void L1TkFastVertexProducer::produce(edm::StreamID, edm::Event& iEvent, const ed float zvtx_sliding = -999; float sigma_max = -999; + int imax = -999; int nb = htmp.GetNbinsX(); for (int i = 2; i <= nb - 1; i++) { float a0 = htmp.GetBinContent(i - 1); @@ -317,6 +320,7 @@ void L1TkFastVertexProducer::produce(edm::StreamID, edm::Event& iEvent, const ed float sigma = a0 + a1 + a2; if (sigma > sigma_max) { sigma_max = sigma; + imax = i; float z0 = htmp.GetBinCenter(i - 1); float z1 = htmp.GetBinCenter(i); float z2 = htmp.GetBinCenter(i + 1); @@ -324,26 +328,31 @@ void L1TkFastVertexProducer::produce(edm::StreamID, edm::Event& iEvent, const ed } } - zvtx_sliding = -999; - sigma_max = -999; - for (int i = 2; i <= nb - 1; i++) { - float a0 = htmp_weight.GetBinContent(i - 1); - float a1 = htmp_weight.GetBinContent(i); - float a2 = htmp_weight.GetBinContent(i + 1); - float sigma = a0 + a1 + a2; - if (sigma > sigma_max) { - sigma_max = sigma; - float z0 = htmp_weight.GetBinCenter(i - 1); - float z1 = htmp_weight.GetBinCenter(i); - float z2 = htmp_weight.GetBinCenter(i + 1); - zvtx_sliding = (a0 * z0 + a1 * z1 + a2 * z2) / sigma; + std::vector found; + found.reserve(nVtx_); + for (int ivtx = 0; ivtx < nVtx_; ivtx++) { + zvtx_sliding = -999; + sigma_max = -999; + imax = -999; + for (int i = 2; i <= nb - 1; i++) { + float a0 = htmp_weight.GetBinContent(i - 1); + float a1 = htmp_weight.GetBinContent(i); + float a2 = htmp_weight.GetBinContent(i + 1); + float sigma = a0 + a1 + a2; + if ((sigma > sigma_max) && (find(found.begin(), found.end(), i) == found.end())) { + sigma_max = sigma; + imax = i; + float z0 = htmp_weight.GetBinCenter(i - 1); + float z1 = htmp_weight.GetBinCenter(i); + float z2 = htmp_weight.GetBinCenter(i + 1); + zvtx_sliding = (a0 * z0 + a1 * z1 + a2 * z2) / sigma; + } } + found.push_back(imax); + TkPrimaryVertex vtx4(zvtx_sliding, sigma_max); + result->push_back(vtx4); } - TkPrimaryVertex vtx4(zvtx_sliding, sigma_max); - - result->push_back(vtx4); - iEvent.put(std::move(result)); } diff --git a/L1Trigger/L1TTrackMatch/plugins/L1TkMuonProducer.cc b/L1Trigger/L1TTrackMatch/plugins/L1TkMuonProducer.cc index 3030438648824..8199d7ac45315 100644 --- a/L1Trigger/L1TTrackMatch/plugins/L1TkMuonProducer.cc +++ b/L1Trigger/L1TTrackMatch/plugins/L1TkMuonProducer.cc @@ -89,6 +89,12 @@ class L1TkMuonProducer : public edm::stream::EDProducer<> { const edm::Handle& muonH, int detector) const; + void build_tkMuons_from_idxs(TkMuonCollection& tkMuons, + const std::vector& matches, + const edm::Handle& l1tksH, + const edm::Handle& emtfTksH, + int detector) const; + // dump and convert tracks to the format needed for the MAnTra correlator std::vector product_to_trkvec(const L1TTTrackCollectionType& l1tks) const; // tracks // regional muon finder @@ -98,6 +104,9 @@ class L1TkMuonProducer : public edm::stream::EDProducer<> { float etaMin_; float etaMax_; + float etaBO_; //eta value for barrel-overlap fontier + float etaOE_; //eta value for overlap-endcap fontier + bool useRegionEtaMatching_; float zMax_; // |z_track| < zMax_ in cm float chi2Max_; float pTMinTra_; @@ -106,6 +115,7 @@ class L1TkMuonProducer : public edm::stream::EDProducer<> { bool correctGMTPropForTkZ_; bool use5ParameterFit_; bool useTPMatchWindows_; + bool applyQuality_; AlgoType bmtfMatchAlgoVersion_; AlgoType omtfMatchAlgoVersion_; @@ -129,11 +139,16 @@ class L1TkMuonProducer : public edm::stream::EDProducer<> { L1TkMuonProducer::L1TkMuonProducer(const edm::ParameterSet& iConfig) : etaMin_((float)iConfig.getParameter("ETAMIN")), etaMax_((float)iConfig.getParameter("ETAMAX")), + etaBO_(iConfig.exists("ETABARRELOVERLAP") ? (float)iConfig.getParameter("ETABARRELOVERLAP") : 0.83), + etaOE_(iConfig.exists("ETAOVERLAPENDCAP") ? (float)iConfig.getParameter("ETAOVERLAPENDCAP") : 1.24), + useRegionEtaMatching_(iConfig.exists("useRegionEtaMatching") ? iConfig.getParameter("useRegionEtaMatching") + : true), zMax_((float)iConfig.getParameter("ZMAX")), chi2Max_((float)iConfig.getParameter("CHI2MAX")), pTMinTra_((float)iConfig.getParameter("PTMINTRA")), dRMax_((float)iConfig.getParameter("DRmax")), nStubsmin_(iConfig.getParameter("nStubsmin")), + // --- mantra corr params mantra_n_trk_par_(iConfig.getParameter("mantra_n_trk_par")), bmtfToken_(consumes(iConfig.getParameter("L1BMTFInputTag"))), @@ -192,6 +207,8 @@ L1TkMuonProducer::L1TkMuonProducer(const edm::ParameterSet& iConfig) use5ParameterFit_ = iConfig.getParameter("use5ParameterFit"); useTPMatchWindows_ = iConfig.getParameter("useTPMatchWindows"); + applyQuality_ = iConfig.exists("applyQualityCuts") ? iConfig.getParameter("applyQualityCuts") : false; + produces(); // initializations @@ -324,9 +341,11 @@ void L1TkMuonProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup const auto& muons = product_to_muvec(*l1bmtfH.product()); const auto& match_idx = mantracorr_barr_->find_match(mantradf_tracks, muons); build_tkMuons_from_idxs(oc_bmtf_tkmuon, match_idx, l1tksH, l1bmtfH, barrel_MTF_region); - } else + } else { throw cms::Exception("TkMuAlgoConfig") << " barrel : trying to run an invalid algorithm version " << bmtfMatchAlgoVersion_ << " (this should never happen)\n"; + return; + } // ----------------------------------------------------- overlap if (omtfMatchAlgoVersion_ == kTP) @@ -335,9 +354,11 @@ void L1TkMuonProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup const auto& muons = product_to_muvec(*l1omtfH.product()); const auto& match_idx = mantracorr_ovrl_->find_match(mantradf_tracks, muons); build_tkMuons_from_idxs(oc_omtf_tkmuon, match_idx, l1tksH, l1omtfH, overlap_MTF_region); - } else + } else { throw cms::Exception("TkMuAlgoConfig") << " overlap : trying to run an invalid algorithm version " << omtfMatchAlgoVersion_ << " (this should never happen)\n"; + return; + } // ----------------------------------------------------- endcap if (emtfMatchAlgoVersion_ == kTP) @@ -347,12 +368,13 @@ void L1TkMuonProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup else if (emtfMatchAlgoVersion_ == kMantra) { const auto& muons = product_to_muvec(*l1emtfTCH.product()); const auto& match_idx = mantracorr_endc_->find_match(mantradf_tracks, muons); - //for the TkMu that were built from a EMTFCollection - do not produce a valid muon ref - edm::Handle invalidMuonH; - build_tkMuons_from_idxs(oc_emtf_tkmuon, match_idx, l1tksH, invalidMuonH, endcap_MTF_region); - } else + //for the TkMu that were built from a EMTFCollection - pass the emtf track as ref + build_tkMuons_from_idxs(oc_emtf_tkmuon, match_idx, l1tksH, l1emtfTCH, endcap_MTF_region); + } else { throw cms::Exception("TkMuAlgoConfig") << "endcap : trying to run an invalid algorithm version " << emtfMatchAlgoVersion_ << " (this should never happen)\n"; + return; + } // now combine all trk muons into a single output collection! auto oc_tkmuon = std::make_unique(); @@ -468,11 +490,26 @@ void L1TkMuonProducer::runOnMTFCollection_v1(const edm::Handle etaBO_) + continue; + } else if (detector == overlap_MTF_region) { + if (std::abs(l1tkmu.eta()) < etaBO_) + continue; + if (std::abs(l1tkmu.eta()) > etaOE_) + continue; + } else if (detector == endcap_MTF_region) { + if (std::abs(l1tkmu.eta()) < etaOE_) + continue; + } + } l1tkmu.setTrackCurvature(matchTk.rInv()); l1tkmu.setTrkzVtx((float)tkv3.z()); l1tkmu.setdR(drmin); l1tkmu.setNTracksMatched(nTracksMatch); l1tkmu.setMuonDetector(detector); + l1tkmu.setQuality(l1muRef->hwQual()); tkMuons.push_back(l1tkmu); } } @@ -509,6 +546,11 @@ void L1TkMuonProducer::runOnMTFCollection_v2(const edm::Handle l1tkPtr(l1tksH, il1ttrack); float trkisol = -999; // now doing as in the TP algo TkMuon l1tkmu(l1tkp4, l1muRef, l1tkPtr, trkisol); + + // avoid leaking of candidates to overlap region... + if (useRegionEtaMatching_ && std::abs(l1tkmu.eta()) < etaOE_) + continue; + l1tkmu.setTrackCurvature(matchTk.rInv()); l1tkmu.setTrkzVtx((float)tkv3.z()); l1tkmu.setMuonDetector(endcap_MTF_region); @@ -635,6 +677,12 @@ std::vector L1TkMuonProducer::product_to_muvec(const EM std::vector result(l1mus.size()); for (uint imu = 0; imu < l1mus.size(); ++imu) { auto& mu = l1mus[imu]; + + // dropping the emtf tracks with certain quality... + int emtfQual = (mu.Mode() == 11 || mu.Mode() == 13 || mu.Mode() == 14 || mu.Mode() == 15); + if (applyQuality_ && !emtfQual) + continue; + result[imu].pt = mu.Pt(); result[imu].eta = mu.Eta(); result[imu].theta = L1TkMuMantra::to_mpio2_pio2(L1TkMuMantra::eta_to_theta(mu.Eta())); @@ -670,6 +718,61 @@ void L1TkMuonProducer::build_tkMuons_from_idxs(TkMuonCollection& tkMuons, l1tkmu.setTrackCurvature(matchTk.rInv()); l1tkmu.setTrkzVtx((float)tkv3.z()); l1tkmu.setMuonDetector(detector); + l1tkmu.setQuality(l1muRef->hwQual()); + + // apply region cleaning (probably this is not the best way, but since this is going to + // be a patch and temporary, it is OK) + if (useRegionEtaMatching_) { + if (detector == barrel_MTF_region) { + if (std::abs(l1tkmu.eta()) > etaBO_) + continue; + } else if (detector == overlap_MTF_region) { + if (std::abs(l1tkmu.eta()) < etaBO_) + continue; + if (std::abs(l1tkmu.eta()) > etaOE_) + continue; + } else if (detector == endcap_MTF_region) { + if (std::abs(l1tkmu.eta()) < etaOE_) + continue; + } + } + tkMuons.push_back(l1tkmu); + } + return; +} + +void L1TkMuonProducer::build_tkMuons_from_idxs(TkMuonCollection& tkMuons, + const std::vector& matches, + const edm::Handle& l1tksH, + const edm::Handle& emtfTksH, + int detector) const { + for (uint imatch = 0; imatch < matches.size(); ++imatch) { + int match_trk_idx = matches[imatch]; + if (match_trk_idx < 0) + continue; // this muon was not matched to any candidate + + // take properties of the track + const L1TTTrackType& matchTk = (*l1tksH.product())[match_trk_idx]; + const auto& p3 = matchTk.momentum(); + const auto& tkv3 = matchTk.POCA(); + float p4e = sqrt(mu_mass * mu_mass + p3.mag2()); + math::XYZTLorentzVector l1tkp4(p3.x(), p3.y(), p3.z(), p4e); + + edm::Ptr l1tkPtr(l1tksH, match_trk_idx); + + auto l1emtfTrk = + emtfTksH.isValid() ? edm::Ref(emtfTksH, imatch) : edm::Ref(); + + float trkisol = -999; + TkMuon l1tkmu(l1tkp4, l1emtfTrk, l1tkPtr, trkisol); + l1tkmu.setTrackCurvature(matchTk.rInv()); + l1tkmu.setTrkzVtx((float)tkv3.z()); + l1tkmu.setMuonDetector(detector); + l1tkmu.setQuality(l1emtfTrk->Mode()); + + if (useRegionEtaMatching_ && std::abs(l1tkmu.eta()) < etaOE_) + continue; + tkMuons.push_back(l1tkmu); } return; diff --git a/L1Trigger/L1TTrackMatch/python/L1TkMuonProducer_cfi.py b/L1Trigger/L1TTrackMatch/python/L1TkMuonProducer_cfi.py index cad1428502d4c..c04c75a90c4d6 100644 --- a/L1Trigger/L1TTrackMatch/python/L1TkMuonProducer_cfi.py +++ b/L1Trigger/L1TTrackMatch/python/L1TkMuonProducer_cfi.py @@ -16,6 +16,9 @@ ############################################### TP algo ETAMIN = cms.double(0), ETAMAX = cms.double(5.), # no cut + ETABARRELOVERLAP = cms.double(0.83), + ETAOVERLAPENDCAP = cms.double(1.24), + useRegionEtaMatching = cms.bool(True), ZMAX = cms.double( 25. ), # in cm CHI2MAX = cms.double( 100. ), PTMINTRA = cms.double( 2. ), # in GeV diff --git a/L1Trigger/L1TTrackMatch/python/L1TkPrimaryVertexProducer_cfi.py b/L1Trigger/L1TTrackMatch/python/L1TkPrimaryVertexProducer_cfi.py index 4b929f74e9f0e..9755d0bd3a57a 100644 --- a/L1Trigger/L1TTrackMatch/python/L1TkPrimaryVertexProducer_cfi.py +++ b/L1Trigger/L1TTrackMatch/python/L1TkPrimaryVertexProducer_cfi.py @@ -11,6 +11,7 @@ ZMAX = cms.double ( 25. ) , # in cm CHI2MAX = cms.double( 100. ), PTMINTRA = cms.double( 2.), # PTMIN of L1Tracks, in GeV + nVtx = cms.int32( 1 ), # number of vertices to return nStubsmin = cms.int32( 4 ) , # minimum number of stubs nStubsPSmin = cms.int32( 3 ), # minimum number of stubs in PS modules nBinning = cms.int32( 601 ), # number of bins for the temp histo (from -30 cm to + 30 cm)