ATLAS Offline Software
Loading...
Searching...
No Matches
MuonTrackPerformanceAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7#include <fstream>
8#include <iostream>
9#include <vector>
10
15#include "TFile.h"
16#include "TrkTrack/Track.h"
17
18MuonTrackPerformanceAlg::MuonTrackPerformanceAlg(const std::string& name, ISvcLocator* pSvcLocator) :
19 AthAlgorithm(name, pSvcLocator),
20 m_eventInfo(nullptr),
21 m_nevents(0),
22 m_ntracks(0),
44 declareProperty("DoHistos", m_doHistos = false);
45 declareProperty("DoSummary", m_doSummary = 0);
46 declareProperty("DoHitResiduals", m_doHitResiduals = 0);
47 declareProperty("DoTrackDebug", m_doTrackDebug = 0);
48 declareProperty("DoTruth", m_doTruth = true);
49 declareProperty("writeToFile", m_writeToFile = true);
50 declareProperty("FileName", m_fileName = "trkPerformance.txt");
51 declareProperty("UsePtCut", m_usePtCut = true);
52 declareProperty("IsCombined", m_isCombined = false);
53 declareProperty("MuonMomentumCutSim", m_momentumCutSim = 2000.);
54 declareProperty("LowMomentumThreshold", m_momentumCut = 2000.);
55 declareProperty("DoSegments", m_doSegments = false);
56 declareProperty("doStau", m_doStau = false);
57 declareProperty("TrackType", m_trackType = 2);
58 declareProperty("ProduceEventListMissedTracks", m_doEventListMissed = 0, "0: off, 1: two station, 2: + one station");
59 declareProperty("ProduceEventListIncompleteTracks", m_doEventListIncomplete = 0,
60 "0: off, 1: missing precision layer, 2: +missing chamber");
61 declareProperty("ProduceEventListFakeTracks", m_doEventListFake = 0, "0: off, 1: high pt, 2: +low pt, 3: +SL");
62 declareProperty("MinMdtHits", m_minMdtHits = 3);
63 declareProperty("MinCscEtaHits", m_minCscEtaHits = 3);
64 declareProperty("MinCscPhiHits", m_minCscPhiHits = 3);
65 declareProperty("MinRPCEtaHits", m_minRpcEtaHits = 1);
66 declareProperty("MinRPCPhiits", m_minRpcPhiHits = 1);
67 declareProperty("MinTGCEtaHits", m_minTgcEtaHits = 1);
68 declareProperty("MinTGCPhiHits", m_minTgcPhiHits = 1);
69 declareProperty("MinSTGCEtaHits", m_minsTgcEtaHits = 1);
70 declareProperty("MinSTGCPhiHits", m_minsTgcPhiHits = 1);
71 declareProperty("MinMMEtaHits", m_minMMEtaHits = 3);
72 declareProperty("ConsideredPDGs", m_pdgsToBeConsidered);
73}
74
76
78
79 ATH_CHECK(m_idHelperSvc.retrieve());
80 ATH_CHECK(m_printer.retrieve());
81 ATH_CHECK(m_edmHelperSvc.retrieve());
82 ATH_CHECK(m_truthTool.retrieve(EnableTool{m_doTruth}));
83
85
86 // add muons
87 if (m_pdgsToBeConsidered.value().empty()) {
88 m_selectedPdgs.insert(13);
89 m_selectedPdgs.insert(-13);
90 } else {
91 // add pdgs
92 for (auto pdg : m_pdgsToBeConsidered.value()) m_selectedPdgs.insert(pdg);
93 msg(MSG::DEBUG) << " PDG codes used for matching";
94 for (auto val : m_selectedPdgs) msg(MSG::DEBUG) << " " << val;
95 msg(MSG::DEBUG) << endmsg;
96 }
97
98 ATH_CHECK(m_trackKey.initialize(!m_trackKey.key().empty()));
99 ATH_CHECK(m_muons.initialize(!m_muons.key().empty()));
100
101 ATH_CHECK(m_eventInfoKey.initialize());
102
103 ATH_CHECK(m_mcEventColl.initialize(m_doTruth));
104 if (!(m_idHelperSvc->hasSTGC() && m_idHelperSvc->hasMM())) m_muonSimData = {"MDT_SDO", "RPC_SDO", "TGC_SDO"};
105 ATH_CHECK(m_muonSimData.initialize(m_doTruth));
106 ATH_CHECK(m_cscSimData.initialize(m_doTruth && m_idHelperSvc->hasCSC()));
107 ATH_CHECK(m_trackRecord.initialize(m_doTruth));
108
109 return StatusCode::SUCCESS;
110}
111
113
115 if (!evInfo.isValid()) {
116 ATH_MSG_WARNING("failed to retrieve EventInfo");
117 return StatusCode::FAILURE;
118 }
119 m_eventInfo = evInfo.cptr();
120 handleTracks();
121
122 ++m_nevents;
123
124 return StatusCode::SUCCESS;
125}
126
129
130 unsigned int nstations = combi.numberOfStations();
131
132 // loop over chambers in combi and extract segments
133 for (unsigned int i = 0; i < nstations; ++i) {
134 // loop over segments in station
135 const Muon::MuonSegmentCombination::SegmentVec* stationSegs = combi.stationSegments(i);
136
137 // check if not empty
138 if (!stationSegs || stationSegs->empty()) continue;
139
140 Muon::MuonSegmentCombination::SegmentVec::const_iterator ipsg = stationSegs->begin();
141 Muon::MuonSegmentCombination::SegmentVec::const_iterator ipsg_end = stationSegs->end();
142 for (; ipsg != ipsg_end; ++ipsg) {
143 const Muon::MuonSegment* seg = dynamic_cast<const Muon::MuonSegment*>((*ipsg).get());
144
145 if (!seg) {
146 ATH_MSG_WARNING("MuonSegmentCombination contains a segment that is not a MuonSegment!!");
147 return false;
148 }
149 }
150 }
151
152 return true;
153}
154
156 std::unique_ptr<TrackCollection> allTracks = std::make_unique<TrackCollection>();
157 if (!m_trackKey.key().empty()) { // MS tracks
159 if (!trackCol.isValid()) {
160 ATH_MSG_WARNING(" Could not find tracks at " << m_trackKey.key());
161 return false;
162 }
164 ATH_MSG_DEBUG(" Retrieved " << trackCol->size() << " tracks from " << trackCol.key());
165 m_ntracks += trackCol->size();
166
167 if (m_doTruth) { handleTrackTruth(*trackCol); }
168
169 if ((msgLvl(MSG::DEBUG) || m_doSummary >= 2) && !m_doTruth) { doSummary(*trackCol); }
170 } else {
172 if (!muons.isValid()) {
173 ATH_MSG_WARNING("could not find muons");
174 return false;
175 }
176 if (m_doStau)
177 m_trackTypeString = "MuGirlStauCombinedTracks";
178 else {
179 if (m_isCombined)
180 m_trackTypeString = "CombinedMuonTracks";
181 else {
182 if (m_trackType == (int)xAOD::Muon::MSOnlyExtrapolatedMuonSpectrometerTrackParticle)
183 m_trackTypeString = "MSOnlyExtrapolatedMuonTracks";
184 else
185 m_trackTypeString = "ExtrapolatedMuonTracks";
186 }
187 }
188 for (auto muon : *muons) {
189 if (!m_doStau) {
190 // if combined and not stau, only take MuidCo and MuGirl
191 if (m_isCombined && muon->author() != 1 && muon->author() != 6) continue;
192 if (!m_isCombined) {
193 // only MuidCo, MuidSA, and STACO will have MSOnlyExtrapolated tracks
194 if (m_trackType == xAOD::Muon::MSOnlyExtrapolatedMuonSpectrometerTrackParticle && muon->author() != 1 &&
195 muon->author() != 5 && muon->author() != 2)
196 continue;
197 // MuGirl should also have ME tracks
198 if (m_trackType == xAOD::Muon::ExtrapolatedMuonSpectrometerTrackParticle && muon->author() != 1 &&
199 muon->author() != 5 && muon->author() != 2 && muon->author() != 6)
200 continue;
201 }
202 } else {
203 // only staus
204 if (muon->author() != 7) continue;
205 }
206 // TrackCollection is a DataVector so allTracks takes ownership of these copies
207 const xAOD::TrackParticle* tp = muon->trackParticle((xAOD::Muon::TrackParticleType)m_trackType);
208 if (!tp) {
209 // possible that MS-only track doesn't exist for combined muon, if initial extrapolation fails but combined fit succeeds
210 // otherwise, the track particle should be there, throw a warning
211 if (m_trackType == xAOD::Muon::MSOnlyExtrapolatedMuonSpectrometerTrackParticle)
212 ATH_MSG_DEBUG("no track particle of type " << m_trackType << " for muon with author " << muon->author() << " and pT "
213 << muon->pt());
214 else
215 ATH_MSG_WARNING("no track particle of type " << m_trackType << " for muon with author " << muon->author() << " and pT "
216 << muon->pt());
217 continue;
218 }
219 if (tp->track()) {
220 m_ntracks++;
221 allTracks->push_back(new Trk::Track(*tp->track()));
222 } else
223 ATH_MSG_WARNING("no track for this trackParticle, skipping");
224 }
225 ATH_MSG_DEBUG("got " << allTracks->size() << " tracks");
226
227 if (m_doTruth) { handleTrackTruth(*allTracks.get()); }
228
229 if ((msgLvl(MSG::DEBUG) || m_doSummary >= 2) && !m_doTruth) { doSummary(*allTracks.get()); }
230 }
231
232 return true;
233}
234
236 if ((!entry.cscHits.empty() || (!entry.mmHits.empty() && !entry.stgcHits.empty())) && entry.mdtHits.empty()) return false;
237 TrackRecord* trackRecord = const_cast<TrackRecord*>(entry.truthTrack);
238 if (!trackRecord) return false;
239 if (m_usePtCut) {
240 if (trackRecord->GetMomentum().perp() < m_momentumCutSim) return false;
241 } else {
242 if (trackRecord->GetMomentum().mag() < m_momentumCutSim) return false;
243 }
244 if (!selectPdg(trackRecord->GetPDGCode())) return false;
245 if (m_isCombined && std::abs(trackRecord->GetMomentum().eta()) > 2.5) return false;
246 int hits = entry.mdtHits.size();
247 if (m_idHelperSvc->hasCSC()) hits += entry.cscHits.size();
248 if (m_idHelperSvc->hasMM()) hits += entry.mmHits.size();
249 return (hits > 4);
250}
251
253 bool didOutput = false;
254
255 unsigned int ntruthTracks(0);
256 unsigned int ntruthTracksSecondary(0);
257
260 std::vector<const MuonSimDataCollection*> muonSimData;
261 for (SG::ReadHandle<MuonSimDataCollection>& simDataMap : m_muonSimData.makeHandles()) {
262 if (!simDataMap.isValid()) {
263 ATH_MSG_WARNING(simDataMap.key() << " not valid");
264 continue;
265 }
266 if (!simDataMap.isPresent()) continue;
267 muonSimData.push_back(simDataMap.cptr());
268 }
269 const CscSimDataCollection* cscSimData = nullptr;
270 if (m_idHelperSvc->hasCSC()) {
272 if (!cscSimDataMap.isValid()) {
273 ATH_MSG_WARNING(cscSimDataMap.key() << " not valid");
274 } else {
275 cscSimData = cscSimDataMap.cptr();
276 }
277 }
279 m_truthTool->createTruthTree(truthTrackCol.cptr(), mcEventCollection.cptr(), muonSimData, cscSimData);
280
281 // map TrackRecord onto entry for printing
282 std::map<const TrackRecord*, Muon::IMuonTrackTruthTool::TruthTreeEntry> truthTrackEntryMap;
283 Muon::IMuonTrackTruthTool::TruthTree::const_iterator tit = truthTree.begin();
284 Muon::IMuonTrackTruthTool::TruthTree::const_iterator tit_end = truthTree.end();
285 for (; tit != tit_end; ++tit) {
286 if (!tit->second.truthTrack) continue;
287
288 truthTrackEntryMap[tit->second.truthTrack] = tit->second;
289
290 if (!goodTruthTrack(tit->second)) continue;
291
292 bool isSec = isSecondary(tit->second);
293
294 if (isSec)
295 ++ntruthTracksSecondary;
296 else
297 ++ntruthTracks;
298 }
299
300 m_ntruthTracks += ntruthTracks;
301 m_ntruthTracksSecondary += ntruthTracksSecondary;
302
303 std::set<const Trk::Track*> matchedTracks;
304 std::set<const Trk::Track*> matchedFakeTracks;
305 std::map<const TrackRecord*, Muon::IMuonTrackTruthTool::MatchResult> bestMatched;
306
307 unsigned int nmatched(0);
308 unsigned int nmatchedSecondary(0);
309
310 Muon::IMuonTrackTruthTool::ResultVec result = m_truthTool->match(truthTree, trackCollection);
311 Muon::IMuonTrackTruthTool::ResultVec::iterator rit = result.begin();
312 Muon::IMuonTrackTruthTool::ResultVec::iterator rit_end = result.end();
313 for (; rit != rit_end; ++rit) {
314 Muon::MuonTrackTruth& trackTruth = rit->second;
315
316 // skip track if not matched to any muon
317 if (!trackTruth.truthTrack) continue;
318
319 // skip match if zero overlap with truth track
320 if (trackTruth.numberOfMatchedHits() == 0) continue;
321
322 std::map<const TrackRecord*, Muon::IMuonTrackTruthTool::TruthTreeEntry>::iterator pos =
323 truthTrackEntryMap.find(trackTruth.truthTrack);
324 if (pos == truthTrackEntryMap.end()) {
325 ATH_MSG_WARNING("Truth track not found in map, this should not happen!!");
326 continue;
327 }
328
329 if (!goodTruthTrack(pos->second)) continue;
330
331 // see whether we already had an track matched to this truth track
332 if (!bestMatched.count(trackTruth.truthTrack)) {
333 // no track found yet, this is the best match
334 bestMatched[trackTruth.truthTrack] = *rit;
335
336 matchedTracks.insert(rit->first);
337
338 bool isSec = isSecondary(pos->second);
339
340 if (isSec)
341 ++nmatchedSecondary;
342 else
343 ++nmatched;
344
345 } else {
347 matchedFakeTracks.insert(rit->first);
348 }
349 }
350
351 m_nmatchedTracks += nmatched;
352 m_nmatchedTracksSecondary += nmatchedSecondary;
353 m_nfakeTracks += trackCollection.size() - nmatched;
354
355 // now we have gathered all links between the tracks and truth.
356 // Let's generate some diagnostics
357
358 EventData eventData;
359 eventData.eventNumber = eventNumber();
360 eventData.eventPosition = m_nevents;
361
362 if (m_doTrackDebug >= 5 || msgLvl(MSG::DEBUG)) {
363 ATH_MSG_INFO("Event " << eventData.eventNumber << " truth tracks " << ntruthTracks);
364 }
365
366 // first loop over truth tracks that were found by reco
367 std::map<const TrackRecord*, Muon::IMuonTrackTruthTool::MatchResult>::iterator mit = bestMatched.begin();
368 std::map<const TrackRecord*, Muon::IMuonTrackTruthTool::MatchResult>::iterator mit_end = bestMatched.end();
369 for (; mit != mit_end; ++mit) {
370 Muon::MuonTrackTruth& truthTrack = mit->second.second;
371 std::map<const TrackRecord*, Muon::IMuonTrackTruthTool::TruthTreeEntry>::iterator pos =
372 truthTrackEntryMap.find(truthTrack.truthTrack);
373 if (pos == truthTrackEntryMap.end()) {
374 ATH_MSG_WARNING("Truth track not found in map, this should not happen!!");
375 continue;
376 }
377
378 // create track summary
379 TrackData* trackData = evaluateTrackTruthOverlap(truthTrack);
380 if (!trackData) continue;
381 addTrackToTrackData(*mit->second.first, *trackData);
382 trackData->truthTrack = new TrackRecord(*mit->first);
383 if (truthTrack.truthTrajectory) {
384 trackData->truthTrajectory = new TruthTrajectory(*truthTrack.truthTrajectory);
386 if (mother) {
387 trackData->motherPdg = mother->pdg_id();
388 if (mother->end_vertex())
389 trackData->productionVertex = new Amg::Vector3D(
390 mother->end_vertex()->position().x(), mother->end_vertex()->position().y(), mother->end_vertex()->position().z());
391 }
393 if (original) {
394 trackData->momentumAtProduction =
395 new Amg::Vector3D(original->momentum().x(), original->momentum().y(), original->momentum().z());
396 }
397 }
398 // check whether track is all ok
399 if (trackData->allOk()) {
400 if (m_doTrackDebug >= 5 || msgLvl(MSG::DEBUG)) {
401 ATH_MSG_INFO(print(*trackData));
402 didOutput = true;
403 }
404 delete trackData;
405 continue;
406 }
407
408 // if we get here something was wrong, let's evaluate what
409 if (trackData->hasMissingChambers()) {
410 if (trackData->isEndcapSLTrack() && trackData->isMissingInner()) {
412 eventData.missingStationMomLoss.push_back(trackData);
413 } else if (trackData->hasMissingLayers()) {
415 eventData.missingStationLayer.push_back(trackData);
416 } else if (trackData->hasMissingLayersTrigger()) {
418 eventData.missingStationLayerTrigger.push_back(trackData);
419 } else {
421 eventData.missingStation.push_back(trackData);
422 }
423 } else if (trackData->hasWrongChambers()) {
424 if (trackData->hasWrongLayers()) {
425 eventData.wrongStationLayer.push_back(trackData);
427 } else if (trackData->hasWrongLayersTrigger()) {
428 eventData.wrongStationLayer.push_back(trackData);
430 } else {
432 eventData.wrongStation.push_back(trackData);
433 }
434 } else {
435 ATH_MSG_WARNING("Unknown problem with matched track " << std::endl << print(*trackData));
436 delete trackData;
437 continue;
438 }
439
440 if (msgLvl(MSG::DEBUG) || m_doTrackDebug >= 4) {
441 ATH_MSG_INFO("Incomplete track in event " << eventInfo() << " nevents " << m_nevents << std::endl
442 << print(*trackData));
443 didOutput = true;
444 }
445 }
446
447 // now the truth tracks that were not found
448 unsigned int nmissed(0);
449 tit = truthTree.begin();
450 tit_end = truthTree.end();
451 for (; tit != tit_end; ++tit) {
452 // skip bad truth tracks
453 if (!goodTruthTrack(tit->second)) continue;
454
455 // check whether truth track was matched
456 if (bestMatched.count(tit->second.truthTrack)) continue;
457
458 TrackData* trackData = createTrackData(tit->second);
459 if (!trackData) {
460 ATH_MSG_WARNING("Failed to create TrackData for truth track");
461 continue;
462 }
463 trackData->truthTrack = new TrackRecord(*tit->second.truthTrack);
464 if (tit->second.truthTrajectory) {
465 trackData->truthTrajectory = new TruthTrajectory(*tit->second.truthTrajectory);
466 HepMC::ConstGenParticlePtr mother = getMother(*tit->second.truthTrajectory);
467 if (mother) {
468 trackData->motherPdg = mother->pdg_id();
469 if (mother->end_vertex())
470 trackData->productionVertex = new Amg::Vector3D(
471 mother->end_vertex()->position().x(), mother->end_vertex()->position().y(), mother->end_vertex()->position().z());
472 }
473 HepMC::ConstGenParticlePtr original = getInitialState(*tit->second.truthTrajectory);
474 if (original) {
475 trackData->momentumAtProduction =
476 new Amg::Vector3D(original->momentum().x(), original->momentum().y(), original->momentum().z());
477 }
478 }
479 if (m_doTrackDebug >= 3 || msgLvl(MSG::DEBUG)) {
480 ATH_MSG_INFO("Truth track not found: " << std::endl << print(*trackData));
481 didOutput = true;
482 }
483 bool isSec = isSecondary(tit->second);
484
485 if (trackData->missingLayers.size() == 1) {
486 if (isSec)
488 else
490 eventData.missingTruthTracksOneStation.push_back(trackData);
491 } else {
492 if (isSec)
494 else
496 eventData.missingTruthTracks.push_back(trackData);
497 }
498 ++nmissed;
499 }
500
501 // sanity check
502 if (ntruthTracks < nmatched)
503 ATH_MSG_WARNING("found more matched tracks than truth tracks: truth " << ntruthTracks << " matched " << nmatched);
504
505 if (nmissed != ntruthTracks - nmatched)
506 ATH_MSG_WARNING("inconsisted number of missed tracks: truth " << ntruthTracks << " matched " << nmatched << " missed " << nmissed);
507
508 // finally print fake tracks
509 TrackCollection::const_iterator trit = trackCollection.begin();
510 TrackCollection::const_iterator trit_end = trackCollection.end();
511 for (; trit != trit_end; ++trit) {
512 if (matchedTracks.count(*trit)) continue;
513
514 double pt = 1e9;
515 if ((**trit).perigeeParameters()) {
516 if (m_usePtCut)
517 pt = (**trit).perigeeParameters()->momentum().perp();
518 else
519 pt = (**trit).perigeeParameters()->momentum().mag();
520 }
521 bool isSL = false;
522 if (m_edmHelperSvc->isSLTrack(**trit)) {
523 pt = 0.;
524 isSL = true;
525 }
526 bool isHighPt = pt > m_momentumCut;
527 bool matchedFake = matchedFakeTracks.count(*trit);
528 std::string fakeType = isHighPt ? "HighPt" : "LowPt";
529 if (isSL) fakeType = "SL";
530 if (matchedFake) fakeType += " (matched)";
531
532 TrackSummary summary;
533 if (matchedFake) summary.trackPars = "(matched) ";
534 summary.trackPars += m_printer->print(**trit);
535 summary.chambers = m_printer->printStations(**trit);
536
537 TrackData* trackData = new TrackData();
538 addTrackToTrackData(**trit, *trackData);
539 if (isHighPt) {
540 eventData.fakeTracks.push_back(trackData);
542 } else if (isSL) {
544 eventData.fakeTracksSL.push_back(trackData);
545 } else {
547 eventData.fakeTracksLowPt.push_back(trackData);
548 }
549
550 if (m_doTrackDebug >= 3 || msgLvl(MSG::DEBUG)) {
551 msg() << MSG::INFO << "Fake track " << fakeType << ": " << std::endl
552 << summary.trackPars << " " << summary.chambers << std::endl;
553 didOutput = true;
554 }
555 }
556 if (didOutput) { msg() << MSG::INFO << endmsg; }
557
558 if (!eventData.goodEvent()) m_badEvents.push_back(eventData);
559
560 return true;
561}
562
565
566 // write to file
567 if (m_writeToFile) {
568 std::string outfile = "trkPerformance_";
569 outfile.append(m_trackTypeString);
570 outfile.append(".txt");
571 m_fileOutput.open(outfile.c_str(), std::ios::trunc);
572
574
575 m_fileOutput.close();
576 }
577
578 if (m_doTruth && m_doTrackDebug >= 1) {
582 }
583
584 std::vector<EventData>::iterator eit = m_badEvents.begin();
585 std::vector<EventData>::iterator eit_end = m_badEvents.end();
586 for (; eit != eit_end; ++eit) { clearEvent(*eit); }
587
588 return StatusCode::SUCCESS;
589}
590
592 if (!m_eventInfo) return -1;
593 return m_eventInfo->eventNumber();
594}
595
596std::string MuonTrackPerformanceAlg::eventInfo() const { return std::to_string(eventNumber()); }
597
598void MuonTrackPerformanceAlg::doSummary(const TrackCollection& trackCollection) const {
599 msg() << " Summarizing tracks in event " << eventInfo() << " nevents " << m_nevents;
600 if (trackCollection.empty())
601 msg() << " : no tracks found" << endmsg;
602 else {
603 msg() << " : " << trackCollection.size() << " tracks found " << std::endl;
604 TrackCollection::const_iterator tit = trackCollection.begin();
605 TrackCollection::const_iterator tit_end = trackCollection.end();
606 for (; tit != tit_end; ++tit) {
607 if (m_doHitResiduals > 0) {
608 msg() << m_printer->print(**tit) << " " << m_printer->printStations(**tit) << std::endl;
609 msg() << m_printer->printMeasurements(**tit);
610 } else {
611 msg() << m_printer->print(**tit) << " " << m_printer->printStations(**tit);
612 }
613 // should finish with an 'endmsg' else the buffer does not get flushed.
614 if (tit == tit_end - 1)
615 msg() << endmsg;
616 else
617 msg() << std::endl;
618 }
619 }
620}
621
623 msg() << " Summarizing tracks in event " << eventInfo() << " nevents " << m_nevents;
624 if (truthTracks.empty())
625 msg() << " : no truth tracks" << endmsg;
626 else {
627 msg() << " : " << truthTracks.size() << " truth tracks found " << std::endl;
628 Muon::IMuonTrackTruthTool::TruthTree::const_iterator tit = truthTracks.begin();
629 Muon::IMuonTrackTruthTool::TruthTree::const_iterator tit_end = truthTracks.end();
630 for (; tit != tit_end; ++tit) {
631 msg() << print(tit->second);
632 // should finish with an 'endmsg' else the buffer does not get flushed.
633 Muon::IMuonTrackTruthTool::TruthTree::const_iterator tit_temp = tit;
634 if (++tit_temp == tit_end)
635 msg() << endmsg;
636 else
637 msg() << std::endl;
638 }
639 }
640}
641
643 std::ostringstream sout;
644 if (!trackTruth.truthTrack) {
645 sout << " No TrackRecord found! ";
646 return sout.str();
647 }
648
649 TrackRecord& trackRecord = const_cast<TrackRecord&>(*trackTruth.truthTrack);
650 double charge = trackRecord.GetPDGCode() < 0 ? +1 : -1;
651
652 // keep track of which chambers are present
653 std::map<Identifier, std::pair<int, int> > precisionIds;
654 std::map<Identifier, std::pair<int, int> > triggerIds;
655 std::map<Identifier, std::pair<int, int> > nhitsCompIds;
656
657 unsigned int neta = 0;
658 unsigned int netaTrig = 0;
659 unsigned int nphi = 0;
660
661 std::set<Identifier> allIds;
662 MuonSimDataCollection::const_iterator mit = trackTruth.mdtHits.begin();
663 MuonSimDataCollection::const_iterator mit_end = trackTruth.mdtHits.end();
664 for (; mit != mit_end; ++mit) allIds.insert(mit->first);
665
666 if (m_idHelperSvc->hasCSC()) {
667 CscSimDataCollection::const_iterator cit = trackTruth.cscHits.begin();
668 CscSimDataCollection::const_iterator cit_end = trackTruth.cscHits.end();
669 for (; cit != cit_end; ++cit) allIds.insert(m_idHelperSvc->layerId(cit->first));
670 }
671 if (m_idHelperSvc->hasSTGC()) {
672 mit = trackTruth.stgcHits.begin();
673 mit_end = trackTruth.stgcHits.end();
674 for (; mit != mit_end; ++mit) allIds.insert(m_idHelperSvc->layerId(mit->first));
675 }
676 if (m_idHelperSvc->hasMM()) {
677 mit = trackTruth.mmHits.begin();
678 mit_end = trackTruth.mmHits.end();
679 for (; mit != mit_end; ++mit) allIds.insert(m_idHelperSvc->layerId(mit->first));
680 }
681
682 mit = trackTruth.rpcHits.begin();
683 mit_end = trackTruth.rpcHits.end();
684 for (; mit != mit_end; ++mit) allIds.insert(m_idHelperSvc->layerId(mit->first));
685
686 mit = trackTruth.tgcHits.begin();
687 mit_end = trackTruth.tgcHits.end();
688 for (; mit != mit_end; ++mit) allIds.insert(m_idHelperSvc->layerId(mit->first));
689
690 std::set<Identifier>::iterator it = allIds.begin();
691 std::set<Identifier>::iterator it_end = allIds.end();
692 for (; it != it_end; ++it) {
693 Identifier id = *it;
694 Identifier chId = m_idHelperSvc->chamberId(id);
695 bool measuresPhi = m_idHelperSvc->measuresPhi(id);
696 if (measuresPhi) {
697 ++nhitsCompIds[chId].first;
698 } else {
699 ++nhitsCompIds[chId].second;
700 }
701
702 if (m_idHelperSvc->isTrigger(chId)) {
703 if (measuresPhi) {
704 ++triggerIds[chId].first;
705 ++nphi;
706 } else {
707 ++triggerIds[chId].second;
708 ++netaTrig;
709 }
710 continue;
711 }
712 if (measuresPhi) {
713 ++precisionIds[chId].first;
714 ++nphi;
715 } else {
716 ++precisionIds[chId].second;
717 ++neta;
718 }
719 }
720 sout << "Truth: hits " << std::setw(5) << neta + nphi + netaTrig << " r " << (int)trackRecord.GetPosition().perp() << " z "
721 << (int)trackRecord.GetPosition().z() << std::setprecision(5) << " phi " << trackRecord.GetMomentum().phi() << " theta "
722 << trackRecord.GetMomentum().theta() << std::setw(6) << " q*mom " << (int)trackRecord.GetMomentum().mag() * charge << " pt "
723 << std::setw(5) << (int)trackRecord.GetMomentum().perp();
724 if (std::abs(trackRecord.GetPDGCode()) != 13) sout << " pdg " << trackRecord.GetPDGCode();
725
726 if (trackTruth.truthTrajectory) {
728 if (mother) { sout << " mother " << mother->pdg_id(); }
729 }
730
731 sout << " Eta hits " << neta << " phi " << nphi << " eta trig " << netaTrig << std::endl;
732 std::map<Identifier, std::pair<int, int> >::iterator iit = precisionIds.begin();
733 std::map<Identifier, std::pair<int, int> >::iterator iit_end = precisionIds.end();
734 for (; iit != iit_end; ++iit) {
735 sout.setf(std::ios::left);
736 sout << " " << std::setw(32) << m_idHelperSvc->toStringChamber(iit->first) << " hits: eta " << std::setw(3) << iit->second.second
737 << " phi " << std::setw(3) << iit->second.first << std::endl;
738 }
739 iit = triggerIds.begin();
740 iit_end = triggerIds.end();
741 for (; iit != iit_end; ++iit) {
742 sout << " " << std::setw(32) << m_idHelperSvc->toStringChamber(iit->first) << " hits: eta " << std::setw(3)
743 << nhitsCompIds[iit->first].second << " phi " << std::setw(3) << nhitsCompIds[iit->first].first << " stations: Eta "
744 << iit->second.second << " Phi " << iit->second.first << std::endl;
745 }
746
747 return sout.str();
748}
749
751 const std::vector<MuonTrackPerformanceAlg::TrackData*>& tracks, const std::string& message) const {
752 std::ostringstream sout;
753 if (!tracks.empty()) {
754 sout << " Event " << event.eventNumber << " position in file " << event.eventPosition << " has " << tracks.size() << " " << message
755 << std::endl;
756 std::vector<TrackData*>::const_iterator it = tracks.begin();
757 std::vector<TrackData*>::const_iterator it_end = tracks.end();
758 for (; it != it_end; ++it) { sout << print(**it) << std::endl; }
759 }
760 return sout.str();
761}
762
763std::string MuonTrackPerformanceAlg::print(const MuonTrackPerformanceAlg::EventData& event, const std::vector<const Trk::Track*>& tracks,
764 const std::string& message) const {
765 std::ostringstream sout;
766 if (!tracks.empty()) {
767 sout << " Event " << event.eventNumber << " position in file " << event.eventPosition << " has " << tracks.size() << " " << message
768 << std::endl;
769 std::vector<const Trk::Track*>::const_iterator it = tracks.begin();
770 std::vector<const Trk::Track*>::const_iterator it_end = tracks.end();
771 for (; it != it_end; ++it) { sout << m_printer->print(**it) << std::endl << m_printer->printStations(**it) << std::endl; }
772 }
773 return sout.str();
774}
775
777 std::fstream outputFile;
778 if (m_doEventListIncomplete > 0) {
779 std::string filename = name();
780 filename += "EventListIncompleteTracks.txt";
781 outputFile.open(filename.c_str(), std::ios_base::out | std::ios_base::trunc);
782 }
783
784 msg() << MSG::INFO << "Summarizing events with endcap track without EI layer resulting in momentum loss, total "
785 << m_nmissingStationMomLoss << std::endl;
786 std::vector<EventData>::const_iterator eit = m_badEvents.begin();
787 std::vector<EventData>::const_iterator eit_end = m_badEvents.end();
788 for (; eit != eit_end; ++eit) {
789 if (eit->missingStationMomLoss.empty()) continue;
790 msg() << print(*eit, eit->missingStationMomLoss, " tracks without inner layer in endcap") << std::endl;
791 if (m_doEventListIncomplete > 0) outputFile << eit->eventNumber << std::endl;
792 }
793 msg() << endmsg;
794
795 msg() << MSG::INFO << "Summarizing events with track with missing layer, total " << m_nmissingStationLayer << std::endl;
796 eit = m_badEvents.begin();
797 eit_end = m_badEvents.end();
798 for (; eit != eit_end; ++eit) {
799 if (eit->missingStationLayer.empty()) continue;
800 msg() << print(*eit, eit->missingStationLayer, " tracks with a missing layer") << std::endl;
801 if (m_doEventListIncomplete > 0) outputFile << eit->eventNumber << std::endl;
802 }
803 msg() << endmsg;
804
805 msg() << MSG::INFO << "Summarizing events with track with missing chamber, total " << m_nmissingStation << std::endl;
806 eit = m_badEvents.begin();
807 eit_end = m_badEvents.end();
808 for (; eit != eit_end; ++eit) {
809 if (eit->missingStation.empty()) continue;
810 msg() << print(*eit, eit->missingStation, " tracks with a missing chamber") << std::endl;
811 if (m_doEventListIncomplete > 1) outputFile << eit->eventNumber << std::endl;
812 }
813 msg() << endmsg;
814
815 msg() << MSG::INFO << "Summarizing events with track with wrong layer, total " << m_nwrongStationLayer << std::endl;
816 eit = m_badEvents.begin();
817 eit_end = m_badEvents.end();
818 for (; eit != eit_end; ++eit) {
819 if (eit->wrongStation.empty()) continue;
820 msg() << print(*eit, eit->wrongStation, " tracks with a wrong layer") << std::endl;
821 if (m_doEventListIncomplete > 0) outputFile << eit->eventNumber << std::endl;
822 }
823 msg() << endmsg;
824
825 msg() << MSG::INFO << "Summarizing events with track with wrong chamber, total " << m_nwrongStation << std::endl;
826 eit = m_badEvents.begin();
827 eit_end = m_badEvents.end();
828 for (; eit != eit_end; ++eit) {
829 if (eit->wrongStation.empty()) continue;
830 msg() << print(*eit, eit->wrongStation, " tracks with a wrong chamber") << std::endl;
831 if (m_doEventListIncomplete > 0) outputFile << eit->eventNumber << std::endl;
832 }
833 msg() << endmsg;
834
835 msg() << MSG::INFO << "Summarizing events with track with missing trigger layer, total " << m_nmissingStationLayerTrigger << std::endl;
836 eit = m_badEvents.begin();
837 eit_end = m_badEvents.end();
838 for (; eit != eit_end; ++eit) {
839 if (eit->missingStationLayerTrigger.empty()) continue;
840 msg() << print(*eit, eit->missingStationLayerTrigger, " tracks with a missing trigger layer") << std::endl;
841 if (m_doEventListIncomplete > 0) outputFile << eit->eventNumber << std::endl;
842 }
843 msg() << endmsg;
844
845 msg() << MSG::INFO << "Summarizing events with track with wrong trigger layer, total " << m_nwrongStationLayerTrigger << std::endl;
846 eit = m_badEvents.begin();
847 eit_end = m_badEvents.end();
848 for (; eit != eit_end; ++eit) {
849 if (eit->wrongStationLayerTrigger.empty()) continue;
850 msg() << print(*eit, eit->wrongStationLayerTrigger, " tracks with a wrong trigger layer") << std::endl;
851 if (m_doEventListIncomplete > 0) outputFile << eit->eventNumber << std::endl;
852 }
853 msg() << endmsg;
854}
855
857 std::fstream outputFile;
858 if (m_doEventListMissed > 0) {
859 std::string filename = name();
860 filename += "EventListMissedTracks.txt";
861 outputFile.open(filename.c_str(), std::ios_base::out | std::ios_base::trunc);
862 }
863
864 msg() << MSG::INFO << "Summarizing events with missing track, total " << m_nmissedTracks << std::endl;
865 std::vector<EventData>::const_iterator eit = m_badEvents.begin();
866 std::vector<EventData>::const_iterator eit_end = m_badEvents.end();
867 for (; eit != eit_end; ++eit) {
868 if (eit->missingTruthTracks.empty()) continue;
869 msg() << print(*eit, eit->missingTruthTracks, " missing tracks") << std::endl;
870 if (m_doEventListMissed > 0) outputFile << eit->eventNumber << std::endl;
871 }
872 msg() << endmsg;
873
874 msg() << MSG::INFO << "Summarizing events with missing single station track, total " << m_nmissedTracksOneStation << std::endl;
875 eit = m_badEvents.begin();
876 eit_end = m_badEvents.end();
877 for (; eit != eit_end; ++eit) {
878 if (eit->missingTruthTracksOneStation.empty()) continue;
879 msg() << print(*eit, eit->missingTruthTracksOneStation, " missing single station tracks") << std::endl;
880 if (m_doEventListMissed > 1) outputFile << eit->eventNumber << std::endl;
881 }
882 msg() << endmsg;
883}
884
886 std::fstream outputFile;
887 if (m_doEventListFake > 0) {
888 std::string filename = name();
889 filename += "EventListFakeTracks.txt";
890 outputFile.open(filename.c_str(), std::ios_base::out | std::ios_base::trunc);
891 }
892
893 msg() << MSG::INFO << "Summarizing events with fake tracks, high pt, total " << m_nfakeTracksHighPt << std::endl;
894 std::vector<EventData>::const_iterator eit = m_badEvents.begin();
895 std::vector<EventData>::const_iterator eit_end = m_badEvents.end();
896 for (; eit != eit_end; ++eit) {
897 if (eit->fakeTracks.empty()) continue;
898 msg() << print(*eit, eit->fakeTracks, " high pt fake tracks") << std::endl;
899 if (m_doEventListFake > 0) outputFile << eit->eventNumber << std::endl;
900 }
901 msg() << endmsg;
902
903 msg() << MSG::INFO << "Summarizing events with fake tracks, low pt, total " << m_nfakeTracksLowPt << std::endl;
904 eit = m_badEvents.begin();
905 eit_end = m_badEvents.end();
906 for (; eit != eit_end; ++eit) {
907 if (eit->fakeTracksLowPt.empty()) continue;
908 msg() << print(*eit, eit->fakeTracksLowPt, " low pt fake tracks") << std::endl;
909 if (m_doEventListFake > 1) outputFile << eit->eventNumber << std::endl;
910 }
911 msg() << endmsg;
912
913 msg() << MSG::INFO << "Summarizing events with fake tracks, SL, total " << m_nfakeTracksSL << std::endl;
914 eit = m_badEvents.begin();
915 eit_end = m_badEvents.end();
916 for (; eit != eit_end; ++eit) {
917 if (eit->fakeTracksSL.empty()) continue;
918 msg() << print(*eit, eit->fakeTracksSL, " SL fake tracks") << std::endl;
919 if (m_doEventListFake > 2) outputFile << eit->eventNumber << std::endl;
920 }
921 msg() << endmsg;
922}
923
924std::string MuonTrackPerformanceAlg::printTrackCounters(bool doSecondaries) const {
925 std::ostringstream sout;
926 sout.precision(4);
927
928 double evScale = m_nevents != 0 ? 1. / m_nevents : 1.;
929
930 sout << std::endl;
931 sout << "Summarizing results for track collection " << m_trackTypeString << " " << m_nevents << " events: " << std::endl
932 << " number of tracks " << std::setw(12) << m_ntracks << " average per event " << m_ntracks * evScale;
933
934 if (m_doTruth) {
935 unsigned int nmatchedTracks = !doSecondaries ? m_nmatchedTracks : m_nmatchedTracks + m_nmatchedTracksSecondary;
936 unsigned int nmissedTracks = !doSecondaries ? m_nmissedTracks : m_nmissedTracks + m_nmissedTracksSecondary;
937 unsigned int nmissedTracksOneStation =
939 unsigned int ntruthTracks = !doSecondaries ? m_ntruthTracks : m_ntruthTracks + m_ntruthTracksSecondary;
940
941 double trTrkScale = ntruthTracks != 0 ? 1. / ntruthTracks : 1.;
942 double trTrkScaleSec = m_ntruthTracksSecondary != 0 ? 1. / m_ntruthTracksSecondary : 1.;
943
944 sout << std::endl
945 << " number of truth tracks " << std::setw(12) << ntruthTracks << " average per event "
946 << ntruthTracks * evScale << std::endl
947 << " number of good tracks " << std::setw(12) << nmatchedTracks << " average per event "
948 << nmatchedTracks * evScale << std::endl
949 << " number of missed multi station tracks " << std::setw(12) << nmissedTracks << " average per event "
950 << nmissedTracks * evScale << std::endl
951 << " number of missed one station tracks " << std::setw(12) << nmissedTracksOneStation << " average per event "
952 << nmissedTracksOneStation * evScale << std::endl;
953 if (doSecondaries) {
954 sout << " number of secondary truth tracks " << std::setw(12) << m_ntruthTracksSecondary << " average per event "
955 << m_ntruthTracksSecondary * evScale << std::endl
956 << " number of secondary good tracks " << std::setw(12) << m_nmatchedTracksSecondary << " average per event "
957 << m_nmatchedTracksSecondary * evScale << std::endl
958 << " number of secondary missed multi st tracks " << std::setw(12) << m_nmissedTracksSecondary << " average per event "
959 << m_nmissedTracksSecondary * evScale << std::endl
960 << " number of secondary missed one st tracks " << std::setw(12) << m_nmissedTracksOneStationSecondary
961 << " average per event " << m_nmissedTracksOneStationSecondary * evScale << std::endl;
962 }
963 sout << " number of fake tracks " << std::setw(12) << m_nfakeTracks << " average per event "
964 << m_nfakeTracks * evScale << std::endl
965 << " number of high pt fake tracks " << std::setw(12) << m_nfakeTracksHighPt << " average per event "
966 << m_nfakeTracksHighPt * evScale << std::endl
967 << " number of low pt fake tracks " << std::setw(12) << m_nfakeTracksLowPt << " average per event "
968 << m_nfakeTracksLowPt * evScale << std::endl
969 << " number of SL fake tracks " << std::setw(12) << m_nfakeTracksSL << " average per event "
970 << m_nfakeTracksSL * evScale << std::endl
971 << " number of matched fake tracks " << std::setw(12) << m_nmatchedFakeTracks << " average per event "
972 << m_nmatchedFakeTracks * evScale << std::endl
973 << " number of tracks with lost momentum " << std::setw(12) << m_nmissingStationMomLoss
974 << " average per truth track " << m_nmissingStationMomLoss * trTrkScale << std::endl
975 << " number of tracks missing precision layer " << std::setw(12) << m_nmissingStationLayer << " average per truth track "
976 << m_nmissingStationLayer * trTrkScale << std::endl
977 << " number of tracks missing trigger layer " << std::setw(12) << m_nmissingStationLayerTrigger
978 << " average per truth track " << m_nmissingStationLayerTrigger * trTrkScale << std::endl
979 << " number of tracks missing chamber " << std::setw(12) << m_nmissingStation << " average per truth track "
980 << m_nmissingStation * trTrkScale << std::endl
981 << " number of tracks wrong precision layer " << std::setw(12) << m_nwrongStationLayer << " average per truth track "
982 << m_nwrongStationLayer * trTrkScale << std::endl
983 << " number of tracks wrong trigger layer " << std::setw(12) << m_nwrongStationLayerTrigger
984 << " average per truth track " << m_nwrongStationLayerTrigger * trTrkScale << std::endl
985 << " number of tracks wrong chamber " << std::setw(12) << m_nwrongStation << " average per truth track "
986 << m_nwrongStation * trTrkScale << std::endl
987 << " efficiency: " << nmatchedTracks * trTrkScale << " fake rate " << m_nfakeTracks * evScale << " high pt "
988 << m_nfakeTracksHighPt * evScale << " low pt " << m_nfakeTracksLowPt * evScale << " missed track rate (per truth track) "
989 << nmissedTracks * trTrkScale;
990 if (doSecondaries) sout << " secondary efficiency " << m_nmatchedTracksSecondary * trTrkScaleSec;
991 }
992 sout << std::endl;
993
994 return sout.str();
995}
996
997std::pair<int, int> MuonTrackPerformanceAlg::countHitsInChamber(const Identifier& chId, const std::set<Identifier>& hitIds) const {
998 // loop over hits in set, calculate their chID and compare it with the input chamber
999 int nhitsPhi = m_idHelperSvc->isMdt(chId) ? -1 : 0;
1000 int nhitsEta = 0;
1001 std::set<Identifier>::const_iterator it = hitIds.begin();
1002 std::set<Identifier>::const_iterator it_end = hitIds.end();
1003 for (; it != it_end; ++it) {
1004 Identifier ch = m_idHelperSvc->chamberId(*it);
1005 if (ch == chId) {
1006 if (m_idHelperSvc->measuresPhi(*it))
1007 ++nhitsPhi;
1008 else
1009 ++nhitsEta;
1010 }
1011 }
1012 return std::make_pair(nhitsEta, nhitsPhi);
1013}
1014
1015bool MuonTrackPerformanceAlg::insertChamber(const Identifier& chId, const std::set<Identifier>& hits, int minEtaHits, int minPhiHits,
1016 MuonTrackPerformanceAlg::ChamberData& chamberData) const {
1017 // flag whether chamber passes selection
1018 bool passesThreshold = false;
1019
1020 // count eta and phi hits in chamber
1021 std::pair<int, int> missingHits = countHitsInChamber(chId, hits);
1022 if (missingHits.first >= minEtaHits) passesThreshold = true;
1023 if (missingHits.second >= minPhiHits) passesThreshold = true;
1024
1025
1026 // if inside cuts, copy the hits into summary
1027 if (passesThreshold) {
1028 chamberData.chId = chId;
1029 std::set<Identifier>::const_iterator it = hits.begin();
1030 std::set<Identifier>::const_iterator it_end = hits.end();
1031 for (; it != it_end; ++it) {
1032 Identifier ch = m_idHelperSvc->chamberId(*it);
1033 if (ch == chId) {
1034 chamberData.hits.insert(*it);
1035 }
1036 }
1037 }
1038 return passesThreshold;
1039}
1040
1041bool MuonTrackPerformanceAlg::insertTechnology(const std::set<Identifier>& chIds, const std::set<Identifier>& hits, int minEtaHits,
1042 int minPhiHits, std::vector<MuonTrackPerformanceAlg::ChamberData>& chambers) const {
1043 // loop over chambers
1044 std::set<Identifier>::const_iterator it = chIds.begin();
1045 std::set<Identifier>::const_iterator it_end = chIds.end();
1046 for (; it != it_end; ++it) {
1047 ChamberData chData;
1048 if (insertChamber(*it, hits, minEtaHits, minPhiHits, chData)) chambers.push_back(chData);
1049 }
1050 return !chambers.empty();
1051}
1052
1053bool MuonTrackPerformanceAlg::insertStationLayers(const std::set<Identifier>& chIds,
1054 const std::set<Muon::MuonStationIndex::StIndex>& exclusionList,
1055 std::set<Muon::MuonStationIndex::StIndex>& layers) const {
1056 unsigned int inputSize = layers.size();
1057
1058 std::set<Identifier>::const_iterator chit = chIds.begin();
1059 std::set<Identifier>::const_iterator chit_end = chIds.end();
1060 for (; chit != chit_end; ++chit) {
1061 Muon::MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(*chit);
1062 if (!exclusionList.count(stIndex)) layers.insert(stIndex);
1063 }
1064
1065 return inputSize != layers.size();
1066}
1067
1068bool MuonTrackPerformanceAlg::insertStationLayers(const std::vector<MuonTrackPerformanceAlg::ChamberData>& chambers,
1069 const std::set<Muon::MuonStationIndex::StIndex>& exclusionList,
1070 std::set<Muon::MuonStationIndex::StIndex>& layers, bool usePrecision) const {
1071 std::set<Identifier> chIds;
1072 std::vector<ChamberData>::const_iterator chit = chambers.begin();
1073 std::vector<ChamberData>::const_iterator chit_end = chambers.end();
1074 for (; chit != chit_end; ++chit) {
1075 bool isTrigger = m_idHelperSvc->isTrigger(chit->chId);
1076 if ((usePrecision && isTrigger) || (!usePrecision && !isTrigger)) continue;
1077 chIds.insert(m_idHelperSvc->chamberId(chit->chId));
1078 }
1079 return insertStationLayers(chIds, exclusionList, layers);
1080}
1081
1083 TrackData* trackData = new TrackData();
1084
1085 // handle missing chambers
1086 insertTechnology(truthTrack.mdts.missedChambers, truthTrack.mdts.missedHits, m_minMdtHits, 0, trackData->missingChambers);
1087 if (m_idHelperSvc->hasCSC())
1089 trackData->missingChambers);
1090 if (m_idHelperSvc->hasSTGC())
1092 trackData->missingChambers);
1093 if (m_idHelperSvc->hasMM())
1094 insertTechnology(truthTrack.mms.missedChambers, truthTrack.mms.missedHits, m_minMMEtaHits, 0, trackData->missingChambers);
1096 trackData->missingChambers);
1098 trackData->missingChambers);
1099
1100 // handle wrong chambers
1101 insertTechnology(truthTrack.mdts.wrongChambers, truthTrack.mdts.wrongHits, m_minMdtHits, 0, trackData->wrongChambers);
1102 if (m_idHelperSvc->hasCSC())
1104 trackData->wrongChambers);
1105 if (m_idHelperSvc->hasSTGC())
1107 trackData->wrongChambers);
1108 if (m_idHelperSvc->hasMM())
1109 insertTechnology(truthTrack.mms.wrongChambers, truthTrack.mms.wrongHits, m_minMMEtaHits, 0, trackData->wrongChambers);
1112
1113 // handle layer information for precision chambers
1114 std::set<Muon::MuonStationIndex::StIndex> dummyList;
1115 insertStationLayers(truthTrack.mdts.matchedChambers, dummyList, trackData->layers);
1116 if (m_idHelperSvc->hasCSC()) insertStationLayers(truthTrack.cscs.matchedChambers, dummyList, trackData->layers);
1117 if (m_idHelperSvc->hasMM()) insertStationLayers(truthTrack.mms.matchedChambers, dummyList, trackData->layers);
1118
1119 insertStationLayers(trackData->missingChambers, trackData->layers, trackData->missingLayers, true);
1120 insertStationLayers(trackData->wrongChambers, trackData->layers, trackData->wrongLayers, true);
1121
1122 // handle layer information for precision chambers
1123 insertStationLayers(truthTrack.rpcs.matchedChambers, dummyList, trackData->layersTrigger);
1124 insertStationLayers(truthTrack.tgcs.matchedChambers, dummyList, trackData->layersTrigger);
1125 if (m_idHelperSvc->hasSTGC()) insertStationLayers(truthTrack.stgcs.matchedChambers, dummyList, trackData->layersTrigger);
1126
1127 insertStationLayers(trackData->missingChambers, trackData->layersTrigger, trackData->missingLayersTrigger, false);
1128 insertStationLayers(trackData->wrongChambers, trackData->layersTrigger, trackData->wrongLayersTrigger, false);
1129
1130 return trackData;
1131}
1132
1134 std::ostringstream sout;
1135
1136 // bool atIP = false;
1137 // if( trackData.trackPars && trackData.trackPars->associatedSurface().center().mag() < 1000. ) atIP = true;
1138
1139 if (trackData.truthTrack) {
1140 double charge = trackData.truthTrack->GetPDGCode() < 0 ? +1 : -1;
1141 Trk::Perigee perigee(Amg::Vector3D(trackData.truthTrack->GetPosition().x(), trackData.truthTrack->GetPosition().y(),
1142 trackData.truthTrack->GetPosition().z()),
1143 Amg::Vector3D(trackData.truthTrack->GetMomentum().x(), trackData.truthTrack->GetMomentum().y(),
1144 trackData.truthTrack->GetMomentum().z()),
1146 sout << "Truth: " << m_printer->print(perigee); // << " barcode " << trackData.truthTrack->barcode();
1147 if (std::abs(trackData.truthTrack->GetPDGCode()) == 13) {
1148 if (trackData.motherPdg != -1) sout << " mother " << trackData.motherPdg;
1149 } else {
1150 sout << " pdg " << trackData.truthTrack->GetPDGCode();
1151 }
1152 if (trackData.momentumAtProduction) sout << " production p: " << trackData.momentumAtProduction->mag();
1153
1154 // if( trackData.productionVertex ) sout << " production vertex: r " << trackData.productionVertex->perp()
1155 // << " z " << trackData.productionVertex->z();
1156 sout << std::endl;
1157 }
1158
1159 if (trackData.trackPars) {
1160 sout << "Track: " << m_printer->print(*trackData.trackPars) << " chi2/ndof " << trackData.chi2Ndof << std::endl;
1161 if (trackData.trackPars->covariance()) {
1162 double qOverP = std::abs(trackData.trackPars->parameters()[Trk::qOverP]);
1163 double dpp = 0.;
1164 double cov00 = (*trackData.trackPars->covariance())(0, 0);
1165 double cov11 = (*trackData.trackPars->covariance())(1, 1);
1166 double cov22 = (*trackData.trackPars->covariance())(2, 2);
1167 double cov33 = (*trackData.trackPars->covariance())(3, 3);
1168 double cov44 = (*trackData.trackPars->covariance())(4, 4);
1169 if (qOverP > 0) dpp = std::sqrt(cov44) / qOverP;
1170 sout << " error d0 " << std::sqrt(cov00) << " z0 " << std::sqrt(cov11) << " phi (mrad) " << 1000 * std::sqrt(cov22)
1171 << " theta (mrad) " << 1000 * std::sqrt(cov33) << " dp/p " << dpp << std::endl;
1172 }
1173
1174 if (trackData.trackSummary && trackData.trackSummary->muonTrackSummary())
1175 sout << m_printer->print(*trackData.trackSummary->muonTrackSummary()) << std::endl;
1176 }
1177
1178 if (!trackData.missingChambers.empty()) {
1179 sout << " Missing Chambers: " << std::endl;
1180 std::vector<ChamberData>::const_iterator chIt = trackData.missingChambers.begin();
1181 std::vector<ChamberData>::const_iterator chIt_end = trackData.missingChambers.end();
1182 for (; chIt != chIt_end; ++chIt) {
1183 sout << " " << m_idHelperSvc->toStringChamber(chIt->chId) << " hits " << chIt->hits.size() << std::endl;
1184 if (m_doTrackDebug >= 6) {
1185 std::set<Identifier>::const_iterator hit = chIt->hits.begin();
1186 std::set<Identifier>::const_iterator hit_end = chIt->hits.end();
1187 for (; hit != hit_end; ++hit) { sout << " " << m_idHelperSvc->toString(*hit) << std::endl; }
1188 }
1189 }
1190 }
1191
1192 if (!trackData.wrongChambers.empty()) {
1193 sout << " Wrong Chambers: " << std::endl;
1194 std::vector<ChamberData>::const_iterator chIt = trackData.wrongChambers.begin();
1195 std::vector<ChamberData>::const_iterator chIt_end = trackData.wrongChambers.end();
1196 for (; chIt != chIt_end; ++chIt) {
1197 sout << " " << m_idHelperSvc->toStringChamber(chIt->chId) << " hits " << chIt->hits.size() << std::endl;
1198 if (m_doTrackDebug >= 6) {
1199 std::set<Identifier>::const_iterator hit = chIt->hits.begin();
1200 std::set<Identifier>::const_iterator hit_end = chIt->hits.end();
1201 for (; hit != hit_end; ++hit) { sout << " " << m_idHelperSvc->toString(*hit) << std::endl; }
1202 }
1203 }
1204 }
1205
1206 if (!trackData.missingLayers.empty() || !trackData.missingLayersTrigger.empty()) {
1207 sout << " Missing Layers: ";
1208 if (!trackData.missingLayers.empty()) {
1209 sout << " Precision: ";
1210 std::set<Muon::MuonStationIndex::StIndex>::const_iterator it = trackData.missingLayers.begin();
1211 std::set<Muon::MuonStationIndex::StIndex>::const_iterator it_end = trackData.missingLayers.end();
1212 for (; it != it_end; ++it) sout << " " << Muon::MuonStationIndex::stName(*it);
1213 }
1214
1215 if (!trackData.missingLayersTrigger.empty()) {
1216 sout << " Trigger: ";
1217 std::set<Muon::MuonStationIndex::StIndex>::const_iterator it = trackData.missingLayersTrigger.begin();
1218 std::set<Muon::MuonStationIndex::StIndex>::const_iterator it_end = trackData.missingLayersTrigger.end();
1219 for (; it != it_end; ++it) sout << " " << Muon::MuonStationIndex::stName(*it);
1220 }
1221 sout << std::endl;
1222 }
1223
1224 if (!trackData.wrongLayers.empty() || !trackData.wrongLayersTrigger.empty()) {
1225 sout << " TrackData.Wrong Layers: ";
1226 if (!trackData.wrongLayers.empty()) {
1227 sout << " Precision: ";
1228 std::set<Muon::MuonStationIndex::StIndex>::const_iterator it = trackData.wrongLayers.begin();
1229 std::set<Muon::MuonStationIndex::StIndex>::const_iterator it_end = trackData.wrongLayers.end();
1230 for (; it != it_end; ++it) sout << " " << Muon::MuonStationIndex::stName(*it);
1231 }
1232
1233 if (!trackData.wrongLayersTrigger.empty()) {
1234 sout << " Trigger: ";
1235 std::set<Muon::MuonStationIndex::StIndex>::const_iterator it = trackData.wrongLayersTrigger.begin();
1236 std::set<Muon::MuonStationIndex::StIndex>::const_iterator it_end = trackData.wrongLayersTrigger.end();
1237 for (; it != it_end; ++it) sout << " " << Muon::MuonStationIndex::stName(*it);
1238 }
1239 sout << std::endl;
1240 }
1241 return sout.str();
1242}
1243
1245 trackData.trackPars = track.perigeeParameters() ? new Trk::Perigee(*track.perigeeParameters()) : nullptr;
1246 trackData.chi2Ndof = 0.;
1247
1248 if (track.fitQuality() && track.fitQuality()->numberDoF())
1249 trackData.chi2Ndof = track.fitQuality()->chiSquared() / track.fitQuality()->numberDoF();
1250
1251 trackData.trackSummary = track.trackSummary() ? new Trk::TrackSummary(*track.trackSummary()) : nullptr;
1252 if (trackData.trackSummary && !trackData.trackSummary->muonTrackSummary()) {
1253 m_summaryHelperTool->addDetailedTrackSummary(track, *trackData.trackSummary);
1254 }
1255}
1256
1258 const Muon::IMuonTrackTruthTool::TruthTreeEntry& trackTruth) const {
1259 if (!trackTruth.truthTrack) { return nullptr; }
1260
1261 TrackData* trackData = new TrackData();
1262
1263 std::map<Identifier, std::set<Identifier> > chambers;
1264
1265 MuonSimDataCollection::const_iterator mit = trackTruth.mdtHits.begin();
1266 MuonSimDataCollection::const_iterator mit_end = trackTruth.mdtHits.end();
1267 for (; mit != mit_end; ++mit) {
1268 Identifier chId = m_idHelperSvc->chamberId(mit->first);
1269 chambers[chId].insert(mit->first);
1270 }
1271
1272 if (m_idHelperSvc->hasCSC()) {
1273 CscSimDataCollection::const_iterator cit = trackTruth.cscHits.begin();
1274 CscSimDataCollection::const_iterator cit_end = trackTruth.cscHits.end();
1275 for (; cit != cit_end; ++cit) {
1276 Identifier chId = m_idHelperSvc->chamberId(cit->first);
1277 chambers[chId].insert(m_idHelperSvc->layerId(cit->first));
1278 }
1279 }
1280 if (m_idHelperSvc->hasSTGC()) {
1281 mit = trackTruth.stgcHits.begin();
1282 mit_end = trackTruth.stgcHits.end();
1283 for (; mit != mit_end; ++mit) {
1284 Identifier chId = m_idHelperSvc->chamberId(mit->first);
1285 chambers[chId].insert(mit->first);
1286 }
1287 }
1288 if (m_idHelperSvc->hasMM()) {
1289 mit = trackTruth.mmHits.begin();
1290 mit_end = trackTruth.mmHits.end();
1291 for (; mit != mit_end; ++mit) {
1292 Identifier chId = m_idHelperSvc->chamberId(mit->first);
1293 chambers[chId].insert(mit->first);
1294 }
1295 }
1296
1297 mit = trackTruth.rpcHits.begin();
1298 mit_end = trackTruth.rpcHits.end();
1299 for (; mit != mit_end; ++mit) {
1300 Identifier chId = m_idHelperSvc->chamberId(mit->first);
1301 chambers[chId].insert(mit->first);
1302 }
1303
1304 mit = trackTruth.tgcHits.begin();
1305 mit_end = trackTruth.tgcHits.end();
1306 for (; mit != mit_end; ++mit) {
1307 Identifier chId = m_idHelperSvc->chamberId(mit->first);
1308 chambers[chId].insert(mit->first);
1309 }
1310
1311 std::vector<ChamberData> missingChambers;
1312 std::map<Identifier, std::set<Identifier> >::const_iterator chIt = chambers.begin();
1313 std::map<Identifier, std::set<Identifier> >::const_iterator chIt_end = chambers.end();
1314 for (; chIt != chIt_end; ++chIt) {
1315 ChamberData chamberData;
1316 unsigned int minEtaHits = 0;
1317 unsigned int minPhiHits = 0;
1318 if (m_idHelperSvc->isMdt(chIt->first)) {
1319 minEtaHits = m_minMdtHits;
1320 minPhiHits = m_minMdtHits;
1321 } else if (m_idHelperSvc->isRpc(chIt->first)) {
1322 minEtaHits = m_minRpcEtaHits;
1323 minPhiHits = m_minRpcPhiHits;
1324 } else if (m_idHelperSvc->isTgc(chIt->first)) {
1325 minEtaHits = m_minTgcEtaHits;
1326 minPhiHits = m_minTgcPhiHits;
1327 } else if (m_idHelperSvc->issTgc(chIt->first)) {
1328 minEtaHits = m_minsTgcEtaHits;
1329 minPhiHits = m_minsTgcPhiHits;
1330 } else if (m_idHelperSvc->isMM(chIt->first)) {
1331 minEtaHits = m_minMMEtaHits;
1332 minPhiHits = m_minMMEtaHits;
1333 } else if (m_idHelperSvc->isCsc(chIt->first)) {
1334 minEtaHits = m_minCscEtaHits;
1335 minPhiHits = m_minCscPhiHits;
1336 } else {
1337 ATH_MSG_WARNING("unexpected identifier");
1338 continue;
1339 }
1340 if (insertChamber(chIt->first, chIt->second, minEtaHits, minPhiHits, chamberData)) {
1341 trackData->missingChambers.push_back(chamberData);
1342 Muon::MuonStationIndex::StIndex stIndex = m_idHelperSvc->stationIndex(chIt->first);
1343 if (m_idHelperSvc->isTrigger(chIt->first))
1344 trackData->missingLayersTrigger.insert(stIndex);
1345 else
1346 trackData->missingLayers.insert(stIndex);
1347 }
1348 }
1349 return trackData;
1350}
1351
1352void MuonTrackPerformanceAlg::clearTracks(std::vector<const Trk::Track*> tracks) {
1353 std::vector<const Trk::Track*>::const_iterator it = tracks.begin();
1354 std::vector<const Trk::Track*>::const_iterator it_end = tracks.end();
1355 for (; it != it_end; ++it) delete *it;
1356 tracks.clear();
1357}
1358
1359void MuonTrackPerformanceAlg::clearTracks(std::vector<MuonTrackPerformanceAlg::TrackData*> tracks) {
1360 std::vector<TrackData*>::const_iterator it = tracks.begin();
1361 std::vector<TrackData*>::const_iterator it_end = tracks.end();
1362 for (; it != it_end; ++it) { delete *it; }
1363 tracks.clear();
1364}
1365
1367 clearTracks(event.missingTruthTracks);
1368 clearTracks(event.missingTruthTracksOneStation);
1369
1370 clearTracks(event.missingStationMomLoss);
1371 clearTracks(event.missingStationLayer);
1372 clearTracks(event.missingStation);
1373
1374 clearTracks(event.wrongStationLayer);
1375 clearTracks(event.wrongStation);
1376
1377 clearTracks(event.fakeTracks);
1378 clearTracks(event.fakeTracksLowPt);
1379 clearTracks(event.fakeTracksSL);
1380}
1381
1383 std::vector<HepMcParticleLink>::const_reverse_iterator pit = traj.rbegin();
1384 std::vector<HepMcParticleLink>::const_reverse_iterator pit_end = traj.rend();
1385 for (; pit != pit_end; ++pit) {
1386 if (std::abs((*pit)->pdg_id()) != 13) return *pit;
1387 }
1388 return nullptr;
1389}
1390
1392 std::vector<HepMcParticleLink>::const_reverse_iterator pit = traj.rbegin();
1393 std::vector<HepMcParticleLink>::const_reverse_iterator pit_end = traj.rend();
1394 for (; pit != pit_end; ++pit) {
1395 if (std::abs((*pit)->pdg_id()) != 13) {
1396 if (pit != traj.rbegin())
1397 --pit;
1398 else
1399 return nullptr;
1400 return *pit;
1401 }
1402 }
1403 return nullptr;
1404}
1405
1407 if (!truthTrack.truthTrajectory) return false;
1408 return isSecondary(*truthTrack.truthTrajectory);
1409}
1410
1412 if (!entry.truthTrajectory) return false;
1413 return isSecondary(*entry.truthTrajectory);
1414}
1415
1416bool MuonTrackPerformanceAlg::isSecondary(const TruthTrajectory& truthTrajectory) const {
1417 HepMC::ConstGenParticlePtr mother = getMother(truthTrajectory);
1418 if (mother && mother->end_vertex() && mother->end_vertex()->position().perp() > 100.) return true;
1419 return false;
1420}
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
DataVector< Trk::Track > TrackCollection
This typedef represents a collection of Trk::Track objects.
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
HepMC::ConstGenParticlePtr getMother(const TruthTrajectory &traj) const
void addTrackToTrackData(const Trk::Track &track, TrackData &trackData) const
SG::ReadHandleKey< McEventCollection > m_mcEventColl
ToolHandle< Trk::ITrackSummaryHelperTool > m_summaryHelperTool
void clearTracks(std::vector< const Trk::Track * > tracks)
TrackData * createTrackData(const Muon::IMuonTrackTruthTool::TruthTreeEntry &trackTruth) const
create track data object for truth track
std::string print(const Muon::IMuonTrackTruthTool::TruthTreeEntry &trackTruth) const
std::pair< int, int > countHitsInChamber(const Identifier &chId, const std::set< Identifier > &hitIds) const
counts number of eta (first number) and phi (second number in pair) hits in the set of hit IDs in the...
ServiceHandle< Muon::IMuonEDMHelperSvc > m_edmHelperSvc
bool insertChamber(const Identifier &chId, const std::set< Identifier > &hits, int minEtaHits, int minPhiHits, ChamberData &chamberData) const
insert chamber information into ChamberData if hits counts pass cuts, returns true if anything was in...
ToolHandle< Muon::IMuonTrackTruthTool > m_truthTool
bool isSecondary(const Muon::MuonTrackTruth &truthTrack) const
IntegerArrayProperty m_pdgsToBeConsidered
bool goodTruthTrack(const Muon::IMuonTrackTruthTool::TruthTreeEntry &entry) const
std::string m_fileName
name of external file to write statistics
bool handleTrackTruth(const TrackCollection &trackCollection)
SG::ReadHandleKeyArray< MuonSimDataCollection > m_muonSimData
const xAOD::EventInfo * m_eventInfo
pointer to the event info
void doSummary(const TrackCollection &tracks) const
virtual StatusCode finalize() override
virtual StatusCode execute() override
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
SG::ReadHandleKey< TrackRecordCollection > m_trackRecord
SG::ReadHandleKey< CscSimDataCollection > m_cscSimData
MuonTrackPerformanceAlg(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadHandleKey< xAOD::MuonContainer > m_muons
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
SG::ReadHandleKey< TrackCollection > m_trackKey
Location of the input tracks.
bool insertStationLayers(const std::set< Identifier > &chIds, const std::set< Muon::MuonStationIndex::StIndex > &exclusionList, std::set< Muon::MuonStationIndex::StIndex > &layers) const
insert station layers into layer set if they are not in exclusion list
TrackData * evaluateTrackTruthOverlap(const Muon::MuonTrackTruth &truthTrack) const
evaluate track/truth overlap and create the corresponding overlap description object
bool handleSegmentCombi(const Muon::MuonSegmentCombination &combi)
bool insertTechnology(const std::set< Identifier > &chIds, const std::set< Identifier > &hits, int minEtaHits, int minPhiHits, std::vector< ChamberData > &chamberData) const
insert set of chambers into chamber data if hits counts pass cuts, returns true if anything was inser...
virtual StatusCode initialize() override
std::ofstream m_fileOutput
output file
HepMC::ConstGenParticlePtr getInitialState(const TruthTrajectory &traj) const
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
std::vector< EventData > m_badEvents
std::string printTrackCounters(bool doSecondaries=true) const
print all the track counters to a string to provide a summary
std::map< int, TruthTreeEntry > TruthTree
std::vector< MatchResult > ResultVec
Class to hold a set of MuonSegments belonging together.
std::vector< std::unique_ptr< MuonSegment > > SegmentVec
SegmentVec * stationSegments(unsigned int index) const
Access to segments in a given station.
unsigned int numberOfStations() const
Number of stations with segment.
This is the common class for 3D segments used in the muon spectrometer.
std::set< Identifier > wrongHits
std::set< Identifier > missedChambers
std::set< Identifier > wrongChambers
std::set< Identifier > missedHits
std::set< Identifier > matchedChambers
MuonTechnologyTruth cscs
const TrackRecord * truthTrack
MuonTechnologyTruth mms
MuonTechnologyTruth tgcs
std::shared_ptr< const TruthTrajectory > truthTrajectory
MuonTechnologyTruth stgcs
MuonTechnologyTruth rpcs
MuonTechnologyTruth mdts
unsigned int numberOfMatchedHits() const
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
int GetPDGCode() const
PDG Code.
CLHEP::Hep3Vector GetPosition() const
Position.
Definition TrackRecord.h:88
CLHEP::Hep3Vector GetMomentum() const
Momentum.
Definition TrackRecord.h:94
Class describing the Line to which the Perigee refers to.
A summary of the information contained by a track.
const MuonTrackSummary * muonTrackSummary() const
returns a pointer to the MuonTrackSummary if available
A TruthTrajectory is a chain of charged MC particles connected through the mother-daughter relationsh...
Eigen::Matrix< double, 3, 1 > Vector3D
const GenParticle * ConstGenParticlePtr
Definition GenParticle.h:38
StIndex
enum to classify the different station layers in the muon spectrometer
const std::string & stName(StIndex index)
convert StIndex into a string
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ qOverP
perigee
Definition ParamDefs.h:67
TrackParticle_v1 TrackParticle
Reference the current persistent version:
std::vector< TrackData * > missingStationLayerTrigger
std::vector< TrackData * > missingStationMomLoss
std::vector< TrackData * > wrongStationLayer
std::vector< TrackData * > missingStationLayer
std::vector< TrackData * > missingTruthTracksOneStation
std::vector< TrackData * > missingTruthTracks
std::set< Muon::MuonStationIndex::StIndex > wrongLayers
std::set< Muon::MuonStationIndex::StIndex > layersTrigger
std::set< Muon::MuonStationIndex::StIndex > missingLayers
std::set< Muon::MuonStationIndex::StIndex > missingLayersTrigger
std::set< Muon::MuonStationIndex::StIndex > layers
std::set< Muon::MuonStationIndex::StIndex > wrongLayersTrigger
std::vector< ChamberData > missingChambers
std::shared_ptr< const TruthTrajectory > truthTrajectory