13 static constexpr
double const MeVtoGeV = 1. / 1000.;
16 std::vector<int> initializeChamberIdxOrder() {
22 const std::vector<ChIdx> orderedChIndices{
25 ChIdx::BEE, ChIdx::EIS, ChIdx::EIL, ChIdx::EMS,
26 ChIdx::EML, ChIdx::EOS, ChIdx::EOL, ChIdx::EES,
31 std::vector<int> chamberIndexOrder(orderedChIndices.size());
33 for (
unsigned int i = 0;
i < orderedChIndices.size();
i++) {
34 chamberIndexOrder[
static_cast<int>(orderedChIndices[
i])] =
i;
36 return chamberIndexOrder;
41 static const std::vector<int> chamberIndexOrder = initializeChamberIdxOrder();
42 return (chamberIndexOrder[
static_cast<int>(
first->chamberIndex())] <
43 chamberIndexOrder[
static_cast<int>(
second->chamberIndex())]);
76 "Not using allAuthors variable as currently missing in many derivations; LowPtEfficiency working point will always return "
77 "false, but this is expected at the moment. Have a look here: "
78 "https://twiki.cern.ch/twiki/bin/view/Atlas/MuonSelectionToolR21#New_LowPtEfficiency_working_poin");
82 ATH_MSG_INFO(
"You have opted to select only 3-station muons in the high-pT selection! "
83 <<
"Please feed 'HighPt3Layers' to the 'WorkingPoint' property to retrieve the appropriate scale-factors");
87 ATH_MSG_WARNING(
"No cut-based selection is defined for segment-tagged muons in the Low-pT working point. "
88 <<
"Please set UseMVALowPt=true if you want to try the UseSegmentTaggedLowPt=true option.");
92 ATH_MSG_INFO(
"MuonSelectionTool will assume both Standard and LRT Muons are being used, and that the necessary information is available to identify the type (standard or LRT).");
93 if (
m_quality!=1)
ATH_MSG_WARNING(
"Currently, only Medium quality is supported for LRT muons. Your chosen WP will be applied (w/o ID cuts), but no recommendations are available for this quality.");
98 m_acceptInfo.
addCut(
"IDHits",
"Selection of muons according to whether they passed the MCP ID Hit cuts");
99 m_acceptInfo.
addCut(
"Preselection",
"Selection of muons according to their type/author");
104 "Invalid quality (i.e. selection WP) set: "
106 <<
" - it must be an integer between 0 and 5! (0=Tight, 1=Medium, 2=Loose, 3=Veryloose, 4=HighPt, 5=LowPtEfficiency)");
107 return StatusCode::FAILURE;
110 ATH_MSG_ERROR(
"Cannot use lowPt working point if allAuthors is not available!");
111 return StatusCode::FAILURE;
114 if(m_caloScoreWP<1 || m_caloScoreWP>4){
115 ATH_MSG_FATAL(
"CaloScoreWP property must be set to 1, 2, 3 or 4");
116 return StatusCode::FAILURE;
120 ATH_MSG_INFO(
"Initialising tight working point histograms...");
121 std::string tightWP_rootFile_fullPath;
126 Form(
"MuonSelectorTools/%s/muonSelection_tightWPHisto.root",
m_calibration_version.value().c_str()));
129 ATH_MSG_INFO(
"Reading muon tight working point histograms from " << tightWP_rootFile_fullPath);
131 std::unique_ptr<TFile>
file(TFile::Open(tightWP_rootFile_fullPath.c_str(),
"READ"));
133 if (!
file->IsOpen()) {
134 ATH_MSG_ERROR(
"Cannot read tight working point file from " << tightWP_rootFile_fullPath);
135 return StatusCode::FAILURE;
149 ATH_MSG_INFO(
"Reading bad muon veto cut functions from " << BMVcutFile_fullPath);
151 std::unique_ptr<TFile> BMVfile(TFile::Open(BMVcutFile_fullPath.c_str(),
"READ"));
153 if (!BMVfile->IsOpen()) {
154 ATH_MSG_ERROR(
"Cannot read bad muon veto cut function file from " << BMVcutFile_fullPath);
155 return StatusCode::FAILURE;
165 return StatusCode::FAILURE;
176 auto make_mva_reader = [](TString
file_path) {
177 std::vector<std::string> mva_var_names{
"momentumBalanceSignificance",
178 "scatteringCurvatureSignificance",
179 "scatteringNeighbourSignificance",
181 "middleLargeHoles+middleSmallHoles",
182 "muonSegmentDeltaEta",
183 "muonSeg1ChamberIdx",
184 "muonSeg2ChamberIdx"};
185 std::unique_ptr<TMVA::Reader>
reader = std::make_unique<TMVA::Reader>(mva_var_names);
202 auto make_mva_reader_MuTagIMO = [](TString
file_path,
bool useSeg2ChamberIndex) {
203 std::vector<std::string> mva_var_names;
204 if (useSeg2ChamberIndex) mva_var_names.push_back(
"muonSeg2ChamberIndex");
205 mva_var_names.push_back(
"muonSeg1ChamberIndex");
206 mva_var_names.push_back(
"muonSeg1NPrecisionHits");
207 mva_var_names.push_back(
"muonSegmentDeltaEta");
208 mva_var_names.push_back(
"muonSeg1GlobalR");
209 mva_var_names.push_back(
"muonSeg1Chi2OverDoF");
210 mva_var_names.push_back(
"muonSCS");
212 std::unique_ptr<TMVA::Reader>
reader = std::make_unique<TMVA::Reader>(mva_var_names);
225 return StatusCode::SUCCESS;
231 ATH_MSG_ERROR(
" getHist(...) TFile is nullptr! Check that the Tight cut map is loaded correctly");
232 return StatusCode::FAILURE;
234 TH1* h_ptr =
nullptr;
240 return StatusCode::FAILURE;
242 hist = std::unique_ptr<TH1>{h_ptr};
243 hist->SetDirectory(
nullptr);
244 ATH_MSG_INFO(
"Successfully read tight working point histogram: " <<
hist->GetName());
246 return StatusCode::SUCCESS;
261 ATH_MSG_FATAL(
"accept(...) Failed to cast particle to muon");
272 static std::atomic<bool> checkDone{
false};
280 <<
" while on-the fly check for runNumber "<<
getRunNumber(
true)<<
" indicates isRun3Geo="<<
isRun3(
true));
286 ATH_MSG_WARNING(
"MuonSelectionTool currently supports Loose, Medium, Tight, HighPt, and LowPtEfficiency WPs for Run3; all other WPs can only be used in ExpertDevelopMode mode");
290 ATH_MSG_WARNING(
"For Run3, Tight WP is supported only when ExcludeNSWFromPrecisionLayers=False and RecalcPrecisionLayerswNSW=True");
305 else if (
mu.muonType() == xAOD::Muon::MuonStandAlone)
307 else if (
mu.muonType() == xAOD::Muon::SegmentTagged)
309 else if (
mu.muonType() == xAOD::Muon::CaloTagged)
311 else if (
mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon)
338 if (!passIDCuts || !passMuonCuts) {
return acceptData; }
342 bool thisMu_highpt =
false;
344 bool thisMu_lowptE =
false;
347 ATH_MSG_VERBOSE(
"Muon quality: " << thisMu_quality <<
" passes HighPt: " << thisMu_highpt
348 <<
" passes LowPtEfficiency: " << thisMu_lowptE);
349 if (m_quality < 4 && thisMu_quality >
m_quality) {
return acceptData; }
350 if (
m_quality == 4 && !thisMu_highpt) {
return acceptData; }
351 if (
m_quality == 5 && !thisMu_lowptE) {
return acceptData; }
363 const xAOD::TrackParticle* metrack =
mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
364 if (!idtrack || !metrack) idPt = mePt = -1.;
366 mePt = metrack->
pt();
367 idPt = idtrack->
pt();
369 if (!mePt_acc.isAvailable(
mu) || !idPt_acc.isAvailable(
mu)) {
371 <<
" q:" <<
mu.charge() <<
", author:" <<
mu.author()
372 <<
" is not decorated with calibrated momenta. Please fix");
373 throw std::runtime_error(
"MuonSelectionTool() - qOverP significance calculation failed");
386 <<
" Momentum dependent cuts are disabled. Return 0.");
390 const xAOD::TrackParticle* metrack =
muon.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
391 if (!idtrack || !metrack) {
392 ATH_MSG_VERBOSE(
"No ID / MS track. Return dummy large value of 1 mio");
395 float mePt{-1.}, idPt{-1.};
402 return std::abs((metrack->
charge() / meP) - (idtrack->
charge() / idP)) / qOverPsigma;
407 <<
"Momentum dependent cuts are disabled. Return 0.");
410 float mePt{-1.}, idPt{-1.};
412 return std::abs(idPt - mePt) /
muon.pt();
423 if (
mu.muonType() == xAOD::Muon::SegmentTagged) {
426 if (std::abs(
mu.eta()) < 0.1) {
430 ATH_MSG_VERBOSE(
"Do not allow segment-tagged muon at |eta| > 0.1 - return VeryLoose");
436 if (
mu.muonType() == xAOD::Muon::CaloTagged) {
461 ATH_MSG_VERBOSE(
"Muon has out-of-bounds precision hits - return VeryLoose");
467 const xAOD::TrackParticle* metrack =
mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
471 const float reducedChi2 =
mu.primaryTrackParticle()->chiSquared() /
mu.primaryTrackParticle()->numberDoF();
479 if (
summary.nprecisionLayers > 1 && reducedChi2 < 8 && std::abs(qOverPsignif) < 7) {
486 ATH_MSG_VERBOSE(
"Muon did not pass requirements for tight combined muon");
490 (
summary.nprecisionLayers > 1 ||(
summary.nprecisionLayers == 1 &&
summary.nprecisionHoleLayers < 2 && std::abs(
mu.eta()) < 0.1))
497 ATH_MSG_VERBOSE(
"Muon did not pass requirements for medium combined muon");
503 if ((
summary.nprecisionLayers > 1 ||
504 (
summary.nprecisionLayers == 1 &&
summary.nprecisionHoleLayers < 2 && std::abs(
mu.eta()) < 0.1))) {
520 ATH_MSG_VERBOSE(
"Muon passed selection for loose working point at low pT");
525 ATH_MSG_VERBOSE(
"Did not pass selections for combined muon - returning VeryLoose");
534 ATH_MSG_VERBOSE(
"Standalone muons currently only used when in expert mode for run3");
538 if (std::abs(
mu.eta()) > 2.5) {
549 ATH_MSG_VERBOSE(
"Muon did not pass selection for medium stand-alone muon - return VeryLoose");
554 if (
mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon) {
558 ATH_MSG_VERBOSE(
"Silicon-associated forward muon muons currently only used when in expert mode for run3");
563 const xAOD::TrackParticle* metrack =
mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
565 if (cbtrack && metrack) {
566 if (std::abs(cbtrack->
eta()) > 2.5) {
573 "SiliconForwardAssociated muon has ID track as primary track particle. "
574 <<
"This is a bug fixed starting with xAODMuon-00-17-07, which should be present in this release. "
575 <<
"Please report this to the Muon CP group!");
584 ATH_MSG_VERBOSE(
"Muon did not pass selection for medium silicon-associated forward muon - return VeryLoose");
588 ATH_MSG_VERBOSE(
"Muon did not pass selection for loose/medium/tight for any muon type - return VeryLoose");
598 if (isLRTmuon(
mu))
return true;
605 ATH_MSG_FATAL(
"No information available to tell if the muon is LRT or standard. Either run MuonLRTMergingAlg to decorate with `isLRT` flag, or supply the patternRecoInfo for the original ID track.");
606 throw std::runtime_error(
"MuonSelectionTool() - isLRT decor and patternRecoInfo both unavailable for a muon.");
608 std::bitset<xAOD::NumberOfTrackRecoInfo> patternBitSet(patternAcc(*idtrack));
616 }
else if (
mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon) {
618 if (cbtrack && std::abs(cbtrack->
eta()) > 2.5) {
return true; }
621 if (
mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle))
622 return passedIDCuts(*
mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle));
623 else if (
mu.primaryTrackParticle())
633 const xAOD::TrackParticle* metrack =
mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
639 bool IsBadMuon =
false;
640 if (idtrack && metrack && cbtrack) {
642 double qOverP_ID = idtrack->
qOverP();
644 double qOverP_ME = metrack->
qOverP();
646 double qOverP_CB = cbtrack->
qOverP();
659 double IdCbRatio = std::abs((qOverPerr_ID / qOverP_ID) / (qOverPerr_CB / qOverP_CB));
660 double MeCbRatio = std::abs((qOverPerr_ME / qOverP_ME) / (qOverPerr_CB / qOverP_CB));
661 IsBadMuon = (IdCbRatio < 0.8 || MeCbRatio < 0.8 || IsBadMuon);
665 double IdCbRatio = std::abs((qOverPerr_ID / qOverP_ID) / (qOverPerr_CB / qOverP_CB));
666 double MeCbRatio = std::abs((qOverPerr_ME / qOverP_ME) / (qOverPerr_CB / qOverP_CB));
667 IsBadMuon = (IdCbRatio < 0.8 || MeCbRatio < 0.8);
685 ATH_MSG_VERBOSE(
"LowPt WP currently not supported for run3 if not in expert mode");
701 ATH_MSG_VERBOSE(
"Muon is not combined or segment-tagged - fail low-pT");
714 ATH_MSG_VERBOSE(
"Muon is neither MuGirl / MuidCo / MuTagIMO - fail low-pT");
733 ATH_MSG_VERBOSE(
"Not using MVA selection, failing low-pT selection due to medium requirement in forward region");
741 ATH_MSG_VERBOSE(
"Muon has out-of-bounds precision hits - fail low-pT");
749 uint nStationsCut = (std::abs(
mu.eta()) > 1.3 && std::abs(
mu.eta()) < 1.55) ? 2 : 1;
750 if (
summary.nprecisionLayers < nStationsCut) {
751 ATH_MSG_VERBOSE(
"number of precision layers = " << (
int)
summary.nprecisionLayers <<
" is lower than cut value " << nStationsCut
752 <<
" - fail low-pT");
760 ATH_MSG_VERBOSE(
"MuGirl muon is not confirmed by MuTagIMO - fail low-pT");
796 std::vector<const xAOD::MuonSegment*> segments_sorted;
797 segments_sorted.reserve(
mu.nMuonSegments());
799 for (
unsigned int i = 0;
i <
mu.nMuonSegments();
i++) {
800 if (!
mu.muonSegment(
i))
801 ATH_MSG_WARNING(
"The muon reports more segments than are available. Please report this to the muon software community!");
803 segments_sorted.push_back(
mu.muonSegment(
i));
806 std::sort(segments_sorted.begin(), segments_sorted.end(), chamberIndexCompare);
808 return segments_sorted;
814 ATH_MSG_VERBOSE(
"LowPt WP currently not supported for run3 if not in expert mode");
823 float momentumBalanceSig{-1}, CurvatureSig{-1}, energyLoss{-1}, muonSegmentDeltaEta{-1}, scatteringNeigbour{-1};
834 float seg1ChamberIdx{-1.}, seg2ChamberIdx{-1.}, middleHoles{-1.}, seg1NPrecisionHits{-1.}, seg1GlobalR{-1.}, seg1Chi2OverDoF{-1.};
839 ATH_MSG_WARNING(
"passedLowPtEfficiencyMVACut - found segment-tagged muon with no segments!");
841 seg1ChamberIdx = (!muonSegments.empty()) ? muonSegments[0]->chamberIndex() : -9;
842 seg2ChamberIdx = (muonSegments.size() > 1) ? muonSegments[1]->chamberIndex() : -9;
846 seg1NPrecisionHits = (!muonSegments.empty()) ? muonSegments[0]->nPrecisionHits() : -1;
847 seg1GlobalR = (!muonSegments.empty())
848 ? std::hypot(muonSegments[0]->
x(), muonSegments[0]->y(), muonSegments[0]->z())
850 seg1Chi2OverDoF = (!muonSegments.empty()) ? muonSegments[0]->
chiSquared() / muonSegments[0]->numberDoF() : -1;
859 std::vector<float> var_vector;
861 var_vector = {momentumBalanceSig, CurvatureSig, scatteringNeigbour, energyLoss,
862 middleHoles, muonSegmentDeltaEta, seg1ChamberIdx, seg2ChamberIdx};
864 if (std::abs(
mu.eta()) >= 1.3)
865 var_vector = {seg2ChamberIdx, seg1ChamberIdx, seg1NPrecisionHits, muonSegmentDeltaEta,
866 seg1GlobalR, seg1Chi2OverDoF, std::abs(CurvatureSig)};
868 var_vector = {seg1ChamberIdx, seg1NPrecisionHits, muonSegmentDeltaEta,
869 seg1GlobalR, seg1Chi2OverDoF, std::abs(CurvatureSig)};
884 if (std::abs(
mu.eta()) < 0.7)
886 else if (std::abs(
mu.eta()) < 1.3)
892 float BDTdiscriminant;
895 BDTdiscriminant = reader_MUID->EvaluateMVA(var_vector,
"BDTG");
897 BDTdiscriminant = reader_MUGIRL->EvaluateMVA(var_vector,
"BDTG");
899 BDTdiscriminant = reader_MUTAGIMO->EvaluateMVA(var_vector,
"BDT");
901 ATH_MSG_WARNING(
"Invalid author for low-pT MVA, failing selection...");
908 if (BDTdiscriminant > BDTcut) {
934 ATH_MSG_VERBOSE(
"Muon has out-of-bounds precision hits - fail high-pT");
954 ATH_MSG_VERBOSE(
"passedHighPtCuts - No MS track available for muon. Using combined track.");
955 MS_track =
mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
958 if (MS_track && CB_track) {
960 float phiMS = MS_track->
phi();
961 float etaCB = CB_track->
eta();
964 if (!
isRun3() && (std::abs(
etaMS) > 2.0 || std::abs(etaCB) > 2.0)) {
965 if (
summary.cscUnspoiledEtaHits == 0) {
972 if (!
isRun3() &&
mu.eta() < -1.899 && std::abs(
mu.phi()) < 0.211) {
973 ATH_MSG_VERBOSE(
"Muon is in eta/phi region vetoed due to disabled chambers in MC - fail high-pT");
978 if ((1.01 < std::abs(
etaMS) && std::abs(
etaMS) < 1.1) || (1.01 < std::abs(etaCB) && std::abs(etaCB) < 1.1)) {
979 ATH_MSG_VERBOSE(
"Muon is in barrel/endcap overlap region - fail high-pT");
1009 if (
summary.nprecisionLayers < 4) {
1010 ATH_MSG_VERBOSE(
"Muon is in BEE eta/phi region and does not have 4 precision layers - fail high-pT");
1014 if (std::abs(etaCB) > 1.4) {
1018 if (
summary.nprecisionLayers < 4 && (
summary.extendedSmallHits > 0 ||
summary.extendedSmallHoles > 0)) {
1019 ATH_MSG_VERBOSE(
"Muon is in BEE eta/phi region and does not have 4 precision layers - fail high-pT");
1024 ATH_MSG_WARNING(
"passedHighPtCuts - MS or CB track missing in muon! Failing High-pT selection...");
1030 const xAOD::TrackParticle* metrack =
mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
1035 if (std::abs(qOverPsignif) > 7) {
1047 if (std::abs(
mu.eta()) > 1.2 &&
summary.extendedSmallHits < 3 &&
summary.extendedLargeHits < 3) {
1071 if (
summary.nprecisionLayers < 3) {
1072 ATH_MSG_VERBOSE(
"Muon has less than 3 precision layers - fail high-pT");
1077 if (
summary.isSmallGoodSectors) {
1078 if (!(
summary.innerSmallHits > 2 &&
summary.middleSmallHits > 2 &&
1079 (
summary.outerSmallHits > 2 ||
summary.extendedSmallHits > 2))) {
1080 ATH_MSG_VERBOSE(
"Muon has small/large sectors overlap - fail high-pT");
1084 if (!(
summary.innerLargeHits > 2 &&
summary.middleLargeHits > 2 &&
1085 (
summary.outerLargeHits > 2 ||
summary.extendedLargeHits > 2))) {
1086 ATH_MSG_VERBOSE(
"Muon has small/large sectors overlap - fail high-pT");
1099 double start_cut = 3.0;
1100 double end_cut = 1.6;
1101 double abs_eta = std::abs(
mu.eta());
1104 double p0(8.0),
p1(0.),
p2(0.);
1111 else if (abs_eta > 1.05 && abs_eta <= 1.3) {
1114 }
else if (abs_eta > 1.3 && abs_eta <= 1.7) {
1117 }
else if (abs_eta > 1.7 && abs_eta <= 2.0) {
1120 }
else if (abs_eta > 2.0) {
1131 else if (abs_eta > 1.05 && abs_eta <= 1.3) {
1134 }
else if (abs_eta > 1.3 && abs_eta <= 1.7) {
1137 }
else if (abs_eta > 1.7 && abs_eta <= 2.0) {
1140 }
else if (abs_eta > 2.0) {
1155 if (abs_eta > 1.05 && abs_eta < 1.3) {
1158 }
else if (abs_eta >= 1.3 && abs_eta < 1.7) {
1161 }
else if (abs_eta >= 1.7 && abs_eta < 2.0) {
1164 }
else if (abs_eta >= 2.0) {
1170 bool passErrorCutCB =
false;
1175 double qOverP_CB = cbtrack->
qOverP();
1181 double a = (end_cut - start_cut) / 4000.0;
1182 double b = end_cut -
a * 5000.0;
1183 double coefficient = (pt_CB > 1000.) ? (
a * pt_CB +
b) : start_cut;
1184 if (std::abs(qOverPerr_CB / qOverP_CB) < coefficient *
sigma) { passErrorCutCB =
true; }
1191 ATH_MSG_DEBUG(
"The current event is a MC event. Use bad muon veto mimic.");
1197 return passErrorCutCB;
1203 if (std::abs(
mu.eta()) < 1.05) {
1213 double qOpRelResolution = std::hypot(
p1,
p2 *
mu.primaryTrackParticle()->pt() *
MeVtoGeV);
1215 double qOverPabs_unsmeared = std::abs(
mu.primaryTrackParticle()->definingParameters()[4]);
1216 double qOverPabs_smeared = 1.0 / (
mu.pt() * std::cosh(
mu.eta()));
1218 if ((qOverPabs_smeared - qOverPabs_unsmeared) / (qOpRelResolution * qOverPabs_unsmeared) <
1219 cutFunction->Eval(
mu.primaryTrackParticle()->pt() *
MeVtoGeV))
1229 if (
mu.muonType() == xAOD::Muon::CaloTagged && std::abs(
mu.eta()) < 0.105)
1236 if (
mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon) {
1238 return (cbtrack && std::abs(cbtrack->
eta()) > 2.4);
1249 " !! Tool configured with some of the ID hits requirements changed... FOR DEVELOPMENT ONLY: muon efficiency SF won't be "
1254 if ((value1 + value2 == 0) && !
m_PixCutOff)
return false;
1258 if ((value1 + value2 <= 4) && !
m_SctCutOff)
return false;
1265 const float abseta = std::abs(
track.eta());
1268 const uint8_t totTRThits = value1 + value2;
1269 if (!((0.1 < abseta && abseta <= 1.9 && totTRThits > 5 && value2 < (0.9 * totTRThits)) || (abseta <= 0.1 || abseta > 1.9)))
1284 int CaloMuonIDTag = -20;
1287 bool readID =
mu.parameter(CaloMuonIDTag, xAOD::Muon::CaloMuonIDTag);
1289 ATH_MSG_WARNING(
"Unable to read CaloMuonIDTag Quality information! Rejecting the CALO muon!");
1294 return (CaloMuonIDTag > 10);
1302 float CaloMuonScore{-999.0};
1313 return (CaloMuonScore >= 0.77);
1329 ATH_MSG_VERBOSE(
"for run3, Tight WP is only supported when ExcludeNSWFromPrecisionLayers=False and RecalcPrecisionLayerswNSW=True");
1332 float symmetric_eta = std::abs(
mu.eta());
1336 if (pt < 4.0 || symmetric_eta >= 2.5)
return false;
1337 ATH_MSG_VERBOSE(
"Muon is passing tight WP kinematic cuts with pT,eta " <<
mu.pt() <<
" , " <<
mu.eta());
1344 ATH_MSG_VERBOSE(
"Applying tight WP cuts to a low pt muon with (pt,eta) ( " <<
pt <<
" , " <<
mu.eta() <<
" ) ");
1346 ATH_MSG_VERBOSE(
"Momentum significance value " << oneOverPSig <<
", required to be less than " << qOverPCut);
1348 if (
rho > rhoCut)
return false;
1351 if (oneOverPSig > qOverPCut)
return false;
1352 ATH_MSG_VERBOSE(
"Muon passed tight WP, low pT momentum significance cut");
1360 else if (
pt < 100.0) {
1363 ATH_MSG_VERBOSE(
"Applying tight WP cuts to a medium pt muon with (pt,eta) (" <<
pt <<
"," <<
mu.eta() <<
")");
1367 if (
rho > rhoCut)
return false;
1375 else if (
pt < 500.0) {
1377 ATH_MSG_VERBOSE(
"Applying tight WP cuts to a high pt muon with (pt,eta) (" <<
pt <<
"," <<
mu.eta() <<
")");
1380 ATH_MSG_VERBOSE(
"Rho value " <<
rho <<
", required to be less than " << rhoCut <<
" unless -1, in which no cut is applied");
1382 if (rhoCut < 0.0)
return true;
1383 if (
rho > rhoCut)
return false;
1390 ATH_MSG_VERBOSE(
"Not applying any tight WP cuts to a very high pt muon with (pt,eta) (" <<
pt <<
"," <<
mu.eta() <<
")");
1422 if (std::abs(
muon.eta()) > 2.0) {
1423 ATH_MSG_VERBOSE(
"Recalculating number of precision layers for combined muon");
1432 + (
summary.extendedSmallHits > 2 ||
summary.extendedLargeHits > 2);
1436 if (!eta1stgchits_acc.isAvailable(
muon) || !eta2stgchits_acc.isAvailable(
muon) || !mmhits_acc.isAvailable(
muon)) {
1437 ATH_MSG_FATAL(__FILE__ <<
":" << __LINE__ <<
" Failed to retrieve NSW hits!"
1438 <<
" (Please use DxAODs with p-tags >= p5834 OR set ExcludeNSWFromPrecisionLayers to True (tests only)");
1439 throw std::runtime_error(
"Failed to retrieve NSW hits");
1453 ATH_MSG_FATAL(__FILE__ <<
":" << __LINE__ <<
" Failed to retrieve parameter " << param
1454 <<
" for muon with pT:" <<
muon.pt() *
MeVtoGeV <<
", eta:" <<
muon.eta() <<
", phi: " <<
muon.phi()
1455 <<
", q:" <<
muon.charge() <<
", author: " <<
muon.author());
1456 throw std::runtime_error(
"Failed to retrieve Parameter");
1471 if (
summary.nprecisionLayers == 2)
1472 return ResolutionCategory::highPt2station;
1480 ATH_MSG_VERBOSE(
"getResolutionCategory - No MS track available for muon. Using combined track.");
1481 MS_track =
mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
1485 const float etaMS = MS_track->
eta();
1486 const float etaCB = CB_track->
eta();
1487 const float phiMS = MS_track->
phi();
1492 category = ResolutionCategory::missingInner;
1495 category = ResolutionCategory::missingMiddle;
1499 category = ResolutionCategory::missingOuter;
1501 if (!
isRun3() && (std::abs(
etaMS) > 2.0 || std::abs(etaCB) > 2.0) &&
summary.cscUnspoiledEtaHits == 0)
1502 category = ResolutionCategory::spoiledCSC;
1504 if ((1.01 < std::abs(
etaMS) && std::abs(
etaMS) < 1.1) || (1.01 < std::abs(etaCB) && std::abs(etaCB) < 1.1))
1505 category = ResolutionCategory::BEoverlap;
1510 if (
isBEE(
etaMS, phiMS) || (std::abs(etaCB) > 1.4 && (
summary.extendedSmallHits > 0 ||
summary.extendedSmallHoles > 0))) {
1512 category = ResolutionCategory::missingBEE;
1514 if (
summary.extendedSmallHits >= 3 &&
summary.outerSmallHits < 3)
category = ResolutionCategory::missingOuter;
1516 if (!
summary.isSmallGoodSectors)
1520 if (
summary.nprecisionLayers == 1)
category = ResolutionCategory::oneStation;
1535 ATH_MSG_DEBUG(
"The current event is a data event. Return runNumber.");
1541 static std::atomic<bool> issuedWarningPRW{
false};
1543 unsigned int rn = acc_rnd(*eventInfo);
1544 if (
rn != 0)
return acc_rnd(*eventInfo);
1546 if (!issuedWarningPRW) {
1548 issuedWarningPRW =
true;
1553 if (needOnlyCorrectYear) {
1555 ATH_MSG_DEBUG(
"Random run number not available and this is mc16a or mc20a, returning dummy 2016 run number.");
1558 }
else if (eventInfo->
runNumber() < 310000) {
1559 ATH_MSG_DEBUG(
"Random run number not available and this is mc16d or mc20d, returning dummy 2017 run number.");
1562 }
else if (eventInfo->
runNumber() < 320000) {
1563 ATH_MSG_DEBUG(
"Random run number not available and this is mc16e or mc20e, returning dummy 2018 run number.");
1566 }
else if (eventInfo->
runNumber() < 500000) {
1567 ATH_MSG_DEBUG(
"Random run number not available and this is mc21/mc23, for the time being we're returing a dummy run number.");
1574 ATH_MSG_FATAL(
"Random run number not available, fallback option of using runNumber failed since "<<eventInfo->
runNumber()<<
" cannot be recognised");
1575 throw std::runtime_error(
"MuonSelectionTool() - need RandomRunNumber decoration by the PileupReweightingTool");
1578 ATH_MSG_FATAL(
"Failed to find the RandomRunNumber decoration by the PileupReweightingTool");
1579 throw std::runtime_error(
"MuonSelectionTool() - need RandomRunNumber decoration from PileupReweightingTool");
1585 static constexpr std::array<float, 2> BIS78_eta{1.05, 1.3};
1586 static constexpr std::array<float, 8> BIS78_phi{0.21, 0.57, 1.00, 1.33, 1.78, 2.14, 2.57, 2.93};
1588 float abs_eta = std::abs(eta);
1589 float abs_phi = std::abs(
phi);
1591 if (abs_eta >= BIS78_eta[0] && abs_eta <= BIS78_eta[1]) {
1592 if ((abs_phi >= BIS78_phi[0] && abs_phi <= BIS78_phi[1]) || (abs_phi >= BIS78_phi[2] && abs_phi <= BIS78_phi[3]) ||
1593 (abs_phi >= BIS78_phi[4] && abs_phi <= BIS78_phi[5]) || (abs_phi >= BIS78_phi[6] && abs_phi <= BIS78_phi[7])) {
1603 static constexpr std::array<float, 2> BEE_eta{1.440, 1.692};
1604 static constexpr std::array<float, 8> BEE_phi{0.301, 0.478, 1.086, 1.263, 1.872, 2.049, 2.657, 2.834};
1606 float abs_eta = std::abs(eta);
1607 float abs_phi = std::abs(
phi);
1609 if (abs_eta >= BEE_eta[0] && abs_eta <= BEE_eta[1]) {
1610 if ((abs_phi >= BEE_phi[0] && abs_phi <= BEE_phi[1]) || (abs_phi >= BEE_phi[2] && abs_phi <= BEE_phi[3]) ||
1611 (abs_phi >= BEE_phi[4] && abs_phi <= BEE_phi[5]) || (abs_phi >= BEE_phi[6] && abs_phi <= BEE_phi[7])) {
1621 static constexpr std::array<float, 6> BMG_eta{0.35, 0.47, 0.68, 0.80, 0.925, 1.04};
1622 static constexpr std::array<float, 4> BMG_phi{-1.93, -1.765, -1.38, -1.21};
1624 float abs_eta = std::abs(eta);
1626 if ((abs_eta >= BMG_eta[0] && abs_eta <= BMG_eta[1]) || (abs_eta >= BMG_eta[2] && abs_eta <= BMG_eta[3]) ||
1627 (abs_eta >= BMG_eta[4] && abs_eta <= BMG_eta[5])) {
1628 if ((
phi >= BMG_phi[0] &&
phi <= BMG_phi[1]) || (
phi >= BMG_phi[2] &&
phi <= BMG_phi[3])) {
return true; }