ATLAS Offline Software
MuonSelectionTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
10 #include "CxxUtils/trapping_fp.h"
11 
12 namespace {
13  static constexpr double const MeVtoGeV = 1. / 1000.;
14 
15  // This function defines the order of chamber indices for the low-pT MVA,
16  // i.e. defining the meaning of "the first two segments", which are used in the BDT
17  std::vector<int> initializeChamberIdxOrder() {
18  // This vector defines the order. The current order follows the order of the enum "ChIndex"
19  // except for the CSCs, which appear first. Since the order is not strictly innermost-to-outermost,
20  // a reordering could be considered for a rel. 22 retuning, which can then easily be achieved by
21  // swapping around the elements in the below initialization.
22  const std::vector<int> chamberIndicesOrdered = {
28 
29  // This vector will hold the equivalent information in a form that can be efficiently accessed in the
30  // below function "chamberIndexCompare", using the chamber index as the vector index
31  std::vector<int> chamberIndexOrder(Muon::MuonStationIndex::ChIndexMax);
32 
33  for (unsigned int i = 0; i < chamberIndicesOrdered.size(); i++) chamberIndexOrder[chamberIndicesOrdered[i]] = i;
34 
35  return chamberIndexOrder;
36  }
37 
38  // This is the comparison function for the sorting of segments according to the chamber index
39  bool chamberIndexCompare(const xAOD::MuonSegment* first, const xAOD::MuonSegment* second) {
40  static const std::vector<int> chamberIndexOrder = initializeChamberIdxOrder();
41 
42  return (chamberIndexOrder[first->chamberIndex()] < chamberIndexOrder[second->chamberIndex()]);
43  }
44 
45  static const SG::AuxElement::Accessor<float> mePt_acc("MuonSpectrometerPt");
46  static const SG::AuxElement::Accessor<float> idPt_acc("InnerDetectorPt");
47  static const SG::AuxElement::Accessor<uint8_t> eta1stgchits_acc("etaLayer1STGCHits");
48  static const SG::AuxElement::Accessor<uint8_t> eta2stgchits_acc("etaLayer2STGCHits");
49  static const SG::AuxElement::Accessor<uint8_t> mmhits_acc("MMHits");
50 } // namespace
51 
52 namespace CP {
53 
54  MuonSelectionTool::MuonSelectionTool(const std::string& tool_name) : asg::AsgTool(tool_name), m_acceptInfo("MuonSelection"){}
55 
57 
59 
60  // Greet the user:
61  ATH_MSG_INFO("Initialising...");
62 
63  m_geoOnTheFly ? ATH_MSG_INFO("Is Run-3 geometry: On-the-fly determination")
64  : ATH_MSG_INFO("Is Run-3 geometry: " << m_isRun3.value());
65  ATH_MSG_INFO("Maximum muon |eta|: " << m_maxEta.value());
66  ATH_MSG_INFO("Muon quality: "<< m_quality.value());
67  if (m_toroidOff) ATH_MSG_INFO("!! CONFIGURED FOR TOROID-OFF COLLISIONS !!");
68  if (m_SctCutOff) ATH_MSG_WARNING("!! SWITCHING SCT REQUIREMENTS OFF !! FOR DEVELOPMENT USE ONLY !!");
69  if (m_PixCutOff) ATH_MSG_WARNING("!! SWITCHING PIXEL REQUIREMENTS OFF !! FOR DEVELOPMENT USE ONLY !!");
70  if (m_SiHolesCutOff) ATH_MSG_WARNING("!! SWITCHING SILICON HOLES REQUIREMENTS OFF !! FOR DEVELOPMENT USE ONLY !!");
71  if (m_custom_dir != "")
72  ATH_MSG_WARNING("!! SETTING UP WITH USER SPECIFIED INPUT LOCATION \"" << m_custom_dir << "\"!! FOR DEVELOPMENT USE ONLY !! ");
73  if (!m_useAllAuthors)
75  "Not using allAuthors variable as currently missing in many derivations; LowPtEfficiency working point will always return "
76  "false, but this is expected at the moment. Have a look here: "
77  "https://twiki.cern.ch/twiki/bin/view/Atlas/MuonSelectionToolR21#New_LowPtEfficiency_working_poin");
78 
79  // Print message to ensure that users excluding 2-station muons in the high-pT selection are aware of this
81  ATH_MSG_INFO("You have opted to select only 3-station muons in the high-pT selection! "
82  << "Please feed 'HighPt3Layers' to the 'WorkingPoint' property to retrieve the appropriate scale-factors");
83 
84  // Only an MVA-based selection is defined for segment-tagged muons for the Low-pT working point
86  ATH_MSG_WARNING("No cut-based selection is defined for segment-tagged muons in the Low-pT working point. "
87  << "Please set UseMVALowPt=true if you want to try the UseSegmentTaggedLowPt=true option.");
89  }
90  if (m_useLRT) {
91  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).");
92  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.");
93  }
94 
95  // Set up the TAccept object:
96  m_acceptInfo.addCut("Eta", "Selection of muons according to their pseudorapidity");
97  m_acceptInfo.addCut("IDHits", "Selection of muons according to whether they passed the MCP ID Hit cuts");
98  m_acceptInfo.addCut("Preselection", "Selection of muons according to their type/author");
99  m_acceptInfo.addCut("Quality", "Selection of muons according to their tightness");
100  // Sanity check
101  if (m_quality > 5) {
103  "Invalid quality (i.e. selection WP) set: "
104  << m_quality
105  << " - it must be an integer between 0 and 5! (0=Tight, 1=Medium, 2=Loose, 3=Veryloose, 4=HighPt, 5=LowPtEfficiency)");
106  return StatusCode::FAILURE;
107  }
108  if (m_quality == 5 && !m_useAllAuthors) {
109  ATH_MSG_ERROR("Cannot use lowPt working point if allAuthors is not available!");
110  return StatusCode::FAILURE;
111  }
112 
113  if(m_caloScoreWP<1 || m_caloScoreWP>4){
114  ATH_MSG_FATAL("CaloScoreWP property must be set to 1, 2, 3 or 4");
115  return StatusCode::FAILURE;
116  }
117 
118  // Load Tight WP cut-map
119  ATH_MSG_INFO("Initialising tight working point histograms...");
120  std::string tightWP_rootFile_fullPath;
121  if (!m_custom_dir.empty()) {
122  tightWP_rootFile_fullPath = PathResolverFindCalibFile(m_custom_dir + "/muonSelection_tightWPHisto.root");
123  } else {
124  tightWP_rootFile_fullPath = PathResolverFindCalibFile(
125  Form("MuonSelectorTools/%s/muonSelection_tightWPHisto.root", m_calibration_version.value().c_str()));
126  }
127 
128  ATH_MSG_INFO("Reading muon tight working point histograms from " << tightWP_rootFile_fullPath);
129  //
130  std::unique_ptr<TFile> file(TFile::Open(tightWP_rootFile_fullPath.c_str(), "READ"));
131 
132  if (!file->IsOpen()) {
133  ATH_MSG_ERROR("Cannot read tight working point file from " << tightWP_rootFile_fullPath);
134  return StatusCode::FAILURE;
135  }
136 
137  // Retrieve all the relevant histograms
138  ATH_CHECK(getHist(file.get(), "tightWP_lowPt_rhoCuts", m_tightWP_lowPt_rhoCuts));
139  ATH_CHECK(getHist(file.get(), "tightWP_lowPt_qOverPCuts", m_tightWP_lowPt_qOverPCuts));
140  ATH_CHECK(getHist(file.get(), "tightWP_mediumPt_rhoCuts", m_tightWP_mediumPt_rhoCuts));
141  ATH_CHECK(getHist(file.get(), "tightWP_highPt_rhoCuts", m_tightWP_highPt_rhoCuts));
142  //
143  file->Close();
144 
145  // Read bad muon veto efficiency histograms
146  std::string BMVcutFile_fullPath = PathResolverFindCalibFile(m_BMVcutFile);
147 
148  ATH_MSG_INFO("Reading bad muon veto cut functions from " << BMVcutFile_fullPath);
149  //
150  std::unique_ptr<TFile> BMVfile(TFile::Open(BMVcutFile_fullPath.c_str(), "READ"));
151 
152  if (!BMVfile->IsOpen()) {
153  ATH_MSG_ERROR("Cannot read bad muon veto cut function file from " << BMVcutFile_fullPath);
154  return StatusCode::FAILURE;
155  }
156 
157  m_BMVcutFunction_barrel = std::unique_ptr<TF1>((TF1*)BMVfile->Get("BMVcutFunction_barrel"));
158  m_BMVcutFunction_endcap = std::unique_ptr<TF1>((TF1*)BMVfile->Get("BMVcutFunction_endcap"));
159 
160  BMVfile->Close();
161 
163  ATH_MSG_ERROR("Cannot read bad muon veto cut functions");
164  return StatusCode::FAILURE;
165  }
166 
167  if (m_useMVALowPt) {
168  // Set up TMVA readers for MVA-based low-pT working point
169  // E and O refer to even and odd event numbers to avoid applying the MVA on events used for training
170  TString weightPath_EVEN_MuidCB = PathResolverFindCalibFile(m_MVAreaderFile_EVEN_MuidCB);
171  TString weightPath_ODD_MuidCB = PathResolverFindCalibFile(m_MVAreaderFile_ODD_MuidCB);
172  TString weightPath_EVEN_MuGirl = PathResolverFindCalibFile(m_MVAreaderFile_EVEN_MuGirl);
173  TString weightPath_ODD_MuGirl = PathResolverFindCalibFile(m_MVAreaderFile_ODD_MuGirl);
174 
175  auto make_mva_reader = [](TString file_path) {
176  std::vector<std::string> mva_var_names{"momentumBalanceSignificance",
177  "scatteringCurvatureSignificance",
178  "scatteringNeighbourSignificance",
179  "EnergyLoss",
180  "middleLargeHoles+middleSmallHoles",
181  "muonSegmentDeltaEta",
182  "muonSeg1ChamberIdx",
183  "muonSeg2ChamberIdx"};
184  std::unique_ptr<TMVA::Reader> reader = std::make_unique<TMVA::Reader>(mva_var_names);
185  reader->BookMVA("BDTG", file_path);
186  return reader;
187  };
188  m_readerE_MUID = make_mva_reader(weightPath_EVEN_MuidCB);
189 
190  m_readerO_MUID = make_mva_reader(weightPath_ODD_MuidCB);
191 
192  m_readerE_MUGIRL = make_mva_reader(weightPath_EVEN_MuGirl);
193 
194  m_readerO_MUGIRL = make_mva_reader(weightPath_ODD_MuGirl);
195 
197  TString weightPath_MuTagIMO_etaBin1 = PathResolverFindCalibFile(m_MVAreaderFile_MuTagIMO_etaBin1);
198  TString weightPath_MuTagIMO_etaBin2 = PathResolverFindCalibFile(m_MVAreaderFile_MuTagIMO_etaBin2);
199  TString weightPath_MuTagIMO_etaBin3 = PathResolverFindCalibFile(m_MVAreaderFile_MuTagIMO_etaBin3);
200 
201  auto make_mva_reader_MuTagIMO = [](TString file_path, bool useSeg2ChamberIndex) {
202  std::vector<std::string> mva_var_names;
203  if (useSeg2ChamberIndex) mva_var_names.push_back("muonSeg2ChamberIndex");
204  mva_var_names.push_back("muonSeg1ChamberIndex");
205  mva_var_names.push_back("muonSeg1NPrecisionHits");
206  mva_var_names.push_back("muonSegmentDeltaEta");
207  mva_var_names.push_back("muonSeg1GlobalR");
208  mva_var_names.push_back("muonSeg1Chi2OverDoF");
209  mva_var_names.push_back("muonSCS");
210 
211  std::unique_ptr<TMVA::Reader> reader = std::make_unique<TMVA::Reader>(mva_var_names);
212  reader->BookMVA("BDT", file_path);
213  return reader;
214  };
215 
216  m_reader_MUTAGIMO_etaBin1 = make_mva_reader_MuTagIMO(weightPath_MuTagIMO_etaBin1, false);
217  m_reader_MUTAGIMO_etaBin2 = make_mva_reader_MuTagIMO(weightPath_MuTagIMO_etaBin2, false);
218  m_reader_MUTAGIMO_etaBin3 = make_mva_reader_MuTagIMO(weightPath_MuTagIMO_etaBin3, true);
219  }
220  }
222 
223  // Return gracefully:
224  return StatusCode::SUCCESS;
225  }
226 
227  StatusCode MuonSelectionTool::getHist(TFile* file, const std::string& histName, std::unique_ptr<TH1>& hist) const {
228  //
229  if (!file) {
230  ATH_MSG_ERROR(" getHist(...) TFile is nullptr! Check that the Tight cut map is loaded correctly");
231  return StatusCode::FAILURE;
232  }
233  TH1* h_ptr = nullptr;
234  file->GetObject(histName.c_str(), h_ptr);
235  //
236  //
237  if (!h_ptr) {
238  ATH_MSG_ERROR("Cannot retrieve histogram " << histName);
239  return StatusCode::FAILURE;
240  }
241  hist = std::unique_ptr<TH1>{h_ptr};
242  hist->SetDirectory(nullptr);
243  ATH_MSG_INFO("Successfully read tight working point histogram: " << hist->GetName());
244  //
245  return StatusCode::SUCCESS;
246  }
247 
249 
251  // Check if this is a muon:
252  if (p->type() != xAOD::Type::Muon) {
253  ATH_MSG_ERROR("accept(...) Function received a non-muon");
254  return asg::AcceptData(&m_acceptInfo);
255  }
256 
257  // Cast it to a muon:
258  const xAOD::Muon* mu = dynamic_cast<const xAOD::Muon*>(p);
259  if (!mu) {
260  ATH_MSG_FATAL("accept(...) Failed to cast particle to muon");
261  return asg::AcceptData(&m_acceptInfo);
262  }
263 
264  // Let the specific function do the work:
265  return accept(*mu);
266  }
267 
268  //============================================================================
270 
271  static std::atomic<bool> checkDone{false};
272 
273  if(!checkDone) {
274  // Check that the user either set the correct geometry or enabled on-the-fly determination
275  // This can happen intentionally in developer mode. In any case don't throw an exception
276  // (we should either trust the user or ignore in the first place and force on-the-fly determination).
277  if (isRun3() != isRun3(true)) {
278  ATH_MSG_WARNING("MuonSelectionTool is configured with isRun3Geo="<<isRun3()
279  <<" while on-the fly check for runNumber "<<getRunNumber(true)<<" indicates isRun3Geo="<<isRun3(true));
280  }
281 
282  // Check that the requested WP is currently supported by the MCP group.
283  if (isRun3()) {
284  if(m_quality!=0 && m_quality!=1 && m_quality!=2 && m_quality!=4) {
285  ATH_MSG_WARNING("MuonSelectionTool currently supports Loose, Medium, Tight and HighPt WPs for Run3; all other WPs can only be used in ExpertDevelopMode mode");
286  }
287 
289  ATH_MSG_WARNING("For Run3, Tight WP is supported only when ExcludeNSWFromPrecisionLayers=False and RecalcPrecisionLayerswNSW=True");
290  }
291  }
292 
293  checkDone = true;
294  }
295  }
296 
297  //============================================================================
299  // Verbose information
300  ATH_MSG_VERBOSE("-----------------------------------");
301  ATH_MSG_VERBOSE("New muon passed to accept function:");
302  if (mu.muonType() == xAOD::Muon::Combined)
303  ATH_MSG_VERBOSE("Muon type: combined");
304  else if (mu.muonType() == xAOD::Muon::MuonStandAlone)
305  ATH_MSG_VERBOSE("Muon type: stand-alone");
306  else if (mu.muonType() == xAOD::Muon::SegmentTagged)
307  ATH_MSG_VERBOSE("Muon type: segment-tagged");
308  else if (mu.muonType() == xAOD::Muon::CaloTagged)
309  ATH_MSG_VERBOSE("Muon type: calorimeter-tagged");
310  else if (mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon)
311  ATH_MSG_VERBOSE("Muon type: silicon-associated forward");
312  ATH_MSG_VERBOSE("Muon pT [GeV]: " << mu.pt() * MeVtoGeV);
313  ATH_MSG_VERBOSE("Muon eta: " << mu.eta());
314  ATH_MSG_VERBOSE("Muon phi: " << mu.phi());
315 
316  checkSanity();
317 
318  asg::AcceptData acceptData(&m_acceptInfo);
319 
320  // Do the eta cut:
321  if (std::abs(mu.eta()) >= m_maxEta) {
322  ATH_MSG_VERBOSE("Failed eta cut");
323  return acceptData;
324  }
325  acceptData.setCutResult("Eta", true);
326 
327  // Passes ID hit cuts
328  bool passIDCuts = passedIDCuts(mu);
329  ATH_MSG_VERBOSE("Passes ID Hit cuts " << passIDCuts);
330  acceptData.setCutResult("IDHits", passIDCuts);
331 
332  // passes muon preselection
333  bool passMuonCuts = passedMuonCuts(mu);
334  ATH_MSG_VERBOSE("Passes preselection cuts " << passMuonCuts);
335  acceptData.setCutResult("Preselection", passMuonCuts);
336 
337  if (!passIDCuts || !passMuonCuts) { return acceptData; }
338 
339  // Passes quality requirements
340  xAOD::Muon::Quality thisMu_quality = getQuality(mu);
341  bool thisMu_highpt = false;
342  thisMu_highpt = passedHighPtCuts(mu);
343  bool thisMu_lowptE = false;
344  thisMu_lowptE = passedLowPtEfficiencyCuts(mu, thisMu_quality);
345  ATH_MSG_VERBOSE("Summary of quality information for this muon: ");
346  ATH_MSG_VERBOSE("Muon quality: " << thisMu_quality << " passes HighPt: " << thisMu_highpt
347  << " passes LowPtEfficiency: " << thisMu_lowptE);
348  if (m_quality < 4 && thisMu_quality > m_quality) { return acceptData; }
349  if (m_quality == 4 && !thisMu_highpt) { return acceptData; }
350  if (m_quality == 5 && !thisMu_lowptE) { return acceptData; }
351  acceptData.setCutResult("Quality", true);
352  // Return the result:
353  return acceptData;
354  }
355 
357  mu.setQuality(getQuality(mu));
358  return;
359  }
360  void MuonSelectionTool::IdMsPt(const xAOD::Muon& mu, float& idPt, float& mePt) const {
361  const xAOD::TrackParticle* idtrack = mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
362  const xAOD::TrackParticle* metrack = mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
363  if (!idtrack || !metrack) idPt = mePt = -1.;
364  else if (m_turnOffMomCorr) {
365  mePt = metrack->pt();
366  idPt = idtrack->pt();
367  } else {
368  if (!mePt_acc.isAvailable(mu) || !idPt_acc.isAvailable(mu)) {
369  ATH_MSG_FATAL("The muon with pT " << mu.pt() * MeVtoGeV << " eta: " << mu.eta() << ", phi:" << mu.phi()
370  << " q:" << mu.charge() << ", author:" << mu.author()
371  << " is not decorated with calibrated momenta. Please fix");
372  throw std::runtime_error("MuonSelectionTool() - qOverP significance calculation failed");
373  }
374  mePt = mePt_acc(mu);
375  idPt = idPt_acc(mu);
376  }
377  }
378 
380  // Avoid spurious FPEs in the clang build.
382 
383  if (m_disablePtCuts) {
384  ATH_MSG_VERBOSE(__FILE__ << ":"<<__LINE__
385  << " Momentum dependent cuts are disabled. Return 0.");
386  return 0.;
387  }
388  const xAOD::TrackParticle* idtrack = muon.trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
389  const xAOD::TrackParticle* metrack = muon.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
390  if (!idtrack || !metrack) {
391  ATH_MSG_VERBOSE("No ID / MS track. Return dummy large value of 1 mio");
392  return 1.e6;
393  }
394  float mePt{-1.}, idPt{-1.};
395  IdMsPt(muon, idPt, mePt);
396 
397  const float meP = mePt / std::sin(metrack->theta());
398  const float idP = idPt / std::sin(idtrack->theta());
399 
400  float qOverPsigma = std::sqrt(idtrack->definingParametersCovMatrix()(4, 4) + metrack->definingParametersCovMatrix()(4, 4));
401  return std::abs((metrack->charge() / meP) - (idtrack->charge() / idP)) / qOverPsigma;
402  }
404  if (m_disablePtCuts) {
405  ATH_MSG_VERBOSE(__FILE__ << ":"<<__LINE__
406  << "Momentum dependent cuts are disabled. Return 0.");
407  return 0.;
408  }
409  float mePt{-1.}, idPt{-1.};
410  IdMsPt(muon, idPt, mePt);
411  return std::abs(idPt - mePt) / muon.pt();
412  }
413 
414  xAOD::Muon::Quality MuonSelectionTool::getQuality(const xAOD::Muon& mu) const {
415  ATH_MSG_VERBOSE("Evaluating muon quality...");
416  static const std::set<int> run3_qual{xAOD::Muon::Loose, xAOD::Muon::Medium, xAOD::Muon::Tight, 4};
417  //currently allow only tight, medium, loose and highpt when not in expert mode for run3
418  if(isRun3() && !m_developMode && !run3_qual.count(m_quality))
419  {
420  ATH_MSG_VERBOSE("tool configured with quality="<<m_quality<<" which is currently only supported in expert mode for run3");
421  return xAOD::Muon::VeryLoose;
422  }
423  if (isRun3() && mu.isAuthor(xAOD::Muon::Author::Commissioning) && !m_allowComm) {
424  ATH_MSG_VERBOSE("Reject authors from the commissioning chain");
425  return xAOD::Muon::VeryLoose;
426  }
427 
428  // SegmentTagged muons
429  if (mu.muonType() == xAOD::Muon::SegmentTagged) {
430  ATH_MSG_VERBOSE("Muon is segment-tagged");
431 
432  if (std::abs(mu.eta()) < 0.1) {
433  ATH_MSG_VERBOSE("Muon is loose");
434  return xAOD::Muon::Loose;
435  } else {
436  ATH_MSG_VERBOSE("Do not allow segment-tagged muon at |eta| > 0.1 - return VeryLoose");
437  return xAOD::Muon::VeryLoose;
438  }
439  }
440 
441  // CaloTagged muons
442  if (mu.muonType() == xAOD::Muon::CaloTagged) {
443  ATH_MSG_VERBOSE("Muon is calorimeter-tagged");
444 
445  if (std::abs(mu.eta()) < 0.1 && passedCaloTagQuality(mu)) {
446  ATH_MSG_VERBOSE("Muon is loose");
447  return xAOD::Muon::Loose;
448  }
449  }
450 
451  // Combined muons
454 
455  if (mu.muonType() == xAOD::Muon::Combined) {
456  ATH_MSG_VERBOSE("Muon is combined");
457  if (mu.author() == xAOD::Muon::STACO) {
458  ATH_MSG_VERBOSE("Muon is STACO - return VeryLoose");
459  return xAOD::Muon::VeryLoose;
460  }
461 
462  // rejection muons with out-of-bounds hits
465 
467  ATH_MSG_VERBOSE("Muon has out-of-bounds precision hits - return VeryLoose");
468  return xAOD::Muon::VeryLoose;
469  }
470 
471  // LOOSE / MEDIUM / TIGHT WP
472  const xAOD::TrackParticle* idtrack = mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
473  const xAOD::TrackParticle* metrack = mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
474  if (idtrack && metrack && metrack->definingParametersCovMatrix()(4, 4) > 0) {
475  const float qOverPsignif = qOverPsignificance(mu);
476  const float rho = rhoPrime(mu);
477  const float reducedChi2 = mu.primaryTrackParticle()->chiSquared() / mu.primaryTrackParticle()->numberDoF();
478 
479  ATH_MSG_VERBOSE("Relevant cut variables:");
480  ATH_MSG_VERBOSE("number of precision layers = " << (int)summary.nprecisionLayers);
481  ATH_MSG_VERBOSE("reduced Chi2 = " << reducedChi2);
482  ATH_MSG_VERBOSE("qOverP significance = " << qOverPsignif);
483 
484  // NEW TIGHT WP
485  if (summary.nprecisionLayers > 1 && reducedChi2 < 8 && std::abs(qOverPsignif) < 7) {
486  if (passTight(mu, rho, qOverPsignif)) {
487  ATH_MSG_VERBOSE("Muon is tight");
488  return xAOD::Muon::Tight;
489  }
490  }
491 
492  ATH_MSG_VERBOSE("Muon did not pass requirements for tight combined muon");
493 
494  // MEDIUM WP
495  if ((std::abs(qOverPsignif) < 7 || m_toroidOff) &&
496  (summary.nprecisionLayers > 1 ||(summary.nprecisionLayers == 1 && summary.nprecisionHoleLayers < 2 && std::abs(mu.eta()) < 0.1))
497 
498  ) {
499  ATH_MSG_VERBOSE("Muon is medium");
500  return xAOD::Muon::Medium;
501  }
502 
503  ATH_MSG_VERBOSE("Muon did not pass requirements for medium combined muon");
504 
505  } else {
506  ATH_MSG_VERBOSE("Muon is missing the ID and/or ME tracks...");
507 
508  // CB muons with missing ID or ME track
509  if ((summary.nprecisionLayers > 1 ||
510  (summary.nprecisionLayers == 1 && summary.nprecisionHoleLayers < 2 && std::abs(mu.eta()) < 0.1))) {
511  // In toroid-off data ME/MS tracks often missing - need special treatment => flagging as "Medium"
512  // In toroid-on data ME/MS tracks missing only for <1% of CB muons, mostly MuGirl (to be fixed) => flagging as "Loose"
513  if (m_toroidOff) {
514  ATH_MSG_VERBOSE("...this is toroid-off data - returning medium");
515  return xAOD::Muon::Medium;
516  } else {
517  ATH_MSG_VERBOSE("...this is not toroid-off data - returning loose");
518  return xAOD::Muon::Loose;
519  }
520  }
521  }
522 
523  // Improvement for Loose targeting low-pT muons (pt<7 GeV)
524  if ((m_disablePtCuts || mu.pt() * MeVtoGeV < 7.) && std::abs(mu.eta()) < 1.3 && summary.nprecisionLayers > 0 &&
525  (mu.author() == xAOD::Muon::MuGirl && mu.isAuthor(xAOD::Muon::MuTagIMO))) {
526  ATH_MSG_VERBOSE("Muon passed selection for loose working point at low pT");
527  return xAOD::Muon::Loose;
528  }
529 
530  // didn't pass the set of requirements for a medium or tight combined muon
531  ATH_MSG_VERBOSE("Did not pass selections for combined muon - returning VeryLoose");
532  return xAOD::Muon::VeryLoose;
533  }
534 
535  // SA muons
536  if (mu.author() == xAOD::Muon::MuidSA) {
537  ATH_MSG_VERBOSE("Muon is stand-alone");
538 
539  if(isRun3() && !m_developMode){
540  ATH_MSG_VERBOSE("Standalone muons currently only used when in expert mode for run3");
541  return xAOD::Muon::VeryLoose; //SA muons currently disabled for run3
542  }
543 
544  if (std::abs(mu.eta()) > 2.5) {
545  ATH_MSG_VERBOSE("number of precision layers = " << (int)summary.nprecisionLayers);
546 
547  // 3 station requirement for medium
548  if (summary.nprecisionLayers > 2 && !m_toroidOff) {
549  ATH_MSG_VERBOSE("Muon is medium");
550  return xAOD::Muon::Medium;
551  }
552  }
553 
554  // didn't pass the set of requirements for a medium SA muon
555  ATH_MSG_VERBOSE("Muon did not pass selection for medium stand-alone muon - return VeryLoose");
556  return xAOD::Muon::VeryLoose;
557  }
558 
559  // SiliconAssociatedForward (SAF) muons
560  if (mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon) {
561  ATH_MSG_VERBOSE("Muon is silicon-associated forward muon");
562 
563  if(isRun3() && !m_developMode){
564  ATH_MSG_VERBOSE("Silicon-associated forward muon muons currently only used when in expert mode for run3");
565  return xAOD::Muon::VeryLoose; //SAF muons currently disabled for run3
566  }
567 
568  const xAOD::TrackParticle* cbtrack = mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
569  const xAOD::TrackParticle* metrack = mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
570 
571  if (cbtrack && metrack) {
572  if (std::abs(cbtrack->eta()) > 2.5) {
573  ATH_MSG_VERBOSE("number of precision layers = " << (int)summary.nprecisionLayers);
574 
575  if (summary.nprecisionLayers > 2 && !m_toroidOff) {
576  if (mu.trackParticle(xAOD::Muon::Primary) == mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle) &&
577  !m_developMode) {
579  "SiliconForwardAssociated muon has ID track as primary track particle. "
580  << "This is a bug fixed starting with xAODMuon-00-17-07, which should be present in this release. "
581  << "Please report this to the Muon CP group!");
582  }
583  ATH_MSG_VERBOSE("Muon is medium");
584  return xAOD::Muon::Medium;
585  }
586  }
587  }
588 
589  // didn't pass the set of requirements for a medium SAF muon
590  ATH_MSG_VERBOSE("Muon did not pass selection for medium silicon-associated forward muon - return VeryLoose");
591  return xAOD::Muon::VeryLoose;
592  }
593 
594  ATH_MSG_VERBOSE("Muon did not pass selection for loose/medium/tight for any muon type - return VeryLoose");
595  return xAOD::Muon::VeryLoose;
596  }
597 
598  void MuonSelectionTool::setPassesIDCuts(xAOD::Muon& mu) const { mu.setPassesIDCuts(passedIDCuts(mu)); }
599 
601 
603  if (m_useLRT) {
604  static const SG::AuxElement::Accessor<char> isLRTmuon("isLRT");
605  if (isLRTmuon.isAvailable(mu)) {
606  if (isLRTmuon(mu)) return true;
607  }
608  else {
609  static const SG::AuxElement::Accessor<uint64_t> patternAcc("patternRecoInfo");
610  const xAOD::TrackParticle* idtrack = mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
611  if(idtrack) {
612  if(!patternAcc.isAvailable(*idtrack)) {
613  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.");
614  throw std::runtime_error("MuonSelectionTool() - isLRT decor and patternRecoInfo both unavailable for a muon.");
615  }
616  std::bitset<xAOD::NumberOfTrackRecoInfo> patternBitSet(patternAcc(*idtrack));
617  if (patternBitSet.test(xAOD::SiSpacePointsSeedMaker_LargeD0)) return true;
618  }
619  }
620  }
621  // do not apply the ID hit requirements for SA muons for |eta| > 2.5
622  if (mu.author() == xAOD::Muon::MuidSA && std::abs(mu.eta()) > 2.5) {
623  return true;
624  } else if (mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon) {
625  const xAOD::TrackParticle* cbtrack = mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
626  if (cbtrack && std::abs(cbtrack->eta()) > 2.5) { return true; }
627  return false;
628  } else {
629  if (mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle))
630  return passedIDCuts(*mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle));
631  else if (mu.primaryTrackParticle())
632  return passedIDCuts(*mu.primaryTrackParticle());
633  }
634  return false;
635  }
636 
638  if (mu.muonType() != xAOD::Muon::Combined) return false;
639  // ::
640  const xAOD::TrackParticle* idtrack = mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
641  const xAOD::TrackParticle* metrack = mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
642  const xAOD::TrackParticle* cbtrack = mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
643  // ::
644  // Some spurious muons are found to have negative ME track fit covariance, and are typically poorly reconstructed
645  if (metrack && metrack->definingParametersCovMatrix()(4, 4) < 0.0) return true;
646  // ::
647  bool IsBadMuon = false;
648  if (idtrack && metrack && cbtrack) {
649  // ::
650  double qOverP_ID = idtrack->qOverP();
651  double qOverPerr_ID = std::sqrt(idtrack->definingParametersCovMatrix()(4, 4));
652  double qOverP_ME = metrack->qOverP();
653  double qOverPerr_ME = std::sqrt(metrack->definingParametersCovMatrix()(4, 4));
654  double qOverP_CB = cbtrack->qOverP();
655  double qOverPerr_CB = std::sqrt(cbtrack->definingParametersCovMatrix()(4, 4));
656  // ::
657  if (m_quality == 4) {
658  // recipe for high-pt selection
659  IsBadMuon = !passedErrorCutCB(mu);
660 
663 
664  // temporarily apply same recipe as for other working points in addition to CB error
665  // cut for 2-station muons, pending better treatment of ID/MS misalignments
666  if (m_use2stationMuonsHighPt && summary.nprecisionLayers == 2) {
667  double IdCbRatio = std::abs((qOverPerr_ID / qOverP_ID) / (qOverPerr_CB / qOverP_CB));
668  double MeCbRatio = std::abs((qOverPerr_ME / qOverP_ME) / (qOverPerr_CB / qOverP_CB));
669  IsBadMuon = (IdCbRatio < 0.8 || MeCbRatio < 0.8 || IsBadMuon);
670  }
671  } else {
672  // recipe for other WP
673  double IdCbRatio = std::abs((qOverPerr_ID / qOverP_ID) / (qOverPerr_CB / qOverP_CB));
674  double MeCbRatio = std::abs((qOverPerr_ME / qOverP_ME) / (qOverPerr_CB / qOverP_CB));
675  IsBadMuon = (IdCbRatio < 0.8 || MeCbRatio < 0.8);
676  }
677  } else {
678  return true;
679  }
680  return IsBadMuon;
681  }
682 
684  xAOD::Muon::Quality thisMu_quality = getQuality(mu);
685  return passedLowPtEfficiencyCuts(mu, thisMu_quality);
686  }
687 
688  bool MuonSelectionTool::passedLowPtEfficiencyCuts(const xAOD::Muon& mu, xAOD::Muon::Quality thisMu_quality) const {
689  ATH_MSG_VERBOSE("Checking whether muon passes low-pT selection...");
690 
691  //LowPt Not supported in run3 for the time being
692  if(isRun3() && !m_developMode){
693  ATH_MSG_VERBOSE("LowPt WP currently not supported for run3 if not in expert mode");
694  return false;
695  }
696  if (!m_useAllAuthors) { // no allAuthors, always fail the WP
697  ATH_MSG_VERBOSE("Do not have allAuthors variable - fail low-pT");
698  return false;
699  }
700 
701  // requiring combined muons, unless segment-tags are included
703  if (mu.muonType() != xAOD::Muon::Combined) {
704  ATH_MSG_VERBOSE("Muon is not combined - fail low-pT");
705  return false;
706  }
707  } else {
708  if (mu.muonType() != xAOD::Muon::Combined && mu.muonType() != xAOD::Muon::SegmentTagged) {
709  ATH_MSG_VERBOSE("Muon is not combined or segment-tagged - fail low-pT");
710  return false;
711  }
712  }
713 
714  // author check
716  if (mu.author() != xAOD::Muon::MuGirl && mu.author() != xAOD::Muon::MuidCo) {
717  ATH_MSG_VERBOSE("Muon is neither MuGirl nor MuidCo - fail low-pT");
718  return false;
719  }
720  } else {
721  if (mu.author() != xAOD::Muon::MuGirl && mu.author() != xAOD::Muon::MuidCo && mu.author() != xAOD::Muon::MuTagIMO) {
722  ATH_MSG_VERBOSE("Muon is neither MuGirl / MuidCo / MuTagIMO - fail low-pT");
723  return false;
724  }
725  }
726 
727  // applying Medium selection above pT = 18 GeV
728  if (mu.pt() * MeVtoGeV > 18.) {
729  ATH_MSG_VERBOSE("pT > 18 GeV - apply medium selection");
730  if (thisMu_quality <= xAOD::Muon::Medium) {
731  ATH_MSG_VERBOSE("Muon passed low-pT selection");
732  return true;
733  } else {
734  ATH_MSG_VERBOSE("Muon failed low-pT selection");
735  return false;
736  }
737  }
738 
739  // requiring Medium in forward regions
740  if (!m_useMVALowPt && std::abs(mu.eta()) > 1.55 && thisMu_quality > xAOD::Muon::Medium) {
741  ATH_MSG_VERBOSE("Not using MVA selection, failing low-pT selection due to medium requirement in forward region");
742  return false;
743  }
744 
745  // rejection of muons with out-of-bounds hits
749  ATH_MSG_VERBOSE("Muon has out-of-bounds precision hits - fail low-pT");
750  return false;
751  }
752 
753  // requiring explicitely >=1 station (2 in the |eta|>1.3 region when Medium selection is not explicitely required)
754  if (mu.muonType() == xAOD::Muon::Combined) {
757  uint nStationsCut = (std::abs(mu.eta()) > 1.3 && std::abs(mu.eta()) < 1.55) ? 2 : 1;
758  if (summary.nprecisionLayers < nStationsCut) {
759  ATH_MSG_VERBOSE("number of precision layers = " << (int)summary.nprecisionLayers << " is lower than cut value " << nStationsCut
760  << " - fail low-pT");
761  return false;
762  }
763  }
764 
765  // reject MuGirl muon if not found also by MuTagIMO
766  if (m_useAllAuthors) {
767  if (mu.author() == xAOD::Muon::MuGirl && !mu.isAuthor(xAOD::Muon::MuTagIMO)) {
768  ATH_MSG_VERBOSE("MuGirl muon is not confirmed by MuTagIMO - fail low-pT");
769  return false;
770  }
771  } else
772  return false;
773 
774  if (m_useMVALowPt) {
775  ATH_MSG_VERBOSE("Applying MVA-based selection");
777  }
778 
779  ATH_MSG_VERBOSE("Applying cut-based selection");
780 
781  // apply some loose quality requirements
783 
787 
788  ATH_MSG_VERBOSE("momentum balance significance: " << momentumBalanceSignificance);
789  ATH_MSG_VERBOSE("scattering curvature significance: " << scatteringCurvatureSignificance);
790  ATH_MSG_VERBOSE("scattering neighbour significance: " << scatteringNeighbourSignificance);
791 
792  if (std::abs(momentumBalanceSignificance) > 3. || std::abs(scatteringCurvatureSignificance) > 3. ||
793  std::abs(scatteringNeighbourSignificance) > 3.) {
794  ATH_MSG_VERBOSE("Muon failed cut-based low-pT selection");
795  return false;
796  }
797 
798  // passed low pt selection
799  ATH_MSG_VERBOSE("Muon passed cut-based low-pT selection");
800  return true;
801  }
802 
803  std::vector<const xAOD::MuonSegment*> MuonSelectionTool::getSegmentsSorted(const xAOD::Muon& mu) const {
804  std::vector<const xAOD::MuonSegment*> segments_sorted;
805  segments_sorted.reserve(mu.nMuonSegments());
806 
807  for (unsigned int i = 0; i < mu.nMuonSegments(); i++) {
808  if (!mu.muonSegment(i))
809  ATH_MSG_WARNING("The muon reports more segments than are available. Please report this to the muon software community!");
810  else
811  segments_sorted.push_back(mu.muonSegment(i));
812  }
813 
814  std::sort(segments_sorted.begin(), segments_sorted.end(), chamberIndexCompare);
815 
816  return segments_sorted;
817  }
818 
820  //LowPt Not supported in run3 for the time being
821  if(isRun3() && !m_developMode){
822  ATH_MSG_VERBOSE("LowPt WP currently not supported for run3 if not in expert mode");
823  return false;
824  }
825  if (!m_useMVALowPt) {
826  ATH_MSG_DEBUG("Low pt MVA disabled. Return... ");
827  return false;
828  }
829  std::lock_guard<std::mutex> guard(m_low_pt_mva_mutex);
830  // set values for all BDT input variables from the muon in question
831  float momentumBalanceSig{-1}, CurvatureSig{-1}, energyLoss{-1}, muonSegmentDeltaEta{-1}, scatteringNeigbour{-1};
835  retrieveParam(mu, energyLoss, xAOD::Muon::EnergyLoss);
836  retrieveParam(mu, muonSegmentDeltaEta, xAOD::Muon::segmentDeltaEta);
837 
841 
842  float seg1ChamberIdx{-1.}, seg2ChamberIdx{-1.}, middleHoles{-1.}, seg1NPrecisionHits{-1.}, seg1GlobalR{-1.}, seg1Chi2OverDoF{-1.};
843 
844  std::vector<const xAOD::MuonSegment*> muonSegments = getSegmentsSorted(mu);
845 
846  if (mu.author() == xAOD::Muon::MuTagIMO && muonSegments.size() == 0)
847  ATH_MSG_WARNING("passedLowPtEfficiencyMVACut - found segment-tagged muon with no segments!");
848 
849  seg1ChamberIdx = (!muonSegments.empty()) ? muonSegments[0]->chamberIndex() : -9;
850  seg2ChamberIdx = (muonSegments.size() > 1) ? muonSegments[1]->chamberIndex() : -9;
851 
852  // these variables are only used for MuTagIMO
853  if (mu.author() == xAOD::Muon::MuTagIMO) {
854  seg1NPrecisionHits = (!muonSegments.empty()) ? muonSegments[0]->nPrecisionHits() : -1;
855  seg1GlobalR = (!muonSegments.empty())
856  ? std::hypot(muonSegments[0]->x(), muonSegments[0]->y(), muonSegments[0]->z())
857  : 0;
858  seg1Chi2OverDoF = (!muonSegments.empty()) ? muonSegments[0]->chiSquared() / muonSegments[0]->numberDoF() : -1;
859  }
860 
861  middleHoles = middleSmallHoles + middleLargeHoles;
862 
863  // get event number from event info
865 
866  // variables for the BDT
867  std::vector<float> var_vector;
868  if (mu.author() == xAOD::Muon::MuidCo || mu.author() == xAOD::Muon::MuGirl) {
869  var_vector = {momentumBalanceSig, CurvatureSig, scatteringNeigbour, energyLoss,
870  middleHoles, muonSegmentDeltaEta, seg1ChamberIdx, seg2ChamberIdx};
871  } else {
872  if (std::abs(mu.eta()) >= 1.3)
873  var_vector = {seg2ChamberIdx, seg1ChamberIdx, seg1NPrecisionHits, muonSegmentDeltaEta,
874  seg1GlobalR, seg1Chi2OverDoF, std::abs(CurvatureSig)};
875  else
876  var_vector = {seg1ChamberIdx, seg1NPrecisionHits, muonSegmentDeltaEta,
877  seg1GlobalR, seg1Chi2OverDoF, std::abs(CurvatureSig)};
878  }
879 
880  // use different trainings for even/odd numbered events
881  TMVA::Reader *reader_MUID, *reader_MUGIRL;
882  if (eventInfo->eventNumber() % 2 == 1) {
883  reader_MUID = m_readerE_MUID.get();
884  reader_MUGIRL = m_readerE_MUGIRL.get();
885  } else {
886  reader_MUID = m_readerO_MUID.get();
887  reader_MUGIRL = m_readerO_MUGIRL.get();
888  }
889 
890  // BDT for MuTagIMO is binned in |eta|
891  TMVA::Reader* reader_MUTAGIMO;
892  if (std::abs(mu.eta()) < 0.7)
893  reader_MUTAGIMO = m_reader_MUTAGIMO_etaBin1.get();
894  else if (std::abs(mu.eta()) < 1.3)
895  reader_MUTAGIMO = m_reader_MUTAGIMO_etaBin2.get();
896  else
897  reader_MUTAGIMO = m_reader_MUTAGIMO_etaBin3.get();
898 
899  // get the BDT discriminant response
900  float BDTdiscriminant;
901 
902  if (mu.author() == xAOD::Muon::MuidCo)
903  BDTdiscriminant = reader_MUID->EvaluateMVA(var_vector, "BDTG");
904  else if (mu.author() == xAOD::Muon::MuGirl)
905  BDTdiscriminant = reader_MUGIRL->EvaluateMVA(var_vector, "BDTG");
906  else if (mu.author() == xAOD::Muon::MuTagIMO && m_useSegmentTaggedLowPt)
907  BDTdiscriminant = reader_MUTAGIMO->EvaluateMVA(var_vector, "BDT");
908  else {
909  ATH_MSG_WARNING("Invalid author for low-pT MVA, failing selection...");
910  return false;
911  }
912 
913  // cut on dicriminant
914  float BDTcut = (mu.author() == xAOD::Muon::MuTagIMO) ? 0.12 : -0.6;
915 
916  if (BDTdiscriminant > BDTcut) {
917  ATH_MSG_VERBOSE("Passed low-pT MVA cut");
918  return true;
919  } else {
920  ATH_MSG_VERBOSE("Failed low-pT MVA cut");
921  return false;
922  }
923  }
924 
926  ATH_MSG_VERBOSE("Checking whether muon passes high-pT selection...");
927 
928  // :: Request combined muons
929  if (mu.muonType() != xAOD::Muon::Combined) {
930  ATH_MSG_VERBOSE("Muon is not combined - fail high-pT");
931  return false;
932  }
933  if (mu.author() == xAOD::Muon::STACO) {
934  ATH_MSG_VERBOSE("Muon is STACO - fail high-pT");
935  return false;
936  }
937 
938  // :: Reject muons with out-of-bounds hits
942  ATH_MSG_VERBOSE("Muon has out-of-bounds precision hits - fail high-pT");
943  return false;
944  }
945 
946  // :: Access MS hits information
949 
950 
951  ATH_MSG_VERBOSE("number of precision layers: " << (int)summary.nprecisionLayers);
952 
953  //::: Apply MS Chamber Vetoes
954  // Given according to their eta-phi locations in the muon spectrometer
955  // FORM: CHAMBERNAME[ array of four values ] = { eta 1, eta 2, phi 1, phi 2}
956  // The vetoes are applied based on the MS track if available. If the MS track is not available,
957  // the vetoes are applied according to the combined track, and runtime warning is printed to
958  // the command line.
959  const xAOD::TrackParticle* CB_track = mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
960  const xAOD::TrackParticle* MS_track = mu.trackParticle(xAOD::Muon::MuonSpectrometerTrackParticle);
961  if (!MS_track) {
962  ATH_MSG_VERBOSE("passedHighPtCuts - No MS track available for muon. Using combined track.");
963  MS_track = mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
964  }
965 
966  if (MS_track && CB_track) {
967  float etaMS = MS_track->eta();
968  float phiMS = MS_track->phi();
969  float etaCB = CB_track->eta();
970 
971  //::: no unspoiled clusters in CSC
972  if (!isRun3() && (std::abs(etaMS) > 2.0 || std::abs(etaCB) > 2.0)) {
973  if (summary.cscUnspoiledEtaHits == 0) {
974  ATH_MSG_VERBOSE("Muon has only spoiled CSC clusters - fail high-pT");
975  return false;
976  }
977  }
978 
979  // veto bad CSC giving troubles with scale factors
980  if (!isRun3() && mu.eta() < -1.899 && std::abs(mu.phi()) < 0.211) {
981  ATH_MSG_VERBOSE("Muon is in eta/phi region vetoed due to disabled chambers in MC - fail high-pT");
982  return false;
983  }
984 
985  //::: Barrel/Endcap overlap region
986  if ((1.01 < std::abs(etaMS) && std::abs(etaMS) < 1.1) || (1.01 < std::abs(etaCB) && std::abs(etaCB) < 1.1)) {
987  ATH_MSG_VERBOSE("Muon is in barrel/endcap overlap region - fail high-pT");
988  return false;
989  }
990 
991  //::: BIS78
992  if (isBIS78(etaMS, phiMS)) {
993  ATH_MSG_VERBOSE("Muon is in BIS7/8 eta/phi region - fail high-pT");
994  return false;
995  }
996 
999  //if (getRunNumber(true) >= 324320) {
1000  //if (isBMG(etaMS, phiMS)) {
1001  //ATH_MSG_VERBOSE("Muon is in BMG eta/phi region - fail high-pT");
1002  //return false;
1003  //}
1004  //}
1005 
1006  //::: BEE
1007  if (isBEE(etaMS, phiMS)) {
1008  // in Run3, large mis-alignment on the BEE chamber was found. temporarily mask the BEE region
1009  if (isRun3()) {
1010  ATH_MSG_VERBOSE("Muon is in BEE eta/phi region - fail high-pT");
1011  return false;
1012  }
1013  // Muon falls in the BEE eta-phi region: asking for 4 good precision layers
1014  // if( nGoodPrecLayers < 4 ) return false; // postponed (further studies needed)
1015  if (summary.nprecisionLayers < 4) {
1016  ATH_MSG_VERBOSE("Muon is in BEE eta/phi region and does not have 4 precision layers - fail high-pT");
1017  return false;
1018  }
1019  }
1020  if (std::abs(etaCB) > 1.4) {
1021  // Veto residual 3-station muons in BEE region due to MS eta/phi resolution effects
1022  // if( nGoodPrecLayers<4 && (extendedSmallHits>0||extendedSmallHoles>0) ) return false; // postponed (further studies
1023  // needed)
1024  if (summary.nprecisionLayers < 4 && (summary.extendedSmallHits > 0 || summary.extendedSmallHoles > 0)) {
1025  ATH_MSG_VERBOSE("Muon is in BEE eta/phi region and does not have 4 precision layers - fail high-pT");
1026  return false;
1027  }
1028  }
1029  } else {
1030  ATH_MSG_WARNING("passedHighPtCuts - MS or CB track missing in muon! Failing High-pT selection...");
1031  return false;
1032  }
1033 
1034  //::: Apply 1/p significance cut
1035  const xAOD::TrackParticle* idtrack = mu.trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
1036  const xAOD::TrackParticle* metrack = mu.trackParticle(xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle);
1037  if (idtrack && metrack && metrack->definingParametersCovMatrix()(4, 4) > 0) { const float qOverPsignif = qOverPsignificance(mu);
1038 
1039  ATH_MSG_VERBOSE("qOverP significance: " << qOverPsignif);
1040 
1041  if (std::abs(qOverPsignif) > 7) {
1042  ATH_MSG_VERBOSE("Muon failed qOverP significance cut");
1043  return false;
1044  }
1045  } else {
1046  ATH_MSG_VERBOSE("Muon missing ID or ME tracks - fail high-pT");
1047  return false;
1048  }
1049 
1050  // Accept good 2-station muons if the user has opted to include these
1051  if (m_use2stationMuonsHighPt && summary.nprecisionLayers == 2) {
1052  // should not accept EM+EO muons due to ID/MS alignment issues
1053  if (std::abs(mu.eta()) > 1.2 && summary.extendedSmallHits < 3 && summary.extendedLargeHits < 3) {
1054  ATH_MSG_VERBOSE("2-station muon with EM+EO - fail high-pT");
1055  return false;
1056  }
1057 
1058  // only select muons missing the inner precision layer
1059  // apply strict veto on overlap between small and large sectors
1060 
1061  if (summary.innerLargeHits == 0 && summary.middleLargeHits == 0 && summary.outerLargeHits == 0 &&
1062  summary.extendedLargeHits == 0 && summary.middleSmallHits > 2 &&
1063  (summary.outerSmallHits > 2 || summary.extendedSmallHits > 2)) {
1064  ATH_MSG_VERBOSE("Accepted 2-station muon in small sector");
1065  return true;
1066  }
1067 
1068  if (summary.innerSmallHits == 0 && summary.middleSmallHits == 0 && summary.outerSmallHits == 0 &&
1069  summary.extendedSmallHits == 0 && summary.middleLargeHits > 2 &&
1070  (summary.outerLargeHits > 2 || summary.extendedLargeHits > 2)) {
1071  ATH_MSG_VERBOSE("Accepted 2-station muon in large sector");
1072  return true;
1073  }
1074  }
1075 
1076  //::: Require 3 (good) station muons
1077  if (summary.nprecisionLayers < 3) {
1078  ATH_MSG_VERBOSE("Muon has less than 3 precision layers - fail high-pT");
1079  return false;
1080  }
1081 
1082  // Remove 3-station muons with small-large sectors overlap
1083  if (summary.isSmallGoodSectors) {
1084  if (!(summary.innerSmallHits > 2 && summary.middleSmallHits > 2 &&
1085  (summary.outerSmallHits > 2 || summary.extendedSmallHits > 2))) {
1086  ATH_MSG_VERBOSE("Muon has small/large sectors overlap - fail high-pT");
1087  return false;
1088  }
1089  } else {
1090  if (!(summary.innerLargeHits > 2 && summary.middleLargeHits > 2 &&
1091  (summary.outerLargeHits > 2 || summary.extendedLargeHits > 2))) {
1092  ATH_MSG_VERBOSE("Muon has small/large sectors overlap - fail high-pT");
1093  return false;
1094  }
1095  }
1096 
1097  ATH_MSG_VERBOSE("Muon passed high-pT selection");
1098  return true;
1099  }
1100 
1102  // ::
1103  if (mu.muonType() != xAOD::Muon::Combined) return false;
1104  // ::
1105  double start_cut = 3.0;
1106  double end_cut = 1.6;
1107  double abs_eta = std::abs(mu.eta());
1108 
1109  // parametrization of expected q/p error as function of pT
1110  double p0(8.0), p1(0.), p2(0.);
1111  if(isRun3()) //MC21 optimization
1112  {
1113  if(abs_eta<=1.05){
1114  p1=0.046;
1115  p2=0.00005;
1116  }
1117  else if (abs_eta > 1.05 && abs_eta <= 1.3) {
1118  p1 = 0.052;
1119  p2 = 0.00008;
1120  } else if (abs_eta > 1.3 && abs_eta <= 1.7) {
1121  p1 = 0.068;
1122  p2 = 0.00006;
1123  } else if (abs_eta > 1.7 && abs_eta <= 2.0) {
1124  p1 = 0.048;
1125  p2 = 0.00006;
1126  } else if (abs_eta > 2.0) {
1127  p1 = 0.037;
1128  p2 = 0.00006;
1129  }
1130  }
1131  else
1132  {
1133  if(abs_eta<=1.05){
1134  p1=0.039;
1135  p2=0.00006;
1136  }
1137  else if (abs_eta > 1.05 && abs_eta <= 1.3) {
1138  p1 = 0.040;
1139  p2 = 0.00009;
1140  } else if (abs_eta > 1.3 && abs_eta <= 1.7) {
1141  p1 = 0.056;
1142  p2 = 0.00008;
1143  } else if (abs_eta > 1.7 && abs_eta <= 2.0) {
1144  p1 = 0.041;
1145  p2 = 0.00006;
1146  } else if (abs_eta > 2.0) {
1147  p1 = 0.031;
1148  p2 = 0.00006;
1149  }
1150  }
1151  // ::
1152  hitSummary summary{};
1154 
1155  // independent parametrization for 2-station muons
1156  if (m_use2stationMuonsHighPt && summary.nprecisionLayers == 2) {
1157  start_cut = 1.1;
1158  end_cut=0.7;
1159  p1 = 0.0739568;
1160  p2 = 0.00012443;
1161  if (abs_eta > 1.05 && abs_eta < 1.3) {
1162  p1 = 0.0674484;
1163  p2 = 0.000119879;
1164  } else if (abs_eta >= 1.3 && abs_eta < 1.7) {
1165  p1 = 0.041669;
1166  p2 = 0.000178349;
1167  } else if (abs_eta >= 1.7 && abs_eta < 2.0) {
1168  p1 = 0.0488664;
1169  p2 = 0.000137648;
1170  } else if (abs_eta >= 2.0) {
1171  p1 = 0.028077;
1172  p2 = 0.000152707;
1173  }
1174  }
1175  // ::
1176  bool passErrorCutCB = false;
1177  const xAOD::TrackParticle* cbtrack = mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
1178  if (cbtrack) {
1179  // ::
1180  double pt_CB = (cbtrack->pt() * MeVtoGeV < 5000.) ? cbtrack->pt() * MeVtoGeV : 5000.; // GeV
1181  double qOverP_CB = cbtrack->qOverP();
1182  double qOverPerr_CB = std::sqrt(cbtrack->definingParametersCovMatrix()(4, 4));
1183  // sigma represents the average expected error at the muon's pt/eta
1184  double sigma = std::sqrt(std::pow(p0 / pt_CB, 2) + std::pow(p1, 2) + std::pow(p2 * pt_CB, 2));
1185  // cutting at start_cut*sigma for pt <=1 TeV depending on eta region,
1186  // then linearly tightening until end_cut*sigma is reached at pt >= 5TeV.
1187  double a = (end_cut - start_cut) / 4000.0;
1188  double b = end_cut - a * 5000.0;
1189  double coefficient = (pt_CB > 1000.) ? (a * pt_CB + b) : start_cut;
1190  if (std::abs(qOverPerr_CB / qOverP_CB) < coefficient * sigma) { passErrorCutCB = true; }
1191  }
1192  // ::
1193  if (m_use2stationMuonsHighPt && m_doBadMuonVetoMimic && summary.nprecisionLayers == 2) {
1195 
1196  if (eventInfo->eventType(xAOD::EventInfo::IS_SIMULATION)) {
1197  ATH_MSG_DEBUG("The current event is a MC event. Use bad muon veto mimic.");
1198  return passErrorCutCB && passedBMVmimicCut(mu);
1199  }
1200  }
1201 
1202  // ::
1203  return passErrorCutCB;
1204  }
1205 
1207  TF1* cutFunction;
1208  double p1, p2;
1209  if (std::abs(mu.eta()) < 1.05) {
1210  cutFunction = m_BMVcutFunction_barrel.get();
1211  p1 = 0.066265;
1212  p2 = 0.000210047;
1213  } else {
1214  cutFunction = m_BMVcutFunction_endcap.get();
1215  p1 = 0.0629747;
1216  p2 = 0.000196466;
1217  }
1218 
1219  double qOpRelResolution = std::hypot(p1, p2 * mu.primaryTrackParticle()->pt() * MeVtoGeV);
1220 
1221  double qOverPabs_unsmeared = std::abs(mu.primaryTrackParticle()->definingParameters()[4]);
1222  double qOverPabs_smeared = 1.0 / (mu.pt() * std::cosh(mu.eta()));
1223 
1224  if ((qOverPabs_smeared - qOverPabs_unsmeared) / (qOpRelResolution * qOverPabs_unsmeared) <
1225  cutFunction->Eval(mu.primaryTrackParticle()->pt() * MeVtoGeV))
1226  return false;
1227  else
1228  return true;
1229  }
1230 
1232  // ::
1233  if (mu.muonType() == xAOD::Muon::Combined) { return mu.author() != xAOD::Muon::STACO; }
1234  // ::
1235  if (mu.muonType() == xAOD::Muon::CaloTagged && std::abs(mu.eta()) < 0.105)
1236  return passedCaloTagQuality(mu);
1237  // ::
1238  if (mu.muonType() == xAOD::Muon::SegmentTagged && (std::abs(mu.eta()) < 0.105 || m_useSegmentTaggedLowPt)) return true;
1239  // ::
1240  if (mu.author() == xAOD::Muon::MuidSA && std::abs(mu.eta()) > 2.4) return true;
1241  // ::
1242  if (mu.muonType() == xAOD::Muon::SiliconAssociatedForwardMuon) {
1243  const xAOD::TrackParticle* cbtrack = mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
1244  return (cbtrack && std::abs(cbtrack->eta()) > 2.4);
1245  }
1246  // ::
1247  return false;
1248  }
1249 
1251  uint8_t value1{0}, value2{0};
1252 
1255  " !! Tool configured with some of the ID hits requirements changed... FOR DEVELOPMENT ONLY: muon efficiency SF won't be "
1256  "valid !! ");
1257 
1260  if ((value1 + value2 == 0) && !m_PixCutOff) return false;
1261 
1264  if ((value1 + value2 <= 4) && !m_SctCutOff) return false;
1265 
1268  if ((value1 + value2 >= 3) && !m_SiHolesCutOff) return false;
1269 
1270  if (!m_TrtCutOff) {
1271  const float abseta = std::abs(track.eta());
1274  const uint8_t totTRThits = value1 + value2;
1275  if (!((0.1 < abseta && abseta <= 1.9 && totTRThits > 5 && value2 < (0.9 * totTRThits)) || (abseta <= 0.1 || abseta > 1.9)))
1276  return false;
1277  }
1278  // Reached end - all ID hit cuts are passed.
1279  return true;
1280  } // passedIDCuts
1281 
1283  // Use CaloScore variable based on Neural Network if enabled
1284  // The neural network is only trained until eta = 1
1285  // cf. https://cds.cern.ch/record/2802605/files/CERN-THESIS-2021-290.pdf
1286  constexpr float eta_range = 1.;
1287  if (std::abs(mu.eta()) < eta_range && m_useCaloScore) return passedCaloScore(mu);
1288 
1289  // Otherwise we use CaloMuonIDTag
1290  int CaloMuonIDTag = -20;
1291 
1292  // Extract CaloMuonIDTag variable
1293  bool readID = mu.parameter(CaloMuonIDTag, xAOD::Muon::CaloMuonIDTag);
1294  if (!readID) {
1295  ATH_MSG_WARNING("Unable to read CaloMuonIDTag Quality information! Rejecting the CALO muon!");
1296  return false;
1297  }
1298 
1299  // Cut on CaloMuonIDTag variable
1300  return (CaloMuonIDTag > 10);
1301  }
1302 
1304  // We use a working point with a pT-dependent cut on the NN discriminant, designed to achieve a constant
1305  // fakes rejection as function of pT in Z->mumu MC
1306 
1307  // Extract the relevant score variable (NN discriminant)
1308  float CaloMuonScore{-999.0};
1309  retrieveParam(mu, CaloMuonScore, xAOD::Muon::CaloMuonScore);
1310 
1311  if(m_caloScoreWP==1) return (CaloMuonScore >= 0.92);
1312  if(m_caloScoreWP==2) return (CaloMuonScore >= 0.56);
1313  else if(m_caloScoreWP==3 || m_caloScoreWP==4)
1314  {
1315  // Cut on the score variable
1316  float pT = mu.pt() * MeVtoGeV; // GeV
1317 
1318  if (pT > 20.0) // constant cut above 20 GeV
1319  return (CaloMuonScore >= 0.77);
1320  else {
1321  // pT-dependent cut below 20 GeV
1322  // The pT-dependent cut is based on a fit of a third-degree polynomial, with coefficients as given below
1323 
1324  if(m_caloScoreWP==3) return (CaloMuonScore >= (-1.98e-4 * std::pow(pT, 3) +6.04e-3 * std::pow(pT, 2) -6.13e-2 * pT + 1.16));
1325  if(m_caloScoreWP==4) return (CaloMuonScore >= (-1.80e-4 * std::pow(pT, 3) +5.02e-3 * std::pow(pT, 2) -4.62e-2 * pT + 1.12));
1326  }
1327  }
1328 
1329  return false;
1330  }
1331 
1332  bool MuonSelectionTool::passTight(const xAOD::Muon& mu, float rho, float oneOverPSig) const {
1333 
1335  ATH_MSG_VERBOSE("for run3, Tight WP is only supported when ExcludeNSWFromPrecisionLayers=False and RecalcPrecisionLayerswNSW=True");
1336  return false;
1337  }
1338  float symmetric_eta = std::abs(mu.eta());
1339  float pt = mu.pt() * MeVtoGeV; // GeV
1340 
1341  // Impose pT and eta cuts; the bounds of the cut maps
1342  if (pt < 4.0 || symmetric_eta >= 2.5) return false;
1343  ATH_MSG_VERBOSE("Muon is passing tight WP kinematic cuts with pT,eta " << mu.pt() << " , " << mu.eta());
1344 
1345  // ** Low pT specific cuts ** //
1346  if (pt < 20.0) {
1347  double rhoCut = m_tightWP_lowPt_rhoCuts->Interpolate(pt, symmetric_eta);
1348  double qOverPCut = m_tightWP_lowPt_qOverPCuts->Interpolate(pt, symmetric_eta);
1349 
1350  ATH_MSG_VERBOSE("Applying tight WP cuts to a low pt muon with (pt,eta) ( " << pt << " , " << mu.eta() << " ) ");
1351  ATH_MSG_VERBOSE("Rho value " << rho << ", required to be less than " << rhoCut);
1352  ATH_MSG_VERBOSE("Momentum significance value " << oneOverPSig << ", required to be less than " << qOverPCut);
1353 
1354  if (rho > rhoCut) return false;
1355  ATH_MSG_VERBOSE("Muon passed tight WP, low pT rho cut!");
1356 
1357  if (oneOverPSig > qOverPCut) return false;
1358  ATH_MSG_VERBOSE("Muon passed tight WP, low pT momentum significance cut");
1359 
1360  // Tight muon!
1361  return true;
1362 
1363  }
1364 
1365  // ** Medium pT specific cuts ** //
1366  else if (pt < 100.0) {
1367  double rhoCut = m_tightWP_mediumPt_rhoCuts->Interpolate(pt, symmetric_eta);
1368  //
1369  ATH_MSG_VERBOSE("Applying tight WP cuts to a medium pt muon with (pt,eta) (" << pt << "," << mu.eta() << ")");
1370  ATH_MSG_VERBOSE("Rho value " << rho << " required to be less than " << rhoCut);
1371 
1372  // Apply cut
1373  if (rho > rhoCut) return false;
1374  ATH_MSG_VERBOSE("Muon passed tight WP, medium pT rho cut!");
1375 
1376  // Tight muon!
1377  return true;
1378  }
1379 
1380  // ** High pT specific cuts
1381  else if (pt < 500.0) {
1382  //
1383  ATH_MSG_VERBOSE("Applying tight WP cuts to a high pt muon with (pt,eta) (" << pt << "," << mu.eta() << ")");
1384  // No interpolation, since bins with -1 mean we should cut really loose
1385  double rhoCut = m_tightWP_highPt_rhoCuts->GetBinContent(m_tightWP_highPt_rhoCuts->FindFixBin(pt, symmetric_eta));
1386  ATH_MSG_VERBOSE("Rho value " << rho << ", required to be less than " << rhoCut << " unless -1, in which no cut is applied");
1387  //
1388  if (rhoCut < 0.0) return true;
1389  if (rho > rhoCut) return false;
1390  ATH_MSG_VERBOSE("Muon passed tight WP, high pT rho cut!");
1391 
1392  return true;
1393  }
1394  // For muons with pT > 500 GeV, no extra cuts
1395  else {
1396  ATH_MSG_VERBOSE("Not applying any tight WP cuts to a very high pt muon with (pt,eta) (" << pt << "," << mu.eta() << ")");
1397  return true;
1398  }
1399 
1400  // you should never reach this point
1401  return false;
1402  }
1403 
1404  //============================================================================
1406 
1407  checkSanity();
1408 
1422 
1423  if (!isRun3()) {
1424  // ignore missing of cscUnspoiledEtaHits in case we are running in expert developer mode
1425  // e.g. for when we want to apply Run2 WPs in Run3
1427 
1428  if (std::abs(muon.eta()) > 2.0) {
1429  ATH_MSG_VERBOSE("Recalculating number of precision layers for combined muon");
1430  summary.nprecisionLayers = (summary.innerSmallHits > 1 || summary.innerLargeHits > 1)
1431  + (summary.middleSmallHits > 2 || summary.middleLargeHits > 2)
1432  + (summary.outerSmallHits > 2 || summary.outerLargeHits > 2);
1433  }
1434 
1435  } else if (std::abs(muon.eta()) > 1.3 && (m_excludeNSWFromPrecisionLayers || m_recalcPrecisionLayerswNSW)) {
1436  summary.nprecisionLayers = (summary.middleSmallHits > 2 || summary.middleLargeHits > 2)
1437  + (summary.outerSmallHits > 2 || summary.outerLargeHits > 2)
1438  + (summary.extendedSmallHits > 2 || summary.extendedLargeHits > 2);
1439 
1441 
1442  if (!eta1stgchits_acc.isAvailable(muon) || !eta2stgchits_acc.isAvailable(muon) || !mmhits_acc.isAvailable(muon)) {
1443  ATH_MSG_FATAL(__FILE__ << ":" << __LINE__ << " Failed to retrieve NSW hits!"
1444  << " (Please use DxAODs with p-tags >= p5834 OR set ExcludeNSWFromPrecisionLayers to True (tests only)");
1445  throw std::runtime_error("Failed to retrieve NSW hits");
1446  }
1447 
1451  summary.nprecisionLayers += ((summary.etaLayer1STGCHits + summary.etaLayer2STGCHits) > 3 || summary.MMHits > 3);
1452  }
1453  }
1454  }
1455 
1456 
1458  if (!muon.parameter(value, param)) {
1459  ATH_MSG_FATAL(__FILE__ << ":" << __LINE__ << " Failed to retrieve parameter " << param
1460  << " for muon with pT:" << muon.pt() * MeVtoGeV << ", eta:" << muon.eta() << ", phi: " << muon.phi()
1461  << ", q:" << muon.charge() << ", author: " << muon.author());
1462  throw std::runtime_error("Failed to retrieve Parameter");
1463  }
1464  }
1465 
1466  // Returns an integer corresponding to categorization of muons with different resolutions
1468  // Resolutions have only been evaluated for medium combined muons
1470 
1471  // :: Access MS hits information
1472  hitSummary summary{};
1474 
1475  // For muons passing the high-pT working point, distinguish between 2-station tracks and the rest
1476  if (passedHighPtCuts(mu)) {
1477  if (summary.nprecisionLayers == 2)
1478  return ResolutionCategory::highPt2station;
1479  else
1481  }
1482 
1483  const xAOD::TrackParticle* CB_track = mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
1484  const xAOD::TrackParticle* MS_track = mu.trackParticle(xAOD::Muon::MuonSpectrometerTrackParticle);
1485  if (!MS_track) {
1486  ATH_MSG_VERBOSE("getResolutionCategory - No MS track available for muon. Using combined track.");
1487  MS_track = mu.trackParticle(xAOD::Muon::CombinedTrackParticle);
1488  }
1489 
1490  if (!MS_track || !CB_track) return ResolutionCategory::unclassified;
1491  const float etaMS = MS_track->eta();
1492  const float etaCB = CB_track->eta();
1493  const float phiMS = MS_track->phi();
1494 
1496 
1497  if ((summary.isSmallGoodSectors && summary.innerSmallHits < 3) || (!summary.isSmallGoodSectors && summary.innerLargeHits < 3))
1498  category = ResolutionCategory::missingInner; // missing-inner
1499 
1500  if ((summary.isSmallGoodSectors && summary.middleSmallHits < 3) || (!summary.isSmallGoodSectors && summary.middleLargeHits < 3))
1501  category = ResolutionCategory::missingMiddle; // missing-middle
1502 
1503  if ((summary.isSmallGoodSectors && summary.outerSmallHits < 3 && summary.extendedSmallHits < 3) ||
1504  (!summary.isSmallGoodSectors && summary.outerLargeHits < 3 && summary.extendedLargeHits < 3))
1505  category = ResolutionCategory::missingOuter; // missing-outer
1506 
1507  if (!isRun3() && (std::abs(etaMS) > 2.0 || std::abs(etaCB) > 2.0) && summary.cscUnspoiledEtaHits == 0)
1508  category = ResolutionCategory::spoiledCSC; // spoiled CSC
1509 
1510  if ((1.01 < std::abs(etaMS) && std::abs(etaMS) < 1.1) || (1.01 < std::abs(etaCB) && std::abs(etaCB) < 1.1))
1511  category = ResolutionCategory::BEoverlap; // barrel-end-cap overlap
1512 
1513  if (isBIS78(etaMS, phiMS)) category = ResolutionCategory::BIS78; // BIS7/8
1514 
1515  //::: BEE
1516  if (isBEE(etaMS, phiMS) || (std::abs(etaCB) > 1.4 && (summary.extendedSmallHits > 0 || summary.extendedSmallHoles > 0))) {
1517  if (summary.extendedSmallHits < 3 && summary.middleSmallHits >= 3 && summary.outerSmallHits >= 3)
1518  category = ResolutionCategory::missingBEE; // missing-BEE
1519 
1520  if (summary.extendedSmallHits >= 3 && summary.outerSmallHits < 3) category = ResolutionCategory::missingOuter; // missing-outer
1521 
1522  if (!summary.isSmallGoodSectors)
1523  category = ResolutionCategory::unclassified; // ambiguity due to eta/phi differences between MS and CB track
1524  }
1525 
1526  if (summary.nprecisionLayers == 1) category = ResolutionCategory::oneStation; // one-station track
1527 
1528  return category;
1529  }
1530 
1531  //============================================================================
1532  // need run number (or random run number) to apply period-dependent selections
1533  unsigned int MuonSelectionTool::getRunNumber(bool needOnlyCorrectYear /*=false*/) const {
1534 
1535  static const SG::AuxElement::ConstAccessor<unsigned int> acc_rnd("RandomRunNumber");
1536 
1538 
1539  // Case of data
1540  if (!eventInfo->eventType(xAOD::EventInfo::IS_SIMULATION)) {
1541  ATH_MSG_DEBUG("The current event is a data event. Return runNumber.");
1542  return eventInfo->runNumber();
1543  }
1544 
1545  // Case of MC
1546  // attempt to get the run number assigned by the PRW tool
1547  static std::atomic<bool> issuedWarningPRW{false};
1548  if (acc_rnd.isAvailable(*eventInfo)) {
1549  unsigned int rn = acc_rnd(*eventInfo);
1550  if (rn != 0) return acc_rnd(*eventInfo);
1551 
1552  if (!issuedWarningPRW) {
1553  ATH_MSG_WARNING("Pile up tool has assigned runNumber = 0");
1554  issuedWarningPRW = true;
1555  }
1556  }
1557 
1558  // otherwise return a dummy run number
1559  if (needOnlyCorrectYear) {
1560  if (eventInfo->runNumber() < 300000) { // mc16a (2016): 284500
1561  ATH_MSG_DEBUG("Random run number not available and this is mc16a or mc20a, returning dummy 2016 run number.");
1562  return 311071;
1563 
1564  } else if (eventInfo->runNumber() < 310000) { // mc16d (2017): 300000
1565  ATH_MSG_DEBUG("Random run number not available and this is mc16d or mc20d, returning dummy 2017 run number.");
1566  return 340072;
1567 
1568  } else if (eventInfo->runNumber() < 320000) { // mc16e (2018): 310000
1569  ATH_MSG_DEBUG("Random run number not available and this is mc16e or mc20e, returning dummy 2018 run number.");
1570  return 351359;
1571 
1572  } else if (eventInfo->runNumber() < 500000) { //mc21: 330000, mc23a: 410000, mc23c: 450000
1573  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  return 399999;
1575  }
1576 
1577  ATH_MSG_FATAL("Random run number not available, fallback option of using runNumber failed since "<<eventInfo->runNumber()<<" cannot be recognised");
1578  throw std::runtime_error("MuonSelectionTool() - need RandomRunNumber decoration by the PileupReweightingTool");
1579  }
1580 
1581  ATH_MSG_FATAL("Failed to find the RandomRunNumber decoration by the PileupReweightingTool");
1582  throw std::runtime_error("MuonSelectionTool() - need RandomRunNumber decoration from PileupReweightingTool");
1583  }
1584 
1585 
1586  // Check if eta/phi coordinates correspond to BIS7/8 chambers
1587  bool MuonSelectionTool::isBIS78(const float eta, const float phi) const {
1588  static constexpr std::array<float, 2> BIS78_eta{1.05, 1.3};
1589  static constexpr std::array<float, 8> BIS78_phi{0.21, 0.57, 1.00, 1.33, 1.78, 2.14, 2.57, 2.93};
1590 
1591  float abs_eta = std::abs(eta);
1592  float abs_phi = std::abs(phi);
1593 
1594  if (abs_eta >= BIS78_eta[0] && abs_eta <= BIS78_eta[1]) {
1595  if ((abs_phi >= BIS78_phi[0] && abs_phi <= BIS78_phi[1]) || (abs_phi >= BIS78_phi[2] && abs_phi <= BIS78_phi[3]) ||
1596  (abs_phi >= BIS78_phi[4] && abs_phi <= BIS78_phi[5]) || (abs_phi >= BIS78_phi[6] && abs_phi <= BIS78_phi[7])) {
1597  return true;
1598  }
1599  }
1600 
1601  return false;
1602  }
1603 
1604  // Check if eta/phi coordinates correspond to BEE chambers
1605  bool MuonSelectionTool::isBEE(const float eta, const float phi) const {
1606  static constexpr std::array<float, 2> BEE_eta{1.440, 1.692};
1607  static constexpr std::array<float, 8> BEE_phi{0.301, 0.478, 1.086, 1.263, 1.872, 2.049, 2.657, 2.834};
1608 
1609  float abs_eta = std::abs(eta);
1610  float abs_phi = std::abs(phi);
1611 
1612  if (abs_eta >= BEE_eta[0] && abs_eta <= BEE_eta[1]) {
1613  if ((abs_phi >= BEE_phi[0] && abs_phi <= BEE_phi[1]) || (abs_phi >= BEE_phi[2] && abs_phi <= BEE_phi[3]) ||
1614  (abs_phi >= BEE_phi[4] && abs_phi <= BEE_phi[5]) || (abs_phi >= BEE_phi[6] && abs_phi <= BEE_phi[7])) {
1615  return true;
1616  }
1617  }
1618 
1619  return false;
1620  }
1621 
1622  // Check if eta/phi coordinates correspond to BMG chambers
1623  bool MuonSelectionTool::isBMG(const float eta, const float phi) const {
1624  static constexpr std::array<float, 6> BMG_eta{0.35, 0.47, 0.68, 0.80, 0.925, 1.04};
1625  static constexpr std::array<float, 4> BMG_phi{-1.93, -1.765, -1.38, -1.21};
1626 
1627  float abs_eta = std::abs(eta);
1628 
1629  if ((abs_eta >= BMG_eta[0] && abs_eta <= BMG_eta[1]) || (abs_eta >= BMG_eta[2] && abs_eta <= BMG_eta[3]) ||
1630  (abs_eta >= BMG_eta[4] && abs_eta <= BMG_eta[5])) {
1631  if ((phi >= BMG_phi[0] && phi <= BMG_phi[1]) || (phi >= BMG_phi[2] && phi <= BMG_phi[3])) { return true; }
1632  }
1633 
1634  return false;
1635  }
1636 
1637 } // namespace CP
Muon::MuonStationIndex::BIS
@ BIS
Definition: MuonStationIndex.h:17
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
xAOD::numberOfPixelHoles
@ numberOfPixelHoles
number of pixel layers on track with absence of hits [unit8_t].
Definition: TrackingPrimitives.h:261
LikeEnum::Loose
@ Loose
Definition: LikelihoodEnums.h:12
python.SystemOfUnits.second
int second
Definition: SystemOfUnits.py:120
CXXUTILS_TRAPPING_FP
#define CXXUTILS_TRAPPING_FP
Definition: trapping_fp.h:24
CalculateHighPtTerm.pT
pT
Definition: ICHEP2016/CalculateHighPtTerm.py:57
Muon::MuonStationIndex::CSS
@ CSS
Definition: MuonStationIndex.h:18
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
CP::MuonSelectionTool::m_MVAreaderFile_MuTagIMO_etaBin2
Gaudi::Property< std::string > m_MVAreaderFile_MuTagIMO_etaBin2
Definition: MuonSelectionTool.h:177
CP::MuonSelectionTool::passTight
bool passTight(const xAOD::Muon &mu, float rho, float oneOverPSig) const
Returns true if the muon passed the tight working point cuts.
Definition: MuonSelectionTool.cxx:1332
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
CP::MuonSelectionTool::m_acceptInfo
asg::AcceptInfo m_acceptInfo
Store selection information.
Definition: MuonSelectionTool.h:130
pdg_comparison.sigma
sigma
Definition: pdg_comparison.py:324
xAOD::MuGirl
@ MuGirl
MuGirl.
Definition: TrackingPrimitives.h:141
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
LikeEnum::VeryLoose
@ VeryLoose
Definition: LikelihoodEnums.h:11
CP::MuonSelectionTool::m_use2stationMuonsHighPt
Gaudi::Property< bool > m_use2stationMuonsHighPt
Definition: MuonSelectionTool.h:151
xAOD::numberOfPrecisionHoleLayers
@ numberOfPrecisionHoleLayers
layers with holes AND no hits [unit8_t].
Definition: TrackingPrimitives.h:289
CP::MuonSelectionTool::m_quality
Gaudi::Property< int > m_quality
Definition: MuonSelectionTool.h:133
AddEmptyComponent.histName
string histName
Definition: AddEmptyComponent.py:64
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:64
CP::MuonSelectionTool::m_custom_dir
Gaudi::Property< std::string > m_custom_dir
Definition: MuonSelectionTool.h:186
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:575
xAOD::EventInfo_v1::eventNumber
uint64_t eventNumber() const
The current event's event number.
CP::MuonSelectionTool::passedCaloTagQuality
virtual bool passedCaloTagQuality(const xAOD::Muon &mu) const override
Returns true if the muon passed additional calo-tag quality cuts.
Definition: MuonSelectionTool.cxx:1282
CP::MuonSelectionTool::m_MVAreaderFile_MuTagIMO_etaBin3
Gaudi::Property< std::string > m_MVAreaderFile_MuTagIMO_etaBin3
Definition: MuonSelectionTool.h:179
xAOD::etaMS
setSAddress etaMS
Definition: L2StandAloneMuon_v1.cxx:116
CP::MuonSelectionTool::getQuality
virtual xAOD::Muon::Quality getQuality(const xAOD::Muon &mu) const override
Returns the quality of the muon. To set the value on the muon, instead call setQuality(xAOD::Muon&) c...
Definition: MuonSelectionTool.cxx:414
Muon::MuonStationIndex::EEL
@ EEL
Definition: MuonStationIndex.h:18
SG::Accessor
Helper class to provide type-safe access to aux data.
Definition: Control/AthContainers/AthContainers/Accessor.h:66
CP::MuonSelectionTool::m_MVAreaderFile_EVEN_MuidCB
Gaudi::Property< std::string > m_MVAreaderFile_EVEN_MuidCB
Definition: MuonSelectionTool.h:161
xAOD::TrackParticle_v1::charge
float charge() const
Returns the charge.
Definition: TrackParticle_v1.cxx:150
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:79
CP::MuonSelectionTool::m_useAllAuthors
Gaudi::Property< bool > m_useAllAuthors
Definition: MuonSelectionTool.h:150
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
CP::MuonSelectionTool::m_reader_MUTAGIMO_etaBin3
std::unique_ptr< TMVA::Reader > m_reader_MUTAGIMO_etaBin3
Definition: MuonSelectionTool.h:222
CP::MuonSelectionTool::m_disablePtCuts
Gaudi::Property< bool > m_disablePtCuts
Definition: MuonSelectionTool.h:144
xAOD::TrackParticle_v1::eta
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
Definition: TrackParticle_v1.cxx:77
CP::MuonSelectionTool::m_readerE_MUID
std::unique_ptr< TMVA::Reader > m_readerE_MUID
Definition: MuonSelectionTool.h:215
plotmaker.hist
hist
Definition: plotmaker.py:148
Muon::MuonStationIndex::BML
@ BML
Definition: MuonStationIndex.h:17
xAOD::extendedSmallHoles
@ extendedSmallHoles
number of precision holes in the extended small layer
Definition: TrackingPrimitives.h:345
CP::MuonSelectionTool::passedIDCuts
virtual bool passedIDCuts(const xAOD::Muon &) const override
Returns true if the muon passes the standard MCP ID cuts.
Definition: MuonSelectionTool.cxx:602
CP::MuonSelectionTool::m_BMVcutFunction_barrel
std::unique_ptr< TF1 > m_BMVcutFunction_barrel
Definition: MuonSelectionTool.h:200
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
CP::MuonSelectionTool::isBEE
bool isBEE(const float eta, const float phi) const
Definition: MuonSelectionTool.cxx:1605
CP::MuonSelectionTool::m_readerE_MUGIRL
std::unique_ptr< TMVA::Reader > m_readerE_MUGIRL
Definition: MuonSelectionTool.h:217
MuonParameters::scatteringNeighbourSignificance
@ scatteringNeighbourSignificance
Definition: MuonParamDefs.h:135
asg
Definition: DataHandleTestTool.h:28
test_pyathena.pt
pt
Definition: test_pyathena.py:11
CP::MeVtoGeV
constexpr float MeVtoGeV
Definition: IsolationCloseByCorrectionTool.cxx:33
CP::MuonSelectionTool::m_turnOffMomCorr
Gaudi::Property< bool > m_turnOffMomCorr
Definition: MuonSelectionTool.h:143
xAOD::MuonSegment_v1
Class describing a MuonSegment.
Definition: MuonSegment_v1.h:33
CP::MuonSelectionTool::m_tightWP_highPt_rhoCuts
std::unique_ptr< TH1 > m_tightWP_highPt_rhoCuts
Definition: MuonSelectionTool.h:198
CP::MuonSelectionTool::getHist
StatusCode getHist(TFile *file, const std::string &histName, std::unique_ptr< TH1 > &hist) const
Checks for each histogram.
Definition: MuonSelectionTool.cxx:227
egammaParameters::ParamDef
ParamDef
Definition: egammaParamDefs.h:99
athena.value
value
Definition: athena.py:122
xAOD::numberOfPixelHits
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
Definition: TrackingPrimitives.h:259
CP::MuonSelectionTool::passedLowPtEfficiencyCuts
virtual bool passedLowPtEfficiencyCuts(const xAOD::Muon &) const override
Returns true if the muon passes the standard MCP low pt cuts.
Definition: MuonSelectionTool.cxx:683
CP::MuonSelectionTool::m_PixCutOff
Gaudi::Property< bool > m_PixCutOff
Definition: MuonSelectionTool.h:148
CP::MuonSelectionTool::setPassesIDCuts
virtual void setPassesIDCuts(xAOD::Muon &) const override
set the passes ID cuts variable of the muon
Definition: MuonSelectionTool.cxx:598
xAOD::numberOfTRTHits
@ numberOfTRTHits
number of TRT hits [unit8_t].
Definition: TrackingPrimitives.h:275
xAOD::middleLargeHoles
@ middleLargeHoles
number of precision holes in the middle large layer
Definition: TrackingPrimitives.h:342
CP::MuonSelectionTool::m_readerO_MUGIRL
std::unique_ptr< TMVA::Reader > m_readerO_MUGIRL
Definition: MuonSelectionTool.h:218
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:54
Muon::MuonStationIndex::BOS
@ BOS
Definition: MuonStationIndex.h:17
Muon::MuonStationIndex::BMS
@ BMS
Definition: MuonStationIndex.h:17
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
CP::MuonSelectionTool::retrieveParam
void retrieveParam(const xAOD::Muon &muon, float &value, const xAOD::Muon::ParamDef param) const
Definition: MuonSelectionTool.cxx:1457
CP::MuonSelectionTool::passedCaloScore
virtual bool passedCaloScore(const xAOD::Muon &mu) const override
Returns true if the muon passed the CaloScore calo-tag working point.
Definition: MuonSelectionTool.cxx:1303
xAOD::IParticle
Class providing the definition of the 4-vector interface.
Definition: Event/xAOD/xAODBase/xAODBase/IParticle.h:40
CP::MuonSelectionTool::m_isRun3
Gaudi::Property< bool > m_isRun3
Definition: MuonSelectionTool.h:135
xAOD::EventInfo_v1::IS_SIMULATION
@ IS_SIMULATION
true: simulation, false: data
Definition: EventInfo_v1.h:151
x
#define x
CP::MuonSelectionTool::m_MVAreaderFile_ODD_MuGirl
Gaudi::Property< std::string > m_MVAreaderFile_ODD_MuGirl
Definition: MuonSelectionTool.h:171
CP
Select isolated Photons, Electrons and Muons.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:48
Muon::MuonStationIndex::EIS
@ EIS
Definition: MuonStationIndex.h:18
CP::MuonSelectionTool::m_toroidOff
Gaudi::Property< bool > m_toroidOff
Definition: MuonSelectionTool.h:134
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
CP::MuonSelectionTool::passedHighPtCuts
virtual bool passedHighPtCuts(const xAOD::Muon &) const override
Returns true if the muon passes the standard MCP High Pt cuts.
Definition: MuonSelectionTool.cxx:925
xAOD::EventInfo_v1::runNumber
uint32_t runNumber() const
The current event's run number.
xAOD::innerLargeHits
@ innerLargeHits
number of precision hits in the inner large layer
Definition: TrackingPrimitives.h:331
CP::MuonSelectionTool::m_BMVcutFile
Gaudi::Property< std::string > m_BMVcutFile
file for bad muon veto mimic cut functions
Definition: MuonSelectionTool.h:189
CP::MuonSelectionTool::m_useMVALowPt
Gaudi::Property< bool > m_useMVALowPt
Definition: MuonSelectionTool.h:152
CP::MuonSelectionTool::m_BMVcutFunction_endcap
std::unique_ptr< TF1 > m_BMVcutFunction_endcap
Definition: MuonSelectionTool.h:201
MuonParameters::MuTagIMO
@ MuTagIMO
Definition: MuonParamDefs.h:66
Muon::MuonStationIndex::EOS
@ EOS
Definition: MuonStationIndex.h:18
xAOD::cscUnspoiledEtaHits
@ cscUnspoiledEtaHits
number of unspoiled CSC eta clusters on track
Definition: TrackingPrimitives.h:450
CP::MuonSelectionTool::m_recalcPrecisionLayerswNSW
Gaudi::Property< bool > m_recalcPrecisionLayerswNSW
Definition: MuonSelectionTool.h:137
MuonParameters::momentumBalanceSignificance
@ momentumBalanceSignificance
Definition: MuonParamDefs.h:136
CP::MuonSelectionTool::m_developMode
Gaudi::Property< bool > m_developMode
Definition: MuonSelectionTool.h:145
CP::MuonSelectionTool::passedErrorCutCB
virtual bool passedErrorCutCB(const xAOD::Muon &) const override
Returns true if a CB muon passes a pt- and eta-dependent cut on the relative CB q/p error.
Definition: MuonSelectionTool.cxx:1101
xAOD::middleLargeHits
@ middleLargeHits
number of precision hits in the middle large layer
Definition: TrackingPrimitives.h:333
InDet::ExclusiveOrigin::Primary
@ Primary
Definition: InDetTrackTruthOriginDefs.h:163
MuonParameters::highPt
@ highPt
Definition: MuonParamDefs.h:51
CP::MuonSelectionTool::setQuality
virtual void setQuality(xAOD::Muon &mu) const override
set the passes low pT cuts variable of the muon
Definition: MuonSelectionTool.cxx:356
CP::MuonSelectionTool::m_doBadMuonVetoMimic
Gaudi::Property< bool > m_doBadMuonVetoMimic
Definition: MuonSelectionTool.h:155
CP::MuonSelectionTool::m_eventInfo
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo
Definition: MuonSelectionTool.h:158
uint
unsigned int uint
Definition: LArOFPhaseFill.cxx:20
CP::MuonSelectionTool::passedBMVmimicCut
bool passedBMVmimicCut(const xAOD::Muon &) const
Returns true if the muon passes a cut which mimics the effect of the combined error cut This is neces...
Definition: MuonSelectionTool.cxx:1206
CP::MuonSelectionTool::qOverPsignificance
float qOverPsignificance(const xAOD::Muon &muon) const
Definition: MuonSelectionTool.cxx:379
CP::MuonSelectionTool::passedMuonCuts
virtual bool passedMuonCuts(const xAOD::Muon &) const override
Returns true if the muon passes a standardized loose preselection.
Definition: MuonSelectionTool.cxx:1231
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
asg::AcceptInfo
Definition: AcceptInfo.h:28
CP::MuonSelectionTool::hitSummary
Definition: MuonSelectionTool.h:227
lumiFormat.i
int i
Definition: lumiFormat.py:92
xAOD::extendedLargeHits
@ extendedLargeHits
number of precision hits in the extended large layer
Definition: TrackingPrimitives.h:337
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
CP::MuonSelectionTool::isBMG
bool isBMG(const float eta, const float phi) const
Definition: MuonSelectionTool.cxx:1623
ReweightUtils.category
category
Definition: ReweightUtils.py:15
CP::MuonSelectionTool::isBIS78
bool isBIS78(const float eta, const float phi) const
Definition: MuonSelectionTool.cxx:1587
CP::MuonSelectionTool::m_useLRT
Gaudi::Property< bool > m_useLRT
Definition: MuonSelectionTool.h:140
xAOD::MMHits
@ MMHits
Definition: TrackingPrimitives.h:437
CP::MuonSelectionTool::m_caloScoreWP
Gaudi::Property< int > m_caloScoreWP
Definition: MuonSelectionTool.h:139
LHEF::Reader
Pythia8::Reader Reader
Definition: Prophecy4fMerger.cxx:11
MuonParameters::segmentDeltaEta
@ segmentDeltaEta
MuTag parameters.
Definition: MuonParamDefs.h:139
athena.file_path
file_path
Definition: athena.py:92
CP::MuonSelectionTool::getAcceptInfo
virtual const asg::AcceptInfo & getAcceptInfo() const override
Get an object describing the "selection steps" of the tool.
Definition: MuonSelectionTool.cxx:248
file
TFile * file
Definition: tile_monitor.h:29
python.BunchSpacingUtils.rn
rn
Definition: BunchSpacingUtils.py:87
xAOD::middleSmallHoles
@ middleSmallHoles
number of precision holes in the middle small layer
Definition: TrackingPrimitives.h:341
CP::MuonSelectionTool::setPassesHighPtCuts
virtual void setPassesHighPtCuts(xAOD::Muon &mu) const override
set the passes high pT cuts variable of the muon
Definition: MuonSelectionTool.cxx:600
xAOD::combinedTrackOutBoundsPrecisionHits
@ combinedTrackOutBoundsPrecisionHits
total out-of-bounds hits on the combined track
Definition: TrackingPrimitives.h:377
CP::MuonSelectionTool::m_useSegmentTaggedLowPt
Gaudi::Property< bool > m_useSegmentTaggedLowPt
Definition: MuonSelectionTool.h:153
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MuonSelectionTool.h
CP::MuonSelectionTool::getSegmentsSorted
std::vector< const xAOD::MuonSegment * > getSegmentsSorted(const xAOD::Muon &mu) const
Returns a vector of the muon's segments, sorted according to chamber index.
Definition: MuonSelectionTool.cxx:803
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
CP::MuonSelectionTool::m_calibration_version
Gaudi::Property< std::string > m_calibration_version
Definition: MuonSelectionTool.h:183
CP::MuonSelectionTool::m_excludeNSWFromPrecisionLayers
Gaudi::Property< bool > m_excludeNSWFromPrecisionLayers
Definition: MuonSelectionTool.h:136
xAOD::numberOfSCTHoles
@ numberOfSCTHoles
number of SCT holes [unit8_t].
Definition: TrackingPrimitives.h:270
xAOD::isSmallGoodSectors
@ isSmallGoodSectors
if non-deweighted track chambers are small
Definition: TrackingPrimitives.h:380
xAOD::SiSpacePointsSeedMaker_LargeD0
@ SiSpacePointsSeedMaker_LargeD0
Definition: TrackingPrimitives.h:183
CP::MuonSelectionTool::getRunNumber
unsigned int getRunNumber(bool needOnlyCorrectYear=false) const
Definition: MuonSelectionTool.cxx:1533
xAOD::etaLayer2STGCHits
@ etaLayer2STGCHits
number of eta hits in the second STGC trigger layer (STGC2)
Definition: TrackingPrimitives.h:428
Trk::Combined
@ Combined
Definition: TrackSummaryTool.h:32
Muon::MuonStationIndex::EES
@ EES
Definition: MuonStationIndex.h:18
LikeEnum::Tight
@ Tight
Definition: LikelihoodEnums.h:15
trapping_fp.h
Tell the compiler to optimize assuming that FP may trap.
MuonParameters::scatteringCurvatureSignificance
@ scatteringCurvatureSignificance
Definition: MuonParamDefs.h:134
xAOD::TrackParticle_v1::qOverP
float qOverP() const
Returns the parameter.
PathResolver.h
CP::MuonSelectionTool::m_low_pt_mva_mutex
std::mutex m_low_pt_mva_mutex
Definition: MuonSelectionTool.h:225
xAOD::TrackParticle_v1::definingParametersCovMatrix
const ParametersCovMatrix_t definingParametersCovMatrix() const
Returns the 5x5 symmetric matrix containing the defining parameters covariance matrix.
Definition: TrackParticle_v1.cxx:246
xAOD::middleSmallHits
@ middleSmallHits
number of precision hits in the middle small layer
Definition: TrackingPrimitives.h:332
CP::MuonSelectionTool::accept
virtual asg::AcceptData accept(const xAOD::IParticle *p) const override
Get the decision using a generic IParticle pointer.
Definition: MuonSelectionTool.cxx:250
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
CP::MuonSelectionTool::m_reader_MUTAGIMO_etaBin1
std::unique_ptr< TMVA::Reader > m_reader_MUTAGIMO_etaBin1
Definition: MuonSelectionTool.h:220
ReadHandle.h
Handle class for reading from StoreGate.
CP::MuonSelectionTool::m_tightWP_mediumPt_rhoCuts
std::unique_ptr< TH1 > m_tightWP_mediumPt_rhoCuts
Definition: MuonSelectionTool.h:197
CP::MuonSelectionTool::m_readerO_MUID
std::unique_ptr< TMVA::Reader > m_readerO_MUID
Definition: MuonSelectionTool.h:216
CP::MuonSelectionTool::m_useCaloScore
Gaudi::Property< bool > m_useCaloScore
Definition: MuonSelectionTool.h:138
CP::MuonSelectionTool::checkSanity
void checkSanity() const
Definition: MuonSelectionTool.cxx:269
MuonParameters::MuidSA
@ MuidSA
Definition: MuonParamDefs.h:59
xAOD::outerSmallHits
@ outerSmallHits
number of precision hits in the outer small layer
Definition: TrackingPrimitives.h:334
CP::MuonSelectionTool::m_SiHolesCutOff
Gaudi::Property< bool > m_SiHolesCutOff
Definition: MuonSelectionTool.h:149
CP::MuonSelectionTool::m_MVAreaderFile_MuTagIMO_etaBin1
Gaudi::Property< std::string > m_MVAreaderFile_MuTagIMO_etaBin1
Definition: MuonSelectionTool.h:175
IDTPM::chiSquared
float chiSquared(const U &p)
Definition: TrackParametersHelper.h:136
Muon::MuonStationIndex::ChIndexMax
@ ChIndexMax
Definition: MuonStationIndex.h:19
CP::MuonSelectionTool::m_tightWP_lowPt_qOverPCuts
std::unique_ptr< TH1 > m_tightWP_lowPt_qOverPCuts
Definition: MuonSelectionTool.h:196
PathResolverFindCalibFile
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.cxx:431
Muon
struct TBPatternUnitContext Muon
CP::MuonSelectionTool::initialize
virtual StatusCode initialize() override
Function initialising the tool.
Definition: MuonSelectionTool.cxx:58
CP::MuonSelectionTool::isBadMuon
virtual bool isBadMuon(const xAOD::Muon &) const override
Returns true if a CB muon fails some loose quaility requirements designed to remove pathological trac...
Definition: MuonSelectionTool.cxx:637
CP::MuonSelectionTool::m_reader_MUTAGIMO_etaBin2
std::unique_ptr< TMVA::Reader > m_reader_MUTAGIMO_etaBin2
Definition: MuonSelectionTool.h:221
CP::MuonSelectionTool::m_tightWP_lowPt_rhoCuts
std::unique_ptr< TH1 > m_tightWP_lowPt_rhoCuts
Definition: MuonSelectionTool.h:195
CP::MuonSelectionTool::MuonSelectionTool
MuonSelectionTool(const std::string &name="MuonSelection")
Create a proper constructor for Athena.
Definition: MuonSelectionTool.cxx:54
Muon::MuonStationIndex::EML
@ EML
Definition: MuonStationIndex.h:18
xAOD::numberOfTRTOutliers
@ numberOfTRTOutliers
number of TRT outliers [unit8_t].
Definition: TrackingPrimitives.h:276
CP::MuonSelectionTool::isRun3
bool isRun3(bool forceOnTheFly=false) const
Definition: MuonSelectionTool.h:266
MuonParameters::MuidCo
@ MuidCo
Definition: MuonParamDefs.h:60
xAOD::outerLargeHits
@ outerLargeHits
number of precision hits in the outer large layer
Definition: TrackingPrimitives.h:335
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
a
TList * a
Definition: liststreamerinfos.cxx:10
CP::MuonSelectionTool::m_maxEta
Gaudi::Property< double > m_maxEta
Definition: MuonSelectionTool.h:132
asg::AcceptData::setCutResult
void setCutResult(const std::string &cutName, bool cutResult)
Set the result of a cut, based on the cut name (safer)
Definition: AcceptData.h:134
LikeEnum::Medium
@ Medium
Definition: LikelihoodEnums.h:14
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
xAOD::numberOfSCTDeadSensors
@ numberOfSCTDeadSensors
number of dead SCT sensors crossed [unit8_t].
Definition: TrackingPrimitives.h:273
Muon::MuonStationIndex::BIL
@ BIL
Definition: MuonStationIndex.h:17
Muon::MuonStationIndex::BEE
@ BEE
Definition: MuonStationIndex.h:17
TH1
Definition: rootspy.cxx:268
DeMoScan.first
bool first
Definition: DeMoScan.py:534
CP::MuonSelectionTool::m_TrtCutOff
Gaudi::Property< bool > m_TrtCutOff
Definition: MuonSelectionTool.h:146
xAOD::etaLayer1STGCHits
@ etaLayer1STGCHits
number of eta hits in the first STGC trigger layer (STGC1)
Definition: TrackingPrimitives.h:427
xAOD::numberOfGoodPrecisionLayers
@ numberOfGoodPrecisionLayers
layers with at least 3 hits that are not deweighted [uint8_t]
Definition: TrackingPrimitives.h:294
CP::MuonSelectionTool::IdMsPt
void IdMsPt(const xAOD::Muon &muon, float &idPt, float &msPt) const
Definition: MuonSelectionTool.cxx:360
CP::MuonSelectionTool::retrieveSummaryValue
void retrieveSummaryValue(const P &muon, T &value, const S type, bool ignoreMissing=false) const
Definition: MuonSelectionTool.h:247
CP::MuonSelectionTool::m_geoOnTheFly
Gaudi::Property< bool > m_geoOnTheFly
Definition: MuonSelectionTool.h:154
xAOD::numberOfSCTHits
@ numberOfSCTHits
number of hits in SCT [unit8_t].
Definition: TrackingPrimitives.h:268
CP::MuonSelectionTool::~MuonSelectionTool
virtual ~MuonSelectionTool()
SG::ConstAccessor< T, AuxAllocator_t< T > >::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
CP::MuonSelectionTool::m_allowComm
Gaudi::Property< bool > m_allowComm
Definition: MuonSelectionTool.h:156
xAOD::STACO
@ STACO
Tracks produced by STACO.
Definition: TrackingPrimitives.h:99
xAOD::numberOfPixelDeadSensors
@ numberOfPixelDeadSensors
number of dead pixel sensors crossed [unit8_t].
Definition: TrackingPrimitives.h:266
xAOD::track
@ track
Definition: TrackingPrimitives.h:512
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
xAOD::extendedSmallHits
@ extendedSmallHits
number of precision hits in the extended small layer
Definition: TrackingPrimitives.h:336
CP::MuonSelectionTool::m_MVAreaderFile_ODD_MuidCB
Gaudi::Property< std::string > m_MVAreaderFile_ODD_MuidCB
Definition: MuonSelectionTool.h:164
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
collisions.reader
reader
read the goodrunslist xml file(s)
Definition: collisions.py:22
Muon::MuonStationIndex::EMS
@ EMS
Definition: MuonStationIndex.h:18
xAOD::innerSmallHits
@ innerSmallHits
number of precision hits in the inner small layer
Definition: TrackingPrimitives.h:330
Muon::MuonStationIndex::EOL
@ EOL
Definition: MuonStationIndex.h:18
CP::MuonSelectionTool::passedLowPtEfficiencyMVACut
bool passedLowPtEfficiencyMVACut(const xAOD::Muon &) const
Definition: MuonSelectionTool.cxx:819
asg::AcceptData
Definition: AcceptData.h:30
CP::MuonSelectionTool::fillSummary
void fillSummary(const xAOD::Muon &muon, hitSummary &summary) const
Definition: MuonSelectionTool.cxx:1405
CaloNoise_fillDB.mu
mu
Definition: CaloNoise_fillDB.py:53
CP::MuonSelectionTool::getResolutionCategory
virtual int getResolutionCategory(const xAOD::Muon &) const override
Returns an integer corresponding to categorization of muons with different resolutions.
Definition: MuonSelectionTool.cxx:1467
xAOD::TrackParticle_v1::theta
float theta() const
Returns the parameter, which has range 0 to .
CP::MuonSelectionTool::m_SctCutOff
Gaudi::Property< bool > m_SctCutOff
Definition: MuonSelectionTool.h:147
Muon::MuonStationIndex::BOL
@ BOL
Definition: MuonStationIndex.h:17
TrackingPrimitives.h
CP::MuonSelectionTool::m_MVAreaderFile_EVEN_MuGirl
Gaudi::Property< std::string > m_MVAreaderFile_EVEN_MuGirl
Definition: MuonSelectionTool.h:168
fitman.rho
rho
Definition: fitman.py:532
Muon::MuonStationIndex::CSL
@ CSL
Definition: MuonStationIndex.h:18
xAOD::TrackParticle_v1::phi
virtual double phi() const override final
The azimuthal angle ( ) of the particle (has range to .)
xAOD::EventInfo_v1::eventType
bool eventType(EventType type) const
Check for one particular bitmask value.
GlobalVariables.eta_range
eta_range
Definition: GlobalVariables.py:359
asg::AcceptInfo::addCut
int addCut(const std::string &cutName, const std::string &cutDescription)
Add a cut; returning the cut position.
Definition: AcceptInfo.h:53
xAOD::TauJetParameters::unclassified
@ unclassified
Definition: TauDefs.h:410
Muon::MuonStationIndex::EIL
@ EIL
Definition: MuonStationIndex.h:18
CP::MuonSelectionTool::rhoPrime
float rhoPrime(const xAOD::Muon &muon) const
Definition: MuonSelectionTool.cxx:403
xAOD::numberOfPrecisionLayers
@ numberOfPrecisionLayers
layers with at least 3 hits [unit8_t].
Definition: TrackingPrimitives.h:288
SCT_Monitoring::summary
@ summary
Definition: SCT_MonitoringNumbers.h:65