ATLAS Offline Software
Loading...
Searching...
No Matches
MuonPerformanceAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <vector>
8
11#include "GaudiKernel/EventContext.h"
12#include "xAODMuon/Muon.h"
20
21MuonPerformanceAlg::MuonPerformanceAlg(const std::string& name, ISvcLocator* pSvcLocator) :
22 AthAlgorithm(name, pSvcLocator), m_writeToFile(false), m_nevents(0), m_runNumber(0), m_eventNumber(0) {
23 declareProperty("writeToFile", m_writeToFile = false);
24 declareProperty("FileName", m_fileName = "MuonPerformanceAlg.txt");
25 declareProperty("ConsideredPDGs", m_pdgsToBeConsidered);
26}
27
29 // initialize cuts, please make sure the number of bins and the sizes of the cuts + string are always the same
30 unsigned int nbins = 12;
31 m_nevents = 0;
32 m_ntruth.resize(nbins);
33 m_ntruth5.resize(nbins);
34 m_ntruth10.resize(nbins);
35 m_nfound.resize(nbins);
36 m_nfound5.resize(nbins);
37 m_nfound10.resize(nbins);
38 m_nfoundr.resize(nbins);
39 m_nfoundr5.resize(nbins);
40 m_nfoundr10.resize(nbins);
41 m_nreco.resize(nbins);
42 m_nreco5.resize(nbins);
43 m_nreco10.resize(nbins);
44 m_hitCutString = {"SA 2.0 ", "CB all ", "MuidCB ", "MuGirl ", "Tag ", "Calo ",
45 "ID ", "SA(no ID)", "Tight ", "Medium ", "Loose ", "Combined "};
46
47 // add muons
48 if (m_pdgsToBeConsidered.value().empty()) {
49 m_selectedPdgs.insert(13);
50 m_selectedPdgs.insert(-13);
51 } else {
52 // add pdgs
53 for (auto pdg : m_pdgsToBeConsidered.value()) m_selectedPdgs.insert(pdg);
54 }
55 if (!m_muonsNameKey.key().empty()) ATH_CHECK(m_muonsNameKey.initialize());
56
57 ATH_CHECK(m_eventInfo.initialize());
58 ATH_CHECK(m_truthMuons.initialize());
61 ATH_CHECK(m_truthMuonTruthType.initialize());
64 return StatusCode::SUCCESS;
65}
66
68
70 uint8_t nblh = 0x0;
71 uint8_t eblh = 0x0;
72 uint8_t nblo = 0x0;
73 uint8_t nphi = 0x0;
74 uint8_t npds = 0x0;
75 uint8_t nsctds = 0x0;
76 uint8_t nscthi = 0x0;
77 uint8_t nsctho = 0x0;
78 uint8_t npho = 0x0;
79 uint8_t ntrthi = 0x0;
80 uint8_t ntrtol = 0x0;
81
82 int tightness = 0;
83
84 bool passesIDcuts = false;
85
86 if (tp) {
87 // check blayer
88 tp->summaryValue(eblh, xAOD::expectInnermostPixelLayerHit);
89 tp->summaryValue(nblh, xAOD::numberOfInnermostPixelLayerHits);
90 tp->summaryValue(nblo, xAOD::numberOfInnermostPixelLayerOutliers);
91 if (static_cast<int>(eblh) == 0 || static_cast<int>(nblh) + static_cast<int>(nblo) > 0) tightness += 1;
92
93 // pixel hit counts
94 tp->summaryValue(nphi, xAOD::numberOfPixelHits);
95 tp->summaryValue(npds, xAOD::numberOfPixelDeadSensors);
96 if (static_cast<int>(nphi) + static_cast<int>(npds) >= 2) tightness += 2;
97
98 // sct hit counts
99 tp->summaryValue(nscthi, xAOD::numberOfSCTHits);
100 tp->summaryValue(nsctds, xAOD::numberOfSCTDeadSensors);
101 if (static_cast<int>(nscthi) + static_cast<int>(nsctds) > 5) tightness += 4;
102
103 // hole cuts
104 tp->summaryValue(npho, xAOD::numberOfPixelHoles);
105 tp->summaryValue(nsctho, xAOD::numberOfSCTHoles);
106 if (static_cast<int>(npho) + static_cast<int>(nsctho) < 2) tightness += 8;
107
108 // trt cuts
109 tp->summaryValue(ntrthi, xAOD::numberOfTRTHits);
110 tp->summaryValue(ntrtol, xAOD::numberOfTRTOutliers);
111 int ntrt = static_cast<int>(ntrthi) + static_cast<int>(ntrtol);
112 bool pass = true;
113 if (ntrt > 5 && static_cast<int>(ntrtol) / (double)ntrt > 0.9) pass = false;
114 if ((std::abs(tp->eta()) > 0.1 && std::abs(tp->eta()) < 1.9) && ntrt <= 5) pass = false;
115 if (pass) tightness += 16;
116 //
117 // B layer is not a requirement anymore
118 //
119 if (pass && tightness > 29) passesIDcuts = true;
120
121 if (passesIDcuts && debug) ATH_MSG_VERBOSE("ID trackparticle PASSED IDcuts with tightness " << tightness);
122 }
123 if (!passesIDcuts && debug) ATH_MSG_DEBUG("ID trackparticle FAILED IDcuts with tightness " << tightness);
124
125 return passesIDcuts;
126}
127
129 const EventContext& ctx = Gaudi::Hive::currentContext();
131
132 m_runNumber = eventInfo->runNumber();
133 m_eventNumber = eventInfo->eventNumber();
134
136 if (!TruthMuons.isPresent()) {
137 ATH_MSG_DEBUG("no truth muon collection present");
138 return StatusCode::SUCCESS;
139 }
140 if (!TruthMuons.isValid()) {
141 ATH_MSG_WARNING(m_truthMuons.key() << " not valid");
142 return StatusCode::FAILURE;
143 }
144 ATH_MSG_VERBOSE("Retrieved truth muons " << TruthMuons->size());
146
147 static const SG::ConstAccessor<int> truthTypeAcc("truthType");
148 static const SG::ConstAccessor<int> truthOriginAcc("truthOrigin");
149 static const SG::ConstAccessor<unsigned int> truthClassificationAcc("truthClassification");
150 static const SG::ConstAccessor<MuonLink> recoMuonLinkAcc("recoMuonLink");
151
152 m_nevents += 1;
153
154 static const SG::ConstAccessor<uint8_t> nprecLayersAcc("nprecLayers");
155
156 for (const auto truthMu : *TruthMuons) {
157 MuonLink link;
158 const int theType = truthTypeAcc(*truthMu);
159 const int theOrigin = truthOriginAcc(*truthMu);
160 const unsigned int theClassification = truthClassificationAcc(*truthMu);
161 ATH_MSG_VERBOSE("Truth muon: pt " << truthMu->pt() << " eta " << truthMu->eta());
162 ATH_MSG_VERBOSE("first loop: type " << theType << " origin " << theOrigin << " classification " << theClassification);
163 if (truthMu->pt() < 2000. || std::abs(truthMu->eta()) > 2.8) continue;
164 if (std::abs(truthMu->eta()) > 2.5)
165 ATH_MSG_VERBOSE(" SA |eta| > 2.5 muon with truth prec layers " << (int)nprecLayersAcc(*truthMu));
166
167 if (std::abs(truthMu->eta()) > 2.5 && (int)nprecLayersAcc(*truthMu) < 2) continue;
168 if (theType != 6 && theType != 7) continue;
169 if (theOrigin == 0 || theOrigin > 17) continue;
170 bool insideID = false;
171 if (std::abs(truthMu->eta()) < 2.0) insideID = true;
172 ATH_MSG_VERBOSE("Accepted Truth muon: pt " << truthMu->pt() << " eta " << truthMu->eta());
173
174 if (!insideID) m_ntruth[0] += 1;
175 if (!insideID) m_ntruth[9] += 1;
176 if (!insideID) m_ntruth[10] += 1;
177 if (insideID)
178 for (int n = 1; n < 6; n++) m_ntruth[n] += 1;
179 if (insideID)
180 for (int n = 7; n < 11; n++) m_ntruth[n] += 1;
181
182 if (truthMu->pt() > 5000.) {
183 if (!insideID) m_ntruth5[0] += 1;
184 if (!insideID) m_ntruth5[9] += 1;
185 if (!insideID) m_ntruth5[10] += 1;
186 if (insideID)
187 for (int n = 1; n < 6; n++) m_ntruth5[n] += 1;
188 if (insideID)
189 for (int n = 7; n < 11; n++) m_ntruth5[n] += 1;
190 }
191
192 if (truthMu->pt() > 10000.) {
193 if (!insideID) m_ntruth10[0] += 1;
194 if (!insideID) m_ntruth10[9] += 1;
195 if (!insideID) m_ntruth10[10] += 1;
196 if (insideID)
197 for (int n = 1; n < 6; n++) m_ntruth10[n] += 1;
198 if (insideID)
199 for (int n = 7; n < 11; n++) m_ntruth10[n] += 1;
200 }
201
202 if (recoMuonLinkAcc.isAvailable(*truthMu)) {
203 link = recoMuonLinkAcc(*truthMu);
204 ATH_MSG_VERBOSE(" link " << link.isValid());
205 if (link.isValid()) {
206 bool loose = false;
207 bool medium = false;
208 bool tight = false;
209 if (((*link)->quality() <= xAOD::Muon_v1::Loose)) loose = true;
210 if (((*link)->quality() <= xAOD::Muon_v1::Medium)) medium = true;
211 if (((*link)->quality() <= xAOD::Muon_v1::Tight)) tight = true;
212 if (!loose) ATH_MSG_WARNING("Muon did not pass Loose WP");
213 if (insideID) {
214 const xAOD::TrackParticle* tp = (*link)->primaryTrackParticle();
215 if (tp) {
216 } else
217 ATH_MSG_VERBOSE("No Track particle found on recoMuonLink");
218 // ID efficiency can only be measured on muons in the container
219
220 m_ntruth[6] += 1;
221 if (truthMu->pt() > 5000.) m_ntruth5[6] += 1;
222 if (truthMu->pt() > 10000.) m_ntruth10[6] += 1;
223
224 bool passesIDcuts = passID(tp, true);
225 ATH_MSG_VERBOSE(" all authors " << (*link)->allAuthors() << " passesIDcuts " << passesIDcuts);
226 if (passesIDcuts != (*link)->passesIDCuts()) {
227 ATH_MSG_DEBUG(" PROBLEM passedIDcuts from xAOD muon: " << (*link)->passesIDCuts()
228 << " BUT MuonPerformancAlg code gives " << passesIDcuts);
229 }
230 // Use xAOD Muon ID hit selection cuts
231 passesIDcuts = (*link)->passesIDCuts();
232 if (passesIDcuts) {
233 if (nprecLayersAcc(*truthMu) > 0) {
234 m_ntruth[11] += 1;
235 if (truthMu->pt() > 5000.) m_ntruth5[11] += 1;
236 if (truthMu->pt() > 10000.) m_ntruth10[11] += 1;
237 }
238 if (loose) {
239 m_nfound[10] += 1;
240 } else
241 print(" Muon not found by Loose ", truthMu);
242 if (medium) {
243 m_nfound[9] += 1;
244 } else if (loose)
245 print(" Muon not found by Medium ", truthMu);
246 if (tight) {
247 m_nfound[8] += 1;
248 } else if (medium)
249 print(" Muon not found by Tight ", truthMu);
250 m_nfound[6] += 1;
251 if (truthMu->pt() > 5000.) {
252 if (loose) m_nfound5[10] += 1;
253 if (medium) m_nfound5[9] += 1;
254 if (tight) m_nfound5[8] += 1;
255 m_nfound5[6] += 1;
256 }
257 if (truthMu->pt() > 10000.) {
258 if (loose) m_nfound10[10] += 1;
259 if (medium) m_nfound10[9] += 1;
260 if (tight) m_nfound10[8] += 1;
261 m_nfound10[6] += 1;
262 }
263 // CaloTag or Calolikelihood
264 if (((*link)->allAuthors() & 64 * 4) || ((*link)->allAuthors() & 64 * 8)) {
265 m_nfound[5] += 1;
266 if (truthMu->pt() > 5000.) m_nfound5[5] += 1;
267 if (truthMu->pt() > 10000.) m_nfound10[5] += 1;
268 } else
269 print(" Muon not found by CaloTag and Calolikelihood ", truthMu);
270 // MuidSA
271 if (((*link)->allAuthors() & 32)) {
272 m_nfound[7] += 1;
273 if (truthMu->pt() > 5000.) m_nfound5[7] += 1;
274 if (truthMu->pt() > 10000.) m_nfound10[7] += 1;
275 } else if (!((*link)->allAuthors() & 2))
276 print(" Muon not found by MuidSA ", truthMu);
277 // MuTag or MuTagIMO
278 if (((*link)->allAuthors() & 8) || ((*link)->allAuthors() & 16)) {
279 m_nfound[4] += 1;
280 if (truthMu->pt() > 5000.) m_nfound5[4] += 1;
281 if (truthMu->pt() > 10000.) m_nfound10[4] += 1;
282 } else
283 print(" Muon not found by MuTagIMO ", truthMu);
284 // MuGirl
285 if (((*link)->allAuthors() & 64)) {
286 m_nfound[3] += 1;
287 if (truthMu->pt() > 5000.) m_nfound5[3] += 1;
288 if (truthMu->pt() > 10000.) m_nfound10[3] += 1;
289 } else
290 print(" Muon not found by MuGirl ", truthMu);
291 // MuidCo
292 if (((*link)->allAuthors() & 2)) {
293 m_nfound[2] += 1;
294 if (truthMu->pt() > 5000.) m_nfound5[2] += 1;
295 if (truthMu->pt() > 10000.) m_nfound10[2] += 1;
296 } else
297 print(" Muon not found by MuidCo ", truthMu);
298 // MuidCo || STACO || Combined
299 if (((*link)->allAuthors() & 2) || ((*link)->allAuthors() & 4) ||
300 (*link)->muonType() == xAOD::Muon::MuonType::Combined) {
301 m_nfound[1] += 1;
302 if (truthMu->pt() > 5000.) m_nfound5[1] += 1;
303 if (truthMu->pt() > 10000.) m_nfound10[1] += 1;
304 if (nprecLayersAcc(*truthMu) > 0) {
305 m_nfound[11] += 1;
306 if (truthMu->pt() > 5000.) m_nfound5[11] += 1;
307 if (truthMu->pt() > 10000.) m_nfound10[11] += 1;
308 }
309 } else
310 print(" Combined Muon not found ", truthMu);
311 } else {
312 // SA or CB not passing ID cuts
313 if (((*link)->allAuthors() & 32) || (*link)->muonType() == xAOD::Muon::MuonType::Combined) {
314 m_nfound[7] += 1;
315 if (truthMu->pt() > 5000.) m_nfound5[7] += 1;
316 if (truthMu->pt() > 10000.) m_nfound10[7] += 1;
317 } else
318 print(" SA (CB) Muon not found ", truthMu);
319 }
320 }
321 // MuidSA
322 else if (!insideID) {
323 if ((((*link)->allAuthors() & 32)) || ((*link)->allAuthors() & 2) || ((*link)->allAuthors() & 4)) {
324 m_nfound[0] += 1;
325 if (truthMu->pt() > 5000.) m_nfound5[0] += 1;
326 if (truthMu->pt() > 10000.) m_nfound10[0] += 1;
327 } else
328 print(" Muon not found by MuidSA endcap ", truthMu);
329 if (loose) {
330 m_nfound[10] += 1;
331 if (truthMu->pt() > 5000.) m_nfound5[10] += 1;
332 if (truthMu->pt() > 10000.) m_nfound10[10] += 1;
333 } else
334 print(" Muon not found by Loose endcap ", truthMu);
335 if (medium) {
336 m_nfound[9] += 1;
337 if (truthMu->pt() > 5000.) m_nfound5[9] += 1;
338 if (truthMu->pt() > 10000.) m_nfound10[9] += 1;
339 } else if (loose)
340 print(" Muon not found by Medium endcap ", truthMu);
341 }
342 } else {
343 print(" No link Muon not found by CaloTag and Calolikelihood ", truthMu);
344 print(" No link Muon not found by MuidSA ", truthMu);
345 print(" No link Muon not found by MuTagIMO ", truthMu);
346 print(" No link Muon not found by MuGirl ", truthMu);
347 print(" No link Muon not found by MuidCo ", truthMu);
348 print(" No link Combined Muon not found ", truthMu);
349 }
350 } // end valid link
351 }
352
353 for (const auto truthMu : *TruthMuons) {
354 MuonLink link;
355 if (truthMu->pt() < 2000. || std::abs(truthMu->eta()) > 3.) continue;
356 const int theType = truthTypeAcc(*truthMu);
357 const int theOrigin = truthOriginAcc(*truthMu);
358 if (theType != 6 && theType != 7) continue;
359 if (theOrigin == 0 || theOrigin > 17) continue;
360 if (std::abs(truthMu->eta()) > 2.5 && (int)nprecLayersAcc(*truthMu) < 2) continue;
361 bool insideID = false;
362 if (recoMuonLinkAcc.isAvailable(*truthMu)) {
363 link = recoMuonLinkAcc(*truthMu);
364 if (link.isValid()) {
365 const xAOD::TrackParticle* tp = (*link)->primaryTrackParticle();
366 if (tp) {
367 if ((*link)->pt() < 2000. || std::abs((*link)->eta()) > 2.8) continue;
368 if (std::abs((*link)->eta()) < 2.0) insideID = true;
369 bool loose = false;
370 bool medium = false;
371 bool tight = false;
372 if (((*link)->quality() == xAOD::Muon_v1::Loose)) loose = true;
373 if (((*link)->quality() == xAOD::Muon_v1::Medium)) loose = true;
374 if (((*link)->quality() == xAOD::Muon_v1::Tight)) loose = true;
375 if (((*link)->quality() == xAOD::Muon_v1::Medium)) medium = true;
376 if (((*link)->quality() == xAOD::Muon_v1::Tight)) medium = true;
377 if (((*link)->quality() == xAOD::Muon_v1::Tight)) tight = true;
378 if (insideID) {
379 bool passesIDcuts = passID(tp, false);
380 // Use xAOD Muon ID hit selection cuts
381 passesIDcuts = (*link)->passesIDCuts();
382 if (passesIDcuts) {
383 if (loose) m_nfoundr[10] += 1;
384 if (medium) m_nfoundr[9] += 1;
385 if (tight) m_nfoundr[8] += 1;
386 m_nfoundr[6] += 1;
387 if (((*link)->allAuthors() & 64 * 4) || ((*link)->allAuthors() & 64 * 8)) m_nfoundr[5] += 1;
388 if (((*link)->allAuthors() & 32)) m_nfoundr[7] += 1;
389 if (((*link)->allAuthors() & 8) || ((*link)->allAuthors() & 16)) m_nfoundr[4] += 1;
390 if (((*link)->allAuthors() & 64)) m_nfoundr[3] += 1;
391 if (((*link)->allAuthors() & 2)) m_nfoundr[2] += 1;
392 if (((*link)->allAuthors() & 2) || ((*link)->allAuthors() & 4) ||
393 (*link)->muonType() == xAOD::Muon::MuonType::Combined)
394 m_nfoundr[1] += 1;
395 if ((*link)->pt() > 5000.) {
396 if (loose) m_nfoundr5[10] += 1;
397 if (medium) m_nfoundr5[9] += 1;
398 if (tight) m_nfoundr5[8] += 1;
399 m_nfoundr5[6] += 1;
400 if (((*link)->allAuthors() & 64 * 4) || ((*link)->allAuthors() & 64 * 8)) m_nfoundr5[5] += 1;
401 if (((*link)->allAuthors() & 32)) m_nfoundr5[7] += 1;
402 if (((*link)->allAuthors() & 8) || ((*link)->allAuthors() & 16)) m_nfoundr5[4] += 1;
403 if (((*link)->allAuthors() & 64)) m_nfoundr5[3] += 1;
404 if (((*link)->allAuthors() & 2)) m_nfoundr5[2] += 1;
405 if (((*link)->allAuthors() & 2) || ((*link)->allAuthors() & 4) ||
406 (*link)->muonType() == xAOD::Muon::MuonType::Combined)
407 m_nfoundr5[1] += 1;
408 }
409 if ((*link)->pt() > 10000.) {
410 if (loose) m_nfoundr10[10] += 1;
411 if (medium) m_nfoundr10[9] += 1;
412 if (tight) m_nfoundr10[8] += 1;
413 m_nfoundr10[6] += 1;
414 if (((*link)->allAuthors() & 64 * 4) || ((*link)->allAuthors() & 64 * 8)) m_nfoundr10[5] += 1;
415 if (((*link)->allAuthors() & 32)) m_nfoundr10[7] += 1;
416 if (((*link)->allAuthors() & 8) || ((*link)->allAuthors() & 16)) m_nfoundr10[4] += 1;
417 if (((*link)->allAuthors() & 64)) m_nfoundr10[3] += 1;
418 if (((*link)->allAuthors() & 2)) m_nfoundr10[2] += 1;
419 if (((*link)->allAuthors() & 2) || ((*link)->allAuthors() & 4) ||
420 (*link)->muonType() == xAOD::Muon::MuonType::Combined)
421 m_nfoundr10[1] += 1;
422 }
423 } else {
424 if (((*link)->allAuthors() & 32) || (*link)->muonType() == xAOD::Muon::MuonType::Combined) {
425 m_nfoundr[7] += 1;
426 if ((*link)->pt() > 5000.) m_nfoundr5[7] += 1;
427 if ((*link)->pt() > 10000.) m_nfoundr10[7] += 1;
428 }
429 }
430 } else if (!insideID) {
431 if ((((*link)->allAuthors() & 32)) || ((*link)->allAuthors() & 2) || ((*link)->allAuthors() & 4)) {
432 m_nfoundr[0] += 1;
433 if ((*link)->pt() > 5000.) m_nfoundr5[0] += 1;
434 if ((*link)->pt() > 10000.) m_nfoundr10[0] += 1;
435 }
436 if (loose) m_nfoundr[10] += 1;
437 if (medium) m_nfoundr[9] += 1;
438 if ((*link)->pt() > 5000.) {
439 if (loose) m_nfoundr5[10] += 1;
440 if (medium) m_nfoundr5[9] += 1;
441 }
442 if ((*link)->pt() > 10000.) {
443 if (loose) m_nfoundr10[10] += 1;
444 if (medium) m_nfoundr10[9] += 1;
445 }
446 }
447 } else
448 ATH_MSG_VERBOSE("No Track particle found on recoMuonLink");
449 } // not valid muonLink
450 } // no muonLink
451 }
452
454
455 if (!Muons.isValid()) {
456 ATH_MSG_ERROR("Couldn't retrieve Muons container with key: " << m_muonsNameKey.key());
457 return StatusCode::FAILURE;
458 }
459 ATH_MSG_VERBOSE("Retrieved muons " << Muons->size());
460
461 for (const auto mu : *Muons) {
462 if (mu->pt() < 2000. || std::abs(mu->eta()) > 2.8) continue;
463 const xAOD::TrackParticle* tp = mu->primaryTrackParticle();
464
465 if (tp) {
467 bool passesIDcuts = passID(tp, false);
468 // Use xAOD Muon ID hit selection cuts
469 passesIDcuts = mu->passesIDCuts();
470
471 bool insideID = false;
472 if (std::abs(mu->eta()) < 2.0) insideID = true;
474 truthParticleLinkAcc ("truthParticleLink");
475 if (truthParticleLinkAcc.isAvailable(*tp))
476 truthLink = truthParticleLinkAcc(*tp);
477 bool fake = true;
478 if (truthLink.isValid()) {
479 if (selectPdg((*truthLink)->pdgId())) fake = false;
480 }
481 bool loose = false;
482 bool medium = false;
483 bool tight = false;
484 if (mu->quality() == xAOD::Muon_v1::Loose) loose = true;
485 if (mu->quality() == xAOD::Muon_v1::Medium) loose = true;
486 if (mu->quality() == xAOD::Muon_v1::Tight) loose = true;
487 if (mu->quality() == xAOD::Muon_v1::Medium) medium = true;
488 if (mu->quality() == xAOD::Muon_v1::Tight) medium = true;
489 if (mu->quality() == xAOD::Muon_v1::Tight) tight = true;
490 if (insideID) {
491 if (passesIDcuts) {
492 if (loose) m_nreco[10] += 1;
493 if (medium) m_nreco[9] += 1;
494 if (tight) m_nreco[8] += 1;
495 m_nreco[6] += 1;
496 if ((mu->allAuthors() & 64 * 4) || (mu->allAuthors() & 64 * 8)) m_nreco[5] += 1;
497 if ((mu->allAuthors() & 32)) m_nreco[7] += 1;
498 if ((mu->allAuthors() & 8) || (mu->allAuthors() & 16)) m_nreco[4] += 1;
499 if ((mu->allAuthors() & 64)) m_nreco[3] += 1;
500 if ((mu->allAuthors() & 2)) m_nreco[2] += 1;
501 if ((mu->allAuthors() & 2) || (mu->allAuthors() & 4) || mu->muonType() == xAOD::Muon::MuonType::Combined)
502 m_nreco[1] += 1;
503 if (mu->pt() > 5000.) {
504 if (loose) m_nreco5[10] += 1;
505 if (medium) m_nreco5[9] += 1;
506 if (tight) m_nreco5[8] += 1;
507 m_nreco5[6] += 1;
508 if ((mu->allAuthors() & 64 * 4) || (mu->allAuthors() & 64 * 8)) m_nreco5[5] += 1;
509 if ((mu->allAuthors() & 32)) m_nreco5[7] += 1;
510 if ((mu->allAuthors() & 8) || (mu->allAuthors() & 16)) m_nreco5[4] += 1;
511 if ((mu->allAuthors() & 64)) m_nreco5[3] += 1;
512 if ((mu->allAuthors() & 2)) m_nreco5[2] += 1;
513 if ((mu->allAuthors() & 2) || (mu->allAuthors() & 4) || mu->muonType() == xAOD::Muon::MuonType::Combined)
514 m_nreco5[1] += 1;
515 }
516 if (mu->pt() > 10000.) {
517 if (loose) m_nreco10[10] += 1;
518 if (medium) m_nreco10[9] += 1;
519 if (tight) m_nreco10[8] += 1;
520 m_nreco10[6] += 1;
521 if ((mu->allAuthors() & 64 * 4) || (mu->allAuthors() & 64 * 8)) m_nreco10[5] += 1;
522 if ((mu->allAuthors() & 32)) m_nreco10[7] += 1;
523 if ((mu->allAuthors() & 8) || (mu->allAuthors() & 16)) m_nreco10[4] += 1;
524 if ((mu->allAuthors() & 64)) m_nreco10[3] += 1;
525 if ((mu->allAuthors() & 2)) m_nreco10[2] += 1;
526 if ((mu->allAuthors() & 2) || (mu->allAuthors() & 4) || mu->muonType() == xAOD::Muon::MuonType::Combined)
527 m_nreco10[1] += 1;
528 }
529 if (fake) {
530 if ((mu->quality() == xAOD::Muon_v1::Loose)) print(" Fake muon found by Loose ", mu);
531 if ((mu->quality() == xAOD::Muon_v1::Medium)) print(" Fake muon found by Medium ", mu);
532 if ((mu->quality() == xAOD::Muon_v1::Tight)) print(" Fake muon found by Tight ", mu);
533 if ((mu->allAuthors() & 64 * 4) || (mu->allAuthors() & 64 * 8))
534 print(" Fake muon found by CaloTag and Calolikelihood ", mu);
535 if ((mu->allAuthors() & 32)) print(" Fake muon found by MuidSA ", mu);
536 if ((mu->allAuthors() & 8) || (mu->allAuthors() & 16)) print(" Fake muon found by MuTagIMO ", mu);
537 if ((mu->allAuthors() & 64)) print(" Fake muon found by MuGirl ", mu);
538 if ((mu->allAuthors() & 2)) print(" Fake muon found by MuidCo ", mu);
539 if ((mu->allAuthors() & 2) || (mu->allAuthors() & 4) || mu->muonType() == xAOD::Muon::MuonType::Combined)
540 print(" Fake Combined muon ", mu);
541 }
542 } else {
543 if ((mu->allAuthors() & 32) || mu->muonType() == xAOD::Muon::MuonType::Combined) {
544 m_nreco[7] += 1;
545 if (fake) print(" Fake muon found by MuidSA with no ID", mu);
546 if (mu->pt() > 5000.) m_nreco5[7] += 1;
547 if (mu->pt() > 10000.) m_nreco10[7] += 1;
548 }
549 }
550 } else if (!insideID) {
551 if (loose) m_nreco[10] += 1;
552 if (medium) m_nreco[9] += 1;
553 if (loose && fake) print(" Fake muon found by Loose Endcap ", mu);
554 if (medium && fake && !loose) print(" Fake muon found by Medium Endcap ", mu);
555 if (tight && !medium && fake) print(" Fake muon found by Tight Endcap ", mu);
556 if (mu->pt() > 5000.) {
557 if (loose) m_nreco5[10] += 1;
558 if (medium) m_nreco5[9] += 1;
559 }
560 if (mu->pt() > 10000.) {
561 if (loose) m_nreco10[10] += 1;
562 if (medium) m_nreco10[9] += 1;
563 }
564 if (((mu->allAuthors() & 32)) || (mu->allAuthors() & 2) || (mu->allAuthors() & 4)) {
565 m_nreco[0] += 1;
566 if (fake) print(" Fake muon found by MuidSA Endcap ", mu);
567 if (mu->pt() > 5000.) m_nreco5[0] += 1;
568 if (mu->pt() > 10000.) m_nreco10[0] += 1;
569 }
570 }
571 }
572 }
573
574 return StatusCode::SUCCESS;
575}
576void MuonPerformanceAlg::print(const std::string& txt, const xAOD::TruthParticle* muon) {
577 // Truth: r 4251 z 3147 theta 0.91843 phi -0.781 q*p(GeV) 1.081e+02 pt(Gev) 8.589e+01
578 // uniqueID 1489 mother 23 production vertex: r 1.06363 z -102.414
579 int q = 1;
580 if (muon->pdgId() > 0) q = -1;
581 double p = sqrt(muon->e() * muon->e() - muon->m() * muon->m());
582 static const SG::ConstAccessor<uint8_t> nprecLayersAcc("nprecLayers");
583 ATH_MSG_DEBUG(txt << " run " << m_runNumber << " event " << m_eventNumber << std::endl
584 << " Truth: pdgId " << muon->pdgId() << " uniqueID " << HepMC::uniqueID(muon) << " eta " << muon->eta() << " phi "
585 << muon->phi() << " q*p (GeV) " << q * p / 1000. << " pt (GeV) " << muon->pt() / 1000. << " precisionLayers "
586 << static_cast<int>(nprecLayersAcc(*muon)));
587}
588void MuonPerformanceAlg::print(const std::string& txt, const xAOD::Muon* muon) {
589 int nprec = 0;
590 uint8_t nPrecision = 0;
591 if (muon->primaryTrackParticleLink().isValid()) {
592 muon->primaryTrackParticle()->summaryValue(nPrecision, xAOD::numberOfPrecisionLayers);
593 nprec = static_cast<int>(nPrecision);
594 }
595 double p = sqrt(muon->e() * muon->e() - muon->m() * muon->m());
596 ATH_MSG_DEBUG(txt << " run " << m_runNumber << " event " << m_eventNumber << std::endl
597 << " eta " << muon->eta() << " phi " << muon->phi() << " q*p (GeV) " << muon->charge() * p / 1000. << " pt (GeV) "
598 << muon->pt() / 1000. << " precisionLayers " << nprec << " nr segments " << muon->nMuonSegments());
599}
600
602 std::ofstream fileOutput;
603 std::string outfile = "muonPerformance_xAOD.txt";
604 fileOutput.open(outfile.c_str(), std::ios::trunc);
605 std::ostringstream sout;
606 sout.precision(4);
607
608 unsigned int width = 9;
609 unsigned int precision = 3;
610
611 sout << std::endl;
612 sout << " Summary of the xAOD Muon performance " << std::endl;
613 sout << " Muon type #Truth muons Efficiency #Truth muons Efficiency #Truth muons Efficiency" << std::endl;
614 sout << " (pt>2) (pt>5) (pt>10 GeV/c) " << std::endl;
615 for (unsigned int i = 0; i < 12; ++i) {
616 if (m_ntruth[i] == 0) {
617 sout << " " << std::endl;
618 } else {
619 sout << " " << m_hitCutString[i];
620 sout << std::setw(width) << std::setprecision(precision);
621 sout << static_cast<double>(m_ntruth[i]);
622 sout << " ";
623 sout << std::setw(width) << std::setprecision(precision);
624 sout << static_cast<double>(m_nfound[i]) / static_cast<double>(m_ntruth[i]);
625 sout << std::setw(width) << std::setprecision(precision);
626 sout << static_cast<double>(m_ntruth5[i]);
627 sout << " ";
628 sout << std::setw(width) << std::setprecision(precision);
629 if (m_ntruth5[i] != 0) {
630 sout << static_cast<double>(m_nfound5[i]) / static_cast<double>(m_ntruth5[i]);
631 } else
632 sout << 0.;
633
634 sout << std::setw(width) << std::setprecision(precision);
635 sout << static_cast<double>(m_ntruth10[i]);
636 sout << " ";
637 sout << std::setw(width) << std::setprecision(precision);
638 if (m_ntruth10[i] != 0) {
639 sout << static_cast<double>(m_nfound10[i]) / static_cast<double>(m_ntruth10[i]) << std::endl;
640 } else
641 sout << 0. << std::endl;
642 }
643 }
644 sout << " The efficiency of the ID is calculated inside |eta| < 2 for the MCP ID hit selection cuts (it uses identified - Combined, "
645 "Tagged or CaloTagged - muons with an ID track)"
646 << std::endl;
647 sout << " The efficiencies for CB all, MuidCB, MuGirl, Tag and Calo include the MCP ID cuts" << std::endl;
648 sout << " The Tight, Medium and Loose efficiencies include MCP ID cuts for muons |eta| < 2" << std::endl;
649 sout << " The SA 2.0 for |eta| >2 and SA (no ID) for |eta| < 2 doesnot include MCP ID cuts" << std::endl;
650 sout << " The Combined efficiency is defined ID tracks after MCP cuts and requiring at least 1 muon station at truth level"
651 << std::endl;
652 sout << " Fakes are calculated with the selections listed above" << std::endl;
653 sout << std::endl;
654
655 sout << " Muon type #Fake muons rate #Fake muons rate #Fake muons rate " << std::endl;
656 sout << " (all pt>0,2) (pt>5) (pt>10 GeV/c) " << std::endl;
657 for (unsigned int i = 0; i < 11; ++i) {
658 if (i == 6) continue;
659 if (m_nevents == 0) {
660 sout << " " << std::endl;
661 } else {
662 sout << " " << m_hitCutString[i];
663 sout << std::setw(width) << std::setprecision(precision);
664 sout << static_cast<double>(m_nreco[i] - m_nfoundr[i]);
665 sout << std::setw(width) << std::setprecision(precision);
666 sout << static_cast<double>(m_nreco[i] - m_nfoundr[i]) / static_cast<double>(m_nevents);
667 sout << std::setw(width) << std::setprecision(precision);
668 sout << static_cast<double>(m_nreco5[i] - m_nfoundr5[i]);
669 sout << std::setw(width) << std::setprecision(precision);
670 sout << static_cast<double>(m_nreco5[i] - m_nfoundr5[i]) / static_cast<double>(m_nevents);
671 sout << std::setw(width) << std::setprecision(precision);
672 sout << static_cast<double>(m_nreco10[i] - m_nfoundr10[i]);
673 sout << std::setw(width) << std::setprecision(precision);
674 sout << static_cast<double>(m_nreco10[i] - m_nfoundr10[i]) / static_cast<double>(m_nevents) << std::endl;
675 }
676 }
677 sout << std::endl;
678 fileOutput << sout.str() << std::endl;
679 fileOutput.close();
680 return StatusCode::SUCCESS;
681}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
ElementLink< xAOD::MuonContainer > MuonLink
Helper class to provide constant type-safe access to aux data.
const bool debug
Handle class for reading a decoration on an object.
const double width
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
std::vector< int > m_nfound5
virtual StatusCode finalize() override
std::vector< int > m_nreco5
MuonPerformanceAlg(const std::string &name, ISvcLocator *pSvcLocator)
std::vector< int > m_nreco10
std::vector< int > m_ntruth10
virtual StatusCode initialize() override
std::set< int > m_selectedPdgs
std::vector< int > m_nfoundr5
std::vector< int > m_ntruth5
IntegerArrayProperty m_pdgsToBeConsidered
std::vector< int > m_nfoundr
std::vector< int > m_ntruth
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfo
bool selectPdg(int pdg) const
std::vector< int > m_nfoundr10
SG::ReadDecorHandleKey< xAOD::TruthParticleContainer > m_truthMuonRecoMuonLinkKey
FIXME ReadDecorHandle should not be used to access dynamic variables applied by the algorithm which c...
virtual StatusCode execute() override
SG::ReadDecorHandleKey< xAOD::TruthParticleContainer > m_truthMuonTruthType
SG::ReadHandleKey< xAOD::MuonContainer > m_muonsNameKey
std::vector< int > m_nreco
SG::ReadDecorHandleKey< xAOD::TruthParticleContainer > m_truthMuonTruthClassification
std::vector< std::string > m_hitCutString
std::vector< int > m_nfound10
SG::ReadHandleKey< xAOD::TruthParticleContainer > m_truthMuons
bool passID(const xAOD::TrackParticle *, bool debug) const
std::vector< int > m_nfound
void print(const std::string &txt, const xAOD::TruthParticle *muon)
SG::ReadDecorHandleKey< xAOD::TruthParticleContainer > m_truthMuonTruthOrigin
SG::ReadDecorHandleKey< xAOD::MuonContainer > m_muonTruthParticleKey
bool m_writeToFile
name of external file to write statistics
Helper class to provide constant type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
bool isPresent() const
Is the referenced object present in SG?
int uniqueID(const T &p)
Definition Muons.py:1
TrackParticle_v1 TrackParticle
Reference the current persistent version:
TruthParticle_v1 TruthParticle
Typedef to implementation.
Muon_v1 Muon
Reference the current persistent version:
@ expectInnermostPixelLayerHit
Do we expect a 0th-layer barrel hit for this track?
@ numberOfPixelHoles
number of pixel layers on track with absence of hits [unit8_t].
@ numberOfPrecisionLayers
layers with at least 3 hits [unit8_t].
@ numberOfTRTHits
number of TRT hits [unit8_t].
@ numberOfSCTDeadSensors
number of dead SCT sensors crossed [unit8_t].
@ numberOfInnermostPixelLayerOutliers
number of 0th layer barrel outliers
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfInnermostPixelLayerHits
these are the hits in the 0th pixel barrel layer
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
@ numberOfTRTOutliers
number of TRT outliers [unit8_t].
@ numberOfPixelDeadSensors
number of dead pixel sensors crossed [unit8_t].
@ numberOfSCTHoles
number of SCT holes [unit8_t].