File indexing completed on 2024-09-07 04:36:38
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "HLTMuonL3PreFilter.h"
0010
0011 #include "DataFormats/Common/interface/Handle.h"
0012 #include "DataFormats/Common/interface/RefToBase.h"
0013
0014 #include "DataFormats/HLTReco/interface/TriggerFilterObjectWithRefs.h"
0015 #include "DataFormats/HLTReco/interface/TriggerRefsCollections.h"
0016
0017 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0018 #include "DataFormats/TrackReco/interface/Track.h"
0019 #include "DataFormats/MuonReco/interface/MuonTrackLinks.h"
0020 #include "DataFormats/MuonReco/interface/Muon.h"
0021
0022 #include "DataFormats/MuonSeed/interface/L3MuonTrajectorySeed.h"
0023 #include "DataFormats/MuonSeed/interface/L3MuonTrajectorySeedCollection.h"
0024 #include "DataFormats/TrajectorySeed/interface/TrajectorySeedCollection.h"
0025
0026 #include "FWCore/Utilities/interface/InputTag.h"
0027
0028
0029
0030
0031 using namespace std;
0032 using namespace edm;
0033 using namespace reco;
0034 using namespace trigger;
0035
0036 HLTMuonL3PreFilter::HLTMuonL3PreFilter(const ParameterSet& iConfig)
0037 : HLTFilter(iConfig),
0038 propSetup_(iConfig, consumesCollector()),
0039 beamspotTag_(iConfig.getParameter<edm::InputTag>("BeamSpotTag")),
0040 beamspotToken_(consumes<reco::BeamSpot>(beamspotTag_)),
0041 candTag_(iConfig.getParameter<InputTag>("CandTag")),
0042 candToken_(consumes<reco::RecoChargedCandidateCollection>(candTag_)),
0043 previousCandTag_(iConfig.getParameter<InputTag>("PreviousCandTag")),
0044 previousCandToken_(consumes<trigger::TriggerFilterObjectWithRefs>(previousCandTag_)),
0045 requireL3MuonTrajectorySeed_(iConfig.getParameter<bool>("requireL3MuonTrajectorySeed")),
0046 l1CandTag_(iConfig.getParameter<InputTag>("L1CandTag")),
0047 l1CandToken_(requireL3MuonTrajectorySeed_ ? edm::EDGetTokenT<trigger::TriggerFilterObjectWithRefs>()
0048 : consumes<trigger::TriggerFilterObjectWithRefs>(l1CandTag_)),
0049 recoMuTag_(iConfig.getParameter<InputTag>("inputMuonCollection")),
0050 recoMuToken_(requireL3MuonTrajectorySeed_ ? edm::EDGetTokenT<reco::MuonCollection>()
0051 : consumes<reco::MuonCollection>(recoMuTag_)),
0052 min_N_(iConfig.getParameter<int>("MinN")),
0053 max_Eta_(iConfig.getParameter<double>("MaxEta")),
0054 min_Nhits_(iConfig.getParameter<int>("MinNhits")),
0055 max_Dr_(iConfig.getParameter<double>("MaxDr")),
0056 min_Dr_(iConfig.getParameter<double>("MinDr")),
0057 max_Dz_(iConfig.getParameter<double>("MaxDz")),
0058 min_DxySig_(iConfig.getParameter<double>("MinDxySig")),
0059 min_Pt_(iConfig.getParameter<double>("MinPt")),
0060 nsigma_Pt_(iConfig.getParameter<double>("NSigmaPt")),
0061 max_NormalizedChi2_(iConfig.getParameter<double>("MaxNormalizedChi2")),
0062 max_DXYBeamSpot_(iConfig.getParameter<double>("MaxDXYBeamSpot")),
0063 min_DXYBeamSpot_(iConfig.getParameter<double>("MinDXYBeamSpot")),
0064 min_NmuonHits_(iConfig.getParameter<int>("MinNmuonHits")),
0065 max_PtDifference_(iConfig.getParameter<double>("MaxPtDifference")),
0066 min_TrackPt_(iConfig.getParameter<double>("MinTrackPt")),
0067 min_MuonStations_L3fromL1_(iConfig.getParameter<int>("minMuonStations")),
0068 allowedTypeMask_L3fromL1_(iConfig.getParameter<unsigned int>("allowedTypeMask")),
0069 requiredTypeMask_L3fromL1_(iConfig.getParameter<unsigned int>("requiredTypeMask")),
0070 maxNormalizedChi2_L3fromL1_(iConfig.getParameter<double>("MaxNormalizedChi2_L3FromL1")),
0071 trkMuonId_(muon::SelectionType(iConfig.getParameter<unsigned int>("trkMuonId"))),
0072 L1MatchingdR_(iConfig.getParameter<double>("L1MatchingdR")),
0073 L1MatchingdR2_(L1MatchingdR_ * L1MatchingdR_),
0074 matchPreviousCand_(iConfig.getParameter<bool>("MatchToPreviousCand")),
0075
0076 devDebug_(false),
0077 theL3LinksLabel(iConfig.getParameter<InputTag>("InputLinks")),
0078 linkToken_(requireL3MuonTrajectorySeed_ ? edm::EDGetTokenT<reco::MuonTrackLinksCollection>()
0079 : consumes<reco::MuonTrackLinksCollection>(theL3LinksLabel)) {
0080 if (L1MatchingdR_ <= 0.) {
0081 throw cms::Exception("HLTMuonL3PreFilterConfiguration")
0082 << "invalid value for parameter \"L1MatchingdR\" (must be > 0): " << L1MatchingdR_;
0083 }
0084 LogDebug("HLTMuonL3PreFilter") << " CandTag/MinN/MaxEta/MinNhits/MaxDr/MinDr/MaxDz/MinDxySig/MinPt/NSigmaPt : "
0085 << candTag_.encode() << " " << min_N_ << " " << max_Eta_ << " " << min_Nhits_ << " "
0086 << max_Dr_ << " " << min_Dr_ << " " << max_Dz_ << " " << min_DxySig_ << " " << min_Pt_
0087 << " " << nsigma_Pt_;
0088 }
0089
0090 HLTMuonL3PreFilter::~HLTMuonL3PreFilter() = default;
0091
0092 void HLTMuonL3PreFilter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0093 edm::ParameterSetDescription desc;
0094 makeHLTFilterDescription(desc);
0095 desc.add<edm::InputTag>("BeamSpotTag", edm::InputTag("hltOfflineBeamSpot"));
0096 desc.add<edm::InputTag>("CandTag", edm::InputTag("hltL3MuonCandidates"));
0097
0098 desc.add<edm::InputTag>("PreviousCandTag", edm::InputTag(""));
0099 desc.add<edm::InputTag>("L1CandTag", edm::InputTag(""));
0100 desc.add<edm::InputTag>("inputMuonCollection", edm::InputTag(""));
0101 desc.add<int>("MinN", 1);
0102 desc.add<double>("MaxEta", 2.5);
0103 desc.add<int>("MinNhits", 0);
0104 desc.add<double>("MaxDr", 2.0);
0105 desc.add<double>("MinDr", -1.0);
0106 desc.add<double>("MaxDz", 9999.0);
0107 desc.add<double>("MinDxySig", -1.0);
0108 desc.add<double>("MinPt", 3.0);
0109 desc.add<double>("NSigmaPt", 0.0);
0110 desc.add<double>("MaxNormalizedChi2", 9999.0);
0111 desc.add<double>("MaxDXYBeamSpot", 9999.0);
0112 desc.add<double>("MinDXYBeamSpot", -1.0);
0113 desc.add<int>("MinNmuonHits", 0);
0114 desc.add<double>("MaxPtDifference", 9999.0);
0115 desc.add<double>("MinTrackPt", 0.0);
0116 desc.add<int>("minMuonStations", -1);
0117 desc.add<int>("minTrkHits", -1);
0118 desc.add<int>("minMuonHits", -1);
0119 desc.add<unsigned int>("allowedTypeMask", 255);
0120 desc.add<unsigned int>("requiredTypeMask", 0);
0121 desc.add<double>("MaxNormalizedChi2_L3FromL1", 9999.);
0122 desc.add<unsigned int>("trkMuonId", 0);
0123 desc.add<double>("L1MatchingdR", 0.3);
0124 desc.add<bool>("MatchToPreviousCand", true);
0125 desc.add<edm::InputTag>("InputLinks", edm::InputTag(""));
0126 desc.add<bool>("requireL3MuonTrajectorySeed", false);
0127 PropagateToMuonSetup::fillPSetDescription(desc);
0128 descriptions.add("hltMuonL3PreFilter", desc);
0129 }
0130
0131
0132
0133
0134
0135
0136 bool HLTMuonL3PreFilter::hltFilter(Event& iEvent,
0137 const EventSetup& iSetup,
0138 trigger::TriggerFilterObjectWithRefs& filterproduct) const {
0139
0140
0141
0142
0143 auto const prop = propSetup_.init(iSetup);
0144
0145 if (saveTags())
0146 filterproduct.addCollectionTag(candTag_);
0147
0148
0149 Handle<RecoChargedCandidateCollection> mucands;
0150 iEvent.getByToken(candToken_, mucands);
0151
0152
0153 Handle<TriggerFilterObjectWithRefs> previousLevelCands;
0154 iEvent.getByToken(previousCandToken_, previousLevelCands);
0155 vector<RecoChargedCandidateRef> vl2cands;
0156 previousLevelCands->getObjects(TriggerMuon, vl2cands);
0157
0158
0159 Handle<BeamSpot> recoBeamSpotHandle;
0160 iEvent.getByToken(beamspotToken_, recoBeamSpotHandle);
0161 const BeamSpot& beamSpot = *recoBeamSpotHandle;
0162
0163
0164 int n = 0;
0165
0166
0167 std::map<reco::TrackRef, std::vector<RecoChargedCandidateRef> > L2toL3s;
0168
0169 std::map<unsigned int, RecoChargedCandidateRef> MuonToL3s;
0170
0171
0172 if (mucands->empty())
0173 return false;
0174 auto const& tk = (*mucands)[0].track();
0175 bool useL3MTS = false;
0176
0177 if (tk->seedRef().isNonnull()) {
0178 auto a = dynamic_cast<const L3MuonTrajectorySeed*>(tk->seedRef().get());
0179
0180 if (requireL3MuonTrajectorySeed_ && not a) {
0181 throw cms::Exception("HLTMuonL3PreFilter")
0182 << "requireL3MuonTrajectorySeed is required to be true, but cannot cast the input "
0183 "RecoChargedCandidateCollection to a L3MuonTrajectorySeed./n Please cross-check the configuration of this "
0184 "module";
0185 }
0186
0187 useL3MTS = a != nullptr;
0188 }
0189
0190
0191 if (useL3MTS) {
0192 LogDebug("HLTMuonL3PreFilter") << "HLTMuonL3PreFilter::hltFilter is in mode: useL3MTS";
0193
0194 unsigned int maxI = mucands->size();
0195 for (unsigned int i = 0; i != maxI; ++i) {
0196 const TrackRef& tk = (*mucands)[i].track();
0197 edm::Ref<L3MuonTrajectorySeedCollection> l3seedRef =
0198 tk->seedRef().castTo<edm::Ref<L3MuonTrajectorySeedCollection> >();
0199 TrackRef staTrack = l3seedRef->l2Track();
0200 LogDebug("HLTMuonL3PreFilter") << "L2 from: " << iEvent.getStableProvenance(staTrack.id()).moduleLabel()
0201 << " index: " << staTrack.key();
0202 L2toL3s[staTrack].push_back(RecoChargedCandidateRef(mucands, i));
0203 }
0204 }
0205
0206
0207 else {
0208 LogDebug("HLTMuonL3PreFilter") << "HLTMuonL3PreFilter::hltFilter is in mode: not useL3MTS";
0209
0210
0211 edm::Handle<reco::MuonTrackLinksCollection> links;
0212 iEvent.getByToken(linkToken_, links);
0213
0214 edm::Handle<trigger::TriggerFilterObjectWithRefs> level1Cands;
0215 std::vector<l1t::MuonRef> vl1cands;
0216
0217 bool check_l1match = true;
0218
0219
0220 for (unsigned int i(0); i < mucands->size(); ++i) {
0221 RecoChargedCandidateRef cand(mucands, i);
0222 TrackRef tk = cand->track();
0223
0224 if (!matchPreviousCand_) {
0225 MuonToL3s[i] = RecoChargedCandidateRef(cand);
0226 } else {
0227 check_l1match = true;
0228 for (auto const& link : *links) {
0229
0230
0231 const reco::Track& trackerTrack = *link.trackerTrack();
0232
0233 float dR2 = deltaR2(tk->eta(), tk->phi(), trackerTrack.eta(), trackerTrack.phi());
0234 float dPt = std::abs(tk->pt() - trackerTrack.pt());
0235 if (tk->pt() != 0)
0236 dPt = dPt / tk->pt();
0237
0238 if (dR2 < 0.02 * 0.02 and dPt < 0.001) {
0239 const TrackRef staTrack = link.standAloneTrack();
0240 L2toL3s[staTrack].push_back(RecoChargedCandidateRef(cand));
0241 check_l1match = false;
0242 }
0243 }
0244
0245 if (!l1CandTag_.label().empty() && check_l1match) {
0246 auto const propagated = prop.extrapolate(*tk);
0247 auto const etaForMatch = propagated.isValid() ? propagated.globalPosition().eta() : cand->eta();
0248 auto const phiForMatch = propagated.isValid() ? (double)propagated.globalPosition().phi() : cand->phi();
0249 iEvent.getByToken(l1CandToken_, level1Cands);
0250 level1Cands->getObjects(trigger::TriggerL1Mu, vl1cands);
0251 const unsigned int nL1Muons(vl1cands.size());
0252 for (unsigned int il1 = 0; il1 != nL1Muons; ++il1) {
0253 if (deltaR2(etaForMatch, phiForMatch, vl1cands[il1]->eta(), vl1cands[il1]->phi()) < L1MatchingdR2_) {
0254 MuonToL3s[i] = RecoChargedCandidateRef(cand);
0255 }
0256 }
0257 }
0258 }
0259 }
0260 }
0261
0262
0263 LogDebug("HLTMuonL3PreFilter") << "looking at: " << L2toL3s.size() << " L2->L3s from: " << mucands->size();
0264 for (const auto& L2toL3s_it : L2toL3s) {
0265 if (!triggeredByLevel2(L2toL3s_it.first, vl2cands))
0266 continue;
0267
0268
0269 unsigned int iTk = 0;
0270 unsigned int maxItk = L2toL3s_it.second.size();
0271 for (; iTk != maxItk; iTk++) {
0272 const RecoChargedCandidateRef& cand = L2toL3s_it.second[iTk];
0273 if (!applySelection(cand, beamSpot))
0274 continue;
0275
0276 filterproduct.addObject(TriggerMuon, cand);
0277 n++;
0278 break;
0279 }
0280 }
0281
0282
0283 edm::Handle<reco::MuonCollection> recomuons;
0284
0285
0286
0287 if (!MuonToL3s.empty()) {
0288 iEvent.getByToken(recoMuToken_, recomuons);
0289 }
0290
0291 for (const auto& MuonToL3s_it : MuonToL3s) {
0292 const reco::Muon& muon(recomuons->at(MuonToL3s_it.first));
0293
0294
0295 if ((muon.type() & allowedTypeMask_L3fromL1_) == 0)
0296 continue;
0297 if ((muon.type() & requiredTypeMask_L3fromL1_) != requiredTypeMask_L3fromL1_)
0298 continue;
0299 if (muon.numberOfMatchedStations() < min_MuonStations_L3fromL1_)
0300 continue;
0301 if (!muon.globalTrack().isNull()) {
0302 if (muon.globalTrack()->normalizedChi2() > maxNormalizedChi2_L3fromL1_)
0303 continue;
0304 }
0305 if (muon.isTrackerMuon() && !muon::isGoodMuon(muon, trkMuonId_))
0306 continue;
0307
0308 const RecoChargedCandidateRef& cand = MuonToL3s_it.second;
0309
0310 if (!applySelection(cand, beamSpot))
0311 continue;
0312 filterproduct.addObject(TriggerMuon, cand);
0313 n++;
0314
0315 break;
0316 }
0317
0318 vector<RecoChargedCandidateRef> vref;
0319 filterproduct.getObjects(TriggerMuon, vref);
0320 for (auto& i : vref) {
0321 RecoChargedCandidateRef candref = RecoChargedCandidateRef(i);
0322 TrackRef tk = candref->get<TrackRef>();
0323 LogDebug("HLTMuonL3PreFilter") << " Track passing filter: trackRef pt= " << tk->pt() << " (" << candref->pt()
0324 << ") "
0325 << ", eta: " << tk->eta() << " (" << candref->eta() << ") ";
0326 }
0327
0328
0329 const bool accept(n >= min_N_);
0330
0331 LogDebug("HLTMuonL3PreFilter") << " >>>>> Result of HLTMuonL3PreFilter is " << accept
0332 << ", number of muons passing thresholds= " << n;
0333
0334 return accept;
0335 }
0336
0337 bool HLTMuonL3PreFilter::triggeredByLevel2(const TrackRef& staTrack, vector<RecoChargedCandidateRef>& vcands) const {
0338 bool ok = false;
0339 for (auto& vcand : vcands) {
0340 if (vcand->get<TrackRef>() == staTrack) {
0341 ok = true;
0342 LogDebug("HLTMuonL3PreFilter") << "The L2 track triggered";
0343 break;
0344 }
0345 }
0346 return ok;
0347 }
0348
0349 bool HLTMuonL3PreFilter::applySelection(const RecoChargedCandidateRef& cand, const BeamSpot& beamSpot) const {
0350
0351 if (std::abs(cand->eta()) > max_Eta_)
0352 return false;
0353
0354 TrackRef tk = cand->track();
0355 LogDebug("HLTMuonL3PreFilter") << " Muon in loop, q*pt= " << tk->charge() * tk->pt() << " ("
0356 << cand->charge() * cand->pt() << ") "
0357 << ", eta= " << tk->eta() << " (" << cand->eta() << ") "
0358 << ", hits= " << tk->numberOfValidHits() << ", d0= " << tk->d0()
0359 << ", dz= " << tk->dz();
0360
0361
0362 if (tk->numberOfValidHits() < min_Nhits_)
0363 return false;
0364
0365
0366 auto dr =
0367 std::abs((-(cand->vx() - beamSpot.x0()) * cand->py() + (cand->vy() - beamSpot.y0()) * cand->px()) / cand->pt());
0368 if (dr > max_Dr_)
0369 return false;
0370
0371
0372 if (dr < min_Dr_)
0373 return false;
0374
0375
0376 if (std::abs((cand->vz() - beamSpot.z0()) -
0377 ((cand->vx() - beamSpot.x0()) * cand->px() + (cand->vy() - beamSpot.y0()) * cand->py()) / cand->pt() *
0378 cand->pz() / cand->pt()) > max_Dz_)
0379 return false;
0380
0381
0382 if (min_DxySig_ > 0 && (tk->dxyError() <= 0 || std::abs(tk->dxy(beamSpot.position()) / tk->dxyError()) < min_DxySig_))
0383 return false;
0384
0385
0386 if (tk->normalizedChi2() > max_NormalizedChi2_)
0387 return false;
0388
0389
0390 float absDxy = std::abs(tk->dxy(beamSpot.position()));
0391 if (absDxy > max_DXYBeamSpot_ || absDxy < min_DXYBeamSpot_)
0392 return false;
0393
0394
0395 const reco::HitPattern& trackHits = tk->hitPattern();
0396 if (trackHits.numberOfValidMuonHits() < min_NmuonHits_)
0397 return false;
0398
0399
0400 double candPt = cand->pt();
0401 double trackPt = tk->pt();
0402
0403 if (std::abs(candPt - trackPt) > max_PtDifference_)
0404 return false;
0405
0406
0407 if (trackPt < min_TrackPt_)
0408 return false;
0409
0410
0411 double pt = cand->pt();
0412 double err0 = tk->error(0);
0413 double abspar0 = std::abs(tk->parameter(0));
0414 double ptLx = pt;
0415
0416 if (abspar0 > 0)
0417 ptLx += nsigma_Pt_ * err0 / abspar0 * pt;
0418 LogTrace("HLTMuonL3PreFilter") << " ...Muon in loop, trackkRef pt= " << tk->pt() << ", ptLx= " << ptLx << " cand pT "
0419 << cand->pt();
0420 if (ptLx < min_Pt_)
0421 return false;
0422
0423 return true;
0424 }
0425
0426
0427 #include "FWCore/Framework/interface/MakerMacros.h"
0428 DEFINE_FWK_MODULE(HLTMuonL3PreFilter);