ATLAS Offline Software
Loading...
Searching...
No Matches
MuonTrackTruthTool.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 <iostream>
8
19#include "TrkTrack/Track.h"
22
23namespace Muon {
24 using namespace MuonStationIndex;
26 ATH_CHECK(m_idHelperSvc.retrieve());
27 ATH_CHECK(m_printer.retrieve());
29
30 // add muons
31 if (m_pdgsToBeConsidered.value().empty()) {
32 m_selectedPdgs.insert(13);
33 m_selectedPdgs.insert(-13);
34 } else {
35 // add pdgs
36 for (auto pdg : m_pdgsToBeConsidered.value()) { m_selectedPdgs.insert(pdg); }
37 ATH_MSG_DEBUG(" PDG codes used for matching "<<m_selectedPdgs);
38 }
39 return StatusCode::SUCCESS;
40 }
41
42 int MuonTrackTruthTool::manipulateBarCode(int barcode) const { // FIXME This is obsolete now
43 if (m_manipulateBarCode) return barcode % 10000;
44 return barcode;
45 }
46
47 bool MuonTrackTruthTool::SortResultByMatchedHits::operator()(const MuonTrackTruthTool::MatchResult& r1,
48 const MuonTrackTruthTool::MatchResult& r2) const {
49 return operator()(r1.second, r2.second);
50 }
51
52 bool MuonTrackTruthTool::SortResultByMatchedHits::operator()(const MuonTrackTruthTool::SegmentMatchResult& r1,
53 const MuonTrackTruthTool::SegmentMatchResult& r2) const {
54 return operator()(r1.second, r2.second);
55 }
56
58 // if not from same track sort by address (should be unique)
59 if (t1.truthTrack && !t2.truthTrack) return true;
60 if (!t1.truthTrack && t2.truthTrack) return false;
61 if (!t1.truthTrack && !t2.truthTrack) return false;
62 if (HepMC::uniqueID(t1.truthTrack) == HepMC::uniqueID(t2.truthTrack)) return t1.numberOfMatchedHits() > t2.numberOfMatchedHits();
63 return HepMC::uniqueID(t1.truthTrack) < HepMC::uniqueID(t2.truthTrack);
64 }
65
66 MuonTrackTruthTool::ResultVec MuonTrackTruthTool::match(const TruthTree& truth_tree, const TrackCollection& tracks) const {
67 ResultVec result;
68 result.reserve(tracks.size());
69
70 // loop over tracks and match each of them with truth
72 TrackCollection::const_iterator tit_end = tracks.end();
73 for (; tit != tit_end; ++tit) {
74 MuonTrackTruth match = getTruth(truth_tree, **tit);
75 if (!match.truthTrack) continue;
76
77 if (match.numberOfMatchedHits() == 0) continue;
78
79 // create truth association
80 result.emplace_back(*tit, match);
81 }
82
83 // sort result per muon and per number of matched hits
85
86 return result;
87 }
88
89 MuonTrackTruthTool::SegmentResultVec MuonTrackTruthTool::match(const TruthTree& truth_tree,
90 const std::vector<const MuonSegment*>& segments) const {
91 SegmentResultVec result;
92 result.reserve(segments.size());
93
94 // loop over tracks and match each of them with truth
95 std::vector<const MuonSegment*>::const_iterator sit = segments.begin();
96 std::vector<const MuonSegment*>::const_iterator sit_end = segments.end();
97 for (; sit != sit_end; ++sit) {
98 // create truth association
99 result.emplace_back(*sit, getTruth(truth_tree, **sit));
100 }
101
102 // sort result per muon and per number of matched hits
104
105 return result;
106 }
107
108 const MuonTrackTruthTool::TruthTree MuonTrackTruthTool::createTruthTree(const TrackRecordCollection* truthTrackCol,
109 const McEventCollection* mcEventCollection,
110 const std::vector<const MuonSimDataCollection*>& muonSimData,
111 const CscSimDataCollection* cscSimDataMap) const {
112 std::map<int, int> barcode_map;
113 MuonTrackTruthTool::TruthTree truth_tree;
114 if (truthTrackCol->empty()) {
115 ATH_MSG_WARNING(" TrackRecordCollection is empty ");
116 return truth_tree;
117 }
118
119 const HepMC::GenEvent* genEvent = nullptr;
120 if (!mcEventCollection->empty()) {
121 ATH_MSG_VERBOSE("McEventCollection size " << mcEventCollection->size());
122 if (mcEventCollection->size() == 1) genEvent = mcEventCollection->front();
123 }
124
125 ATH_MSG_VERBOSE(" creating truth tree from track record " << truthTrackCol->size());
126
127 TrackRecordConstIterator tr_it = truthTrackCol->begin();
128 TrackRecordConstIterator tr_it_end = truthTrackCol->end();
129 for (; tr_it != tr_it_end; ++tr_it) {
130 int PDGCode((*tr_it).GetPDGCode());
131 int barcode = HepMC::uniqueID(*tr_it);
132 if (!m_matchAllParticles && !selectPdg(PDGCode)) {
133 ATH_MSG_VERBOSE(" discarding truth track: pdg " << PDGCode << " barcode " << barcode);
134 continue;
135 }
136
137 // check whether barcode is already in, skip if that is the case
138 if (barcode_map.count(barcode)) {
139 ATH_MSG_VERBOSE(" barcode " << barcode << " already in map, final state barcode " << barcode_map[barcode]);
140 continue;
141 }
142 ATH_MSG_VERBOSE(" found new particle with pdgid " << PDGCode << " in truth record, barcode " << barcode);
143
144 std::unique_ptr<TruthTrajectory> truthTrajectory;
145 // associate the muon truth with the gen event info
146 if (genEvent) {
147 HepMC::ConstGenParticlePtr genParticle =
148#ifdef HEPMC3
149 (barcode>HepMC::UNDEFINED_ID) ? genEvent->particles().at(barcode-1) : nullptr; // FIXME implement HepMC::id_to_particle/vertex explicitly
150#else
151 genEvent->barcode_to_particle(HepMC::uniqueID(*tr_it));
152#endif
153 if (genParticle) {
154 truthTrajectory = std::make_unique<TruthTrajectory>();
155 m_truthTrajectoryBuilder->buildTruthTrajectory(truthTrajectory.get(), genParticle);
156 if (!truthTrajectory->empty()) {
157 // always use barcode of the 'final' particle in chain in map
158 barcode = HepMC::uniqueID(truthTrajectory->front());
159
160 if (msgLvl(MSG::VERBOSE)) {
161 auto particle = truthTrajectory->front().cptr();
162 ATH_MSG_VERBOSE(" found GenParticle: size " << truthTrajectory->size() << " fs barcode " << barcode << "particle "<< particle);
163 if (particle->production_vertex()) {
164 ATH_MSG_VERBOSE(" vertex: r " << particle->production_vertex()->position().perp() << " z "
165 << particle->production_vertex()->position().z());
166 }
167 }
168
169 // now collect all barcodes beloning to this TruthTrajectory
170 std::vector<HepMcParticleLink>::const_iterator pit = truthTrajectory->begin();
171 std::vector<HepMcParticleLink>::const_iterator pit_end = truthTrajectory->end();
172 for (; pit != pit_end; ++pit) {
173 int code = HepMC::uniqueID(*pit);
174
175 if (msgLvl(MSG::VERBOSE) && code != barcode) {
176 auto particle = (*pit).cptr();
177 ATH_MSG_VERBOSE(" secondary barcode: " << code << "particle "<< particle);
178 if (particle->production_vertex())
179 ATH_MSG_VERBOSE(" vertex: r " <<particle->production_vertex()->position().perp() << " z "
180 << particle->production_vertex()->position().z());
181 // sanity check
182 if (barcode_map.count(code)) ATH_MSG_VERBOSE(" pre-existing barcode " << code);
183 }
184
185 // enter barcode
186 barcode_map[code] = barcode;
187 }
188 } else {
189 ATH_MSG_WARNING(" empty truth trajectory " << barcode);
190 }
191 }
192 } else {
193 // add one to one relation
194 barcode_map[barcode] = barcode;
195 }
196
197 if (truth_tree.count(barcode)) {
198 ATH_MSG_WARNING(" found muon barcode twice in truth record: " << barcode);
199 continue;
200 }
201
202 TruthTreeEntry& entry = truth_tree[barcode];
203 entry.truthTrack = &(*tr_it);
204 // entry.truthTrajectory = truthTrajectory.get();
205 entry.truthTrajectory = std::move(truthTrajectory);
206 // m_truthTrajectoriesToBeDeleted.push_back(std::move(truthTrajectory));
207 }
208
209 // add sim data collections
210 for (const MuonSimDataCollection* simDataMap : muonSimData) { addSimDataToTree(truth_tree, barcode_map, simDataMap); }
211 if (cscSimDataMap) { addCscSimDataToTree(truth_tree, barcode_map, cscSimDataMap); }
212
213 unsigned int ngood(0);
214 std::vector<int> badBarcodes;
215 // erase entries with too few hits or no track record
216 TruthTreeIt it = truth_tree.begin();
217 for (; it != truth_tree.end(); ++it) {
218 bool erase = false;
219 unsigned int nhits = it->second.mdtHits.size() + it->second.rpcHits.size() + it->second.tgcHits.size() +
220 it->second.cscHits.size() + it->second.stgcHits.size() + it->second.mmHits.size();
221 if (!it->second.truthTrack) erase = true;
222 if (nhits < m_minHits) erase = true;
223
224 if (erase) {
225 ATH_MSG_VERBOSE(" Erasing entry: barcode " << HepMC::uniqueID(it->second.truthTrack) << " hits " << nhits);
226 badBarcodes.push_back(it->first);
227 } else {
228 ++ngood;
229 ATH_MSG_VERBOSE(" Keeping entry: barcode " << HepMC::uniqueID(it->second.truthTrack) << " hits " << nhits);
230 }
231 }
232
233 std::vector<int>::iterator badIt = badBarcodes.begin();
234 std::vector<int>::iterator badIt_end = badBarcodes.end();
235 for (; badIt != badIt_end; ++badIt) truth_tree.erase(*badIt);
236
237 if (ngood != truth_tree.size()) {
238 ATH_MSG_WARNING(" Problem cleaning map: size " << truth_tree.size() << " accepted entries " << ngood);
239 }
240
241 if (m_doSummary || msgLvl(MSG::DEBUG)) {
242 ATH_MSG_INFO(" summarizing truth tree: number of particles " << truth_tree.size());
243 TruthTreeIt it = truth_tree.begin();
244 TruthTreeIt it_end = truth_tree.end();
245 for (; it != it_end; ++it) {
246 if (!it->second.truthTrack)
247 ATH_MSG_INFO(" no TrackRecord ");
248 else {
249 ATH_MSG_INFO(" PDG " << it->second.truthTrack->GetPDGCode() << " barcode " << HepMC::uniqueID(it->second.truthTrack));
250 }
251 if (!it->second.mdtHits.empty()) ATH_MSG_INFO(" mdt " << it->second.mdtHits.size());
252 if (!it->second.rpcHits.empty()) ATH_MSG_INFO(" rpc " << it->second.rpcHits.size());
253 if (!it->second.tgcHits.empty()) ATH_MSG_INFO(" tgc " << it->second.tgcHits.size());
254 if (!it->second.cscHits.empty()) ATH_MSG_INFO(" csc " << it->second.cscHits.size());
255 if (!it->second.stgcHits.empty()) ATH_MSG_INFO(" stgc " << it->second.stgcHits.size());
256 if (!it->second.mmHits.empty()) ATH_MSG_INFO(" mm " << it->second.mmHits.size());
257 if (it->second.mdtHits.empty() && it->second.rpcHits.empty() && it->second.tgcHits.empty() && it->second.cscHits.empty() &&
258 it->second.stgcHits.empty() && it->second.mmHits.empty())
259 ATH_MSG_INFO(" no hits ");
260 }
261 }
262
263 return truth_tree;
264 }
265
266 void MuonTrackTruthTool::addSimDataToTree(TruthTree& truth_tree, std::map<int, int>& barcode_map,
267 const MuonSimDataCollection* simDataCol) const {
268 // loop over sim collection and check whether identifiers are on track
269 MuonSimDataCollection::const_iterator it = simDataCol->begin();
270 MuonSimDataCollection::const_iterator it_end = simDataCol->end();
271 for (; it != it_end; ++it) {
272 Identifier id = it->first;
273
274 // loop over deposits
275 std::vector<MuonSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
276 std::vector<MuonSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
277 for (; dit != dit_end; ++dit) {
278 int barcodeIn = HepMC::uniqueID(dit->first);
279 std::map<int, int>::const_iterator bit = barcode_map.find(barcodeIn);
280 if (bit == barcode_map.end()) {
281 ATH_MSG_VERBOSE(" discarding "
282 << " " << m_idHelperSvc->toString(id) << " barcode " << barcodeIn);
283 continue;
284 }
285 // replace barcode with barcode from map
286 int barcode = bit->second;
287
288 TruthTreeIt eit = truth_tree.find(barcode);
289 if (eit == truth_tree.end()) {
290 ATH_MSG_VERBOSE(" discarding "
291 << " " << m_idHelperSvc->toString(id) << " barcode " << barcode);
292 continue;
293 }
294
295 if (m_idHelperSvc->isMdt(id)) {
296 eit->second.mdtHits.insert(*it);
297 } else if (m_idHelperSvc->isRpc(id)) {
298 if (m_idHelperSvc->stationIndex(id) == StIndex::BO && m_idHelperSvc->rpcIdHelper().doubletR(id) == 2) {
299 ATH_MSG_VERBOSE(" Discarding non existing RPC hit " << m_idHelperSvc->toString(id));
300 continue;
301 }
302
303 eit->second.rpcHits.insert(*it);
304 } else if (m_idHelperSvc->isTgc(id)) {
305 eit->second.tgcHits.insert(*it);
306 } else if (m_idHelperSvc->issTgc(id)) {
307 eit->second.stgcHits.insert(*it);
308 } else if (m_idHelperSvc->isMM(id)) {
309 eit->second.mmHits.insert(*it);
310 }
311 if (msgLvl(MSG::VERBOSE)) {
312 ATH_MSG_VERBOSE(" adding hit " << m_idHelperSvc->toString(id) << " barcode " << barcode);
313 if (barcode != barcodeIn) ATH_MSG_VERBOSE(" hit barcode " << barcodeIn);
314 }
315 }
316 }
317 }
318
319 void MuonTrackTruthTool::addCscSimDataToTree(TruthTree& truth_tree, std::map<int, int>& barcode_map,
320 const CscSimDataCollection* simDataCol) const {
321 // loop over sim collection and check whether identifiers are on track
322 CscSimDataCollection::const_iterator it = simDataCol->begin();
323 CscSimDataCollection::const_iterator it_end = simDataCol->end();
324 for (; it != it_end; ++it) {
325 Identifier id = it->first;
326
327 // loop over deposits
328 std::vector<CscSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
329 std::vector<CscSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
330 for (; dit != dit_end; ++dit) {
331 int barcodeIn = HepMC::uniqueID(dit->first);
332 std::map<int, int>::const_iterator bit = barcode_map.find(barcodeIn);
333 if (bit == barcode_map.end()) {
334 ATH_MSG_VERBOSE(" discarding "
335 << " " << m_idHelperSvc->toString(id) << " barcode " << barcodeIn);
336 continue;
337 }
338 // replace barcode with barcode from map
339 int barcode = bit->second;
340
341 TruthTreeIt eit = truth_tree.find(barcode);
342 if (eit == truth_tree.end()) {
343 ATH_MSG_VERBOSE(" discarding "
344 << " " << m_idHelperSvc->toString(id) << " barcode " << barcode);
345 continue;
346 }
347
348 if (msgLvl(MSG::VERBOSE)) {
349 ATH_MSG_VERBOSE(" adding hit " << m_idHelperSvc->toString(id) << " barcode " << barcode);
350 if (barcode != barcodeIn) ATH_MSG_VERBOSE(" hit barcode " << barcodeIn);
351 }
352 eit->second.cscHits.insert(*it);
353 }
354 }
355 }
356
357 MuonTrackTruth MuonTrackTruthTool::getTruth(const TruthTree& truth_tree, const Muon::MuonSegment& segment) const {
358 return getTruth(truth_tree, segment.containedMeasurements(), true);
359 }
360
361 MuonTrackTruth MuonTrackTruthTool::getTruth(const TruthTree& truth_tree, const Trk::Track& track, bool restrictedTruth) const {
362 if (track.measurementsOnTrack()) return getTruth(truth_tree, track.measurementsOnTrack()->stdcont(), restrictedTruth);
363 return {};
364 }
365
366 MuonTrackTruth MuonTrackTruthTool::getTruth(const TruthTree& truth_tree, const std::vector<const MuonSegment*>& segments,
367 bool restrictedTruth) const {
368 std::set<Identifier> ids;
369 std::vector<const Trk::MeasurementBase*> measurements;
370 std::vector<const MuonSegment*>::const_iterator sit = segments.begin();
371 std::vector<const MuonSegment*>::const_iterator sit_end = segments.end();
372 for (; sit != sit_end; ++sit) {
373 std::vector<const Trk::MeasurementBase*>::const_iterator mit = (*sit)->containedMeasurements().begin();
374 std::vector<const Trk::MeasurementBase*>::const_iterator mit_end = (*sit)->containedMeasurements().end();
375 for (; mit != mit_end; ++mit) {
376 const Trk::MeasurementBase* meas = *mit;
377 const Trk::RIO_OnTrack* rot = nullptr;
379 if (!rot) {
380 if (!dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas)) ATH_MSG_WARNING(" Could not get rot from measurement ");
381 continue;
382 }
383 Identifier id = rot->identify();
384 if (!id.is_valid() || !m_idHelperSvc->mdtIdHelper().is_muon(id)) continue;
385 if (ids.count(id)) continue;
386 measurements.push_back(meas);
387 ids.insert(id);
388 }
389 }
390 return getTruth(truth_tree, measurements, restrictedTruth);
391 }
392
393 MuonTrackTruth MuonTrackTruthTool::getTruth(const TruthTree& truth_tree, const std::vector<const Trk::MeasurementBase*>& measurements,
394 bool restrictedTruth) const {
395 MuonTrackTruth bestMatch;
396 bestMatch.truthTrack = nullptr;
397 bestMatch.truthTrajectory = nullptr;
398
399 unsigned int nmatchedHitsBest = 0;
400 // loop over muons and match hits
401 TruthTreeConstIt tit = truth_tree.begin();
402 TruthTreeConstIt tit_end = truth_tree.end();
403 for (; tit != tit_end; ++tit) {
404 unsigned int nhits = tit->second.mdtHits.size() + tit->second.cscHits.size() + tit->second.rpcHits.size() +
405 tit->second.tgcHits.size() + tit->second.stgcHits.size() + tit->second.mmHits.size();
406 if (nhits == 0) continue;
407
408 MuonTrackTruth trackTruth = getTruth(measurements, tit->second, restrictedTruth);
409 unsigned int nmatchedHits = trackTruth.numberOfMatchedHits();
410 ATH_MSG_DEBUG(" performed truth match for particle with barcode: " << tit->first << " overlap " << nmatchedHits << " fraction "
411 << (double)nmatchedHits / (double)nhits);
412 if (nmatchedHits > 0 && nmatchedHits > nmatchedHitsBest) {
413 bestMatch = trackTruth;
414 nmatchedHitsBest = nmatchedHits;
415 }
416 }
417
418 return bestMatch;
419 }
420
421 MuonTrackTruth MuonTrackTruthTool::getTruth(const std::vector<const Trk::MeasurementBase*>& measurements,
422 const TruthTreeEntry& truthEntry, bool restrictedTruth) const {
423 MuonTrackTruth trackTruth;
424 trackTruth.truthTrack = truthEntry.truthTrack;
425 trackTruth.truthTrajectory = truthEntry.truthTrajectory;
426
427 std::vector<const Trk::MeasurementBase*>::const_iterator mit = measurements.begin();
428 std::vector<const Trk::MeasurementBase*>::const_iterator mit_end = measurements.end();
429 for (; mit != mit_end; ++mit) {
430 // check whether state is a measurement
431 const Trk::MeasurementBase* meas = *mit;
432 if (!meas) { continue; }
433
434 const Trk::RIO_OnTrack* rot = nullptr;
436 if (!rot) {
437 if (!dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas)) ATH_MSG_WARNING(" Could not get rot from measurement ");
438 continue;
439 }
440 Identifier id = rot->identify();
441 if (!id.is_valid() || !m_idHelperSvc->mdtIdHelper().is_muon(id)) continue;
442
443 if (m_idHelperSvc->isMdt(id)) {
444 addMdtTruth(trackTruth.mdts, id, *meas, truthEntry.mdtHits);
445 } else if (m_idHelperSvc->isCsc(id)) {
446 addClusterTruth(trackTruth.cscs, id, *meas, truthEntry.cscHits);
447 } else if (m_idHelperSvc->isRpc(id)) {
448 addClusterTruth(trackTruth.rpcs, id, *meas, truthEntry.rpcHits);
449 } else if (m_idHelperSvc->isTgc(id)) {
450 addClusterTruth(trackTruth.tgcs, id, *meas, truthEntry.tgcHits);
451 } else if (m_idHelperSvc->issTgc(id)) {
452 addClusterTruth(trackTruth.stgcs, id, *meas, truthEntry.stgcHits);
453 } else if (m_idHelperSvc->isMM(id)) {
454 addClusterTruth(trackTruth.mms, id, *meas, truthEntry.mmHits);
455 }
456 }
457
458 addMissedHits(trackTruth.mdts, trackTruth.mdts.matchedHits, trackTruth.mdts.matchedChambers, truthEntry.mdtHits, restrictedTruth);
459 addMissedHits(trackTruth.cscs, trackTruth.cscs.matchedHits, trackTruth.cscs.matchedChambers, truthEntry.cscHits, restrictedTruth);
460 addMissedHits(trackTruth.rpcs, trackTruth.rpcs.matchedHits, trackTruth.rpcs.matchedChambers, truthEntry.rpcHits, restrictedTruth);
461 addMissedHits(trackTruth.tgcs, trackTruth.tgcs.matchedHits, trackTruth.tgcs.matchedChambers, truthEntry.tgcHits, restrictedTruth);
462 addMissedHits(trackTruth.stgcs, trackTruth.stgcs.matchedHits, trackTruth.stgcs.matchedChambers, truthEntry.stgcHits,
463 restrictedTruth);
464 addMissedHits(trackTruth.mms, trackTruth.mms.matchedHits, trackTruth.mms.matchedChambers, truthEntry.mmHits, restrictedTruth);
465
466 return trackTruth;
467 }
468
469 void MuonTrackTruthTool::addMissedHits(MuonTechnologyTruth& truth, const std::set<Identifier>& ids, const std::set<Identifier>& chids,
470 const MuonSimDataCollection& simCol, bool restrictedTruth) const {
471 // loop over sim collection and check whether identifiers are on track
472 MuonSimDataCollection::const_iterator it = simCol.begin();
473 MuonSimDataCollection::const_iterator it_end = simCol.end();
474 for (; it != it_end; ++it) {
475 Identifier id = it->first;
476 // for trigger chambers use layer id
477 if (m_idHelperSvc->isTrigger(id) || m_idHelperSvc->isCsc(id)) id = m_idHelperSvc->layerId(id);
478
479 int isOnTrack = ids.count(id);
480 if (isOnTrack) continue;
481
482 // if restricted truth mode, skip if chamber has not hits
483 Identifier chid = m_idHelperSvc->chamberId(id);
484 bool chamberHasHits = chids.count(chid);
485 if (restrictedTruth && !chamberHasHits) continue;
486
487 // loop over deposits
488 std::vector<MuonSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
489 std::vector<MuonSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
490 for (; dit != dit_end; ++dit) {
491 truth.missedHits.insert(id);
492 // only fill a missed chamber if the chamber had no hits
493 if (!chamberHasHits) truth.missedChambers.insert(chid);
494 }
495 }
496 }
497
498 void MuonTrackTruthTool::addMissedHits(MuonTechnologyTruth& truth, const std::set<Identifier>& ids, const std::set<Identifier>& chids,
499 const CscSimDataCollection& simCol, bool restrictedTruth) const {
500 // loop over sim collection and check whether identifiers are on track
501 CscSimDataCollection::const_iterator it = simCol.begin();
502 CscSimDataCollection::const_iterator it_end = simCol.end();
503 for (; it != it_end; ++it) {
504 Identifier id = m_idHelperSvc->layerId(it->first);
505
506 int isOnTrack = ids.count(id);
507 if (isOnTrack) continue;
508
509 // if restricted truth mode, skip if chamber has not hits
510 Identifier chid = m_idHelperSvc->chamberId(id);
511 bool chamberHasHits = chids.count(chid);
512 if (restrictedTruth && !chamberHasHits) continue;
513
514 // loop over deposits
515 std::vector<CscSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
516 std::vector<CscSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
517 for (; dit != dit_end; ++dit) {
518 truth.missedHits.insert(id);
519 // only fill a missed chamber if the chamber had no hits
520 if (!chamberHasHits) truth.missedChambers.insert(chid);
521 }
522 }
523 }
524
526 const MuonSimDataCollection& simCol) const {
527 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(&meas);
528 if (!mdt) {
529 ATH_MSG_WARNING(" dynamic_cast to MdtDriftCircleOnTrack failed for measurement with id " << m_idHelperSvc->toString(id));
530 return;
531 }
532
533 Identifier chid = m_idHelperSvc->chamberId(id);
534
535 // find SimData corresponding to identifier
536 MuonSimDataCollection::const_iterator it = simCol.find(id);
537 if (it == simCol.end()) {
538 truth.wrongHits.insert(id);
539 truth.wrongChambers.insert(chid);
540 return;
541 }
542
543 std::vector<MuonSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
544 std::vector<MuonSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
545 for (; dit != dit_end; ++dit) {
546 double radius = dit->second.firstEntry();
547
548 // check whether SDO and hit have same sign, don't check sign if drift radius < 0.3 mm as it will be badly determined
549 double checkSign = fabs(mdt->driftRadius()) > 0.3 ? radius * mdt->driftRadius() : 1;
550 if (checkSign >= 0) {
551 truth.matchedHits.insert(id);
552 truth.matchedChambers.insert(chid);
553 } else {
554 truth.wrongHits.insert(id);
555 truth.wrongChambers.insert(chid);
556 }
557 }
558 }
559
561 const MuonSimDataCollection& simCol) const {
562 Identifier layid = m_idHelperSvc->layerId(id);
563 Identifier chid = m_idHelperSvc->chamberId(id);
564
565 MuonSimDataCollection::const_iterator it = simCol.end();
566
567 bool goodCluster = false;
568 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(&meas);
569 if (crot) {
570 for (unsigned int i = 0; i < crot->numberOfContainedROTs(); ++i) {
571 const MuonClusterOnTrack* cluster = &crot->rioOnTrack(i);
572 if (!cluster) continue;
573 // find SimData corresponding to identifier
574 it = simCol.find(cluster->identify());
575 if (it != simCol.end()) {
576 goodCluster = true;
577 break;
578 }
579 }
580 } else {
581 // Find SimData corresponding to identifier
582 const Trk::RIO_OnTrack* rot = nullptr;
583 Trk::RoT_Extractor::extract(rot, &meas);
584 const Trk::PrepRawData* prd = rot->prepRawData();
585 if (prd) {
586 // check if an identifier from the list of RDOs is matched to that in the SDO collection
587 const std::vector<Identifier> &rdoList = prd->rdoList();
588 std::vector<Identifier>::const_iterator rit = rdoList.begin();
589 std::vector<Identifier>::const_iterator rit_end = rdoList.end();
590 for (; rit != rit_end; ++rit) {
591 it = simCol.find(*rit);
592 if (it != simCol.end()) {
593 goodCluster = true;
594 break;
595 }
596 }
597 } else {
598 it = simCol.find(id);
599 if (it != simCol.end()) goodCluster = true;
600 }
601 }
602
603 if (!goodCluster || it == simCol.end()) {
604 truth.wrongHits.insert(id);
605 return;
606 }
607
608 std::vector<MuonSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
609 std::vector<MuonSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
610 for (; dit != dit_end; ++dit) {
611 truth.matchedHits.insert(layid);
612 truth.matchedChambers.insert(chid);
613 }
614 }
615
617 const CscSimDataCollection& simCol) const {
618 Identifier layid = m_idHelperSvc->layerId(id);
619 Identifier chid = m_idHelperSvc->chamberId(id);
620 // find SimData corresponding to identifier
621 CscSimDataCollection::const_iterator it = simCol.find(id);
622 if (it == simCol.end()) {
623 truth.wrongHits.insert(layid);
624 truth.wrongChambers.insert(chid);
625 return;
626 }
627
628 std::vector<CscSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
629 std::vector<CscSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
630 for (; dit != dit_end; ++dit) {
631 truth.matchedHits.insert(layid);
632 truth.matchedChambers.insert(chid);
633 }
634 }
635
637 ATH_MSG_DEBUG("getMother() : size = " << traj.size());
638 int pdgFinal = ((traj.empty()) ? -999 : traj.front().cptr()->pdg_id());
639 bool foundBC = false;
640 for (const auto& pit : traj) {
641 if (!pit) continue;
642 if (HepMC::uniqueID(pit) == barcodeIn || foundBC) {
643 foundBC = true;
644 ATH_MSG_DEBUG("getMother() : " << pit );
645#ifdef HEPMC3
646 auto particle = pit.scptr();
647#else
648 auto particle = pit.cptr();
649#endif
650 if (particle->pdg_id() != pdgFinal) { // the first case a track had a different flavour
651 break;
652 }
653 }
654 }
655 return nullptr;
656 }
657
659 bool foundBC = false;
660 for (const auto& pit : traj) {
661 if (!pit) continue;
662 if (HepMC::uniqueID(pit) == barcodeIn || foundBC) {
663 foundBC = true;
664#ifdef HEPMC3
665 auto particle = pit.scptr();
666#else
667 auto particle = pit.cptr();
668#endif
669 if (!MC::isStable(particle)) { // first non final state particle
670 return particle;
671 }
672 }
673 }
674 return nullptr;
675 }
676
677 const std::pair<HepMC::ConstGenParticlePtr, unsigned int> MuonTrackTruthTool::getInitialPair(const TruthTrajectory& traj,
678 const int barcodeIn) const {
679 std::pair<HepMC::ConstGenParticlePtr, unsigned int> thePair(nullptr, 0);
680 unsigned int scat = 0;
681 ATH_MSG_DEBUG("getFirst() : size = " << traj.size());
682 bool foundBC = false;
683 int pdgFinal = 0;
684 double ePrev = 0.;
685 HepMC::ConstGenParticlePtr theFirst{nullptr};
686 for (auto pit = traj.begin(); pit != traj.end(); ++pit) {
687 if (HepMC::uniqueID(*pit) == barcodeIn || foundBC) {
688 auto particle = (*pit).scptr();
689#ifdef HEPMC3
690 if (!foundBC) {
691 foundBC = true;
692 theFirst = particle;
693 pdgFinal = particle->pdg_id();
694 } else {
695 if (particle->pdg_id() == pdgFinal) {
696 const auto& pit_p = *pit;
697 if ((theFirst != pit_p.scptr()) && (particle->momentum().t() != ePrev))
698 ++scat; // if the particle has not changed pdgid after the first step count as scatter. also avoid counting
699 // pure interface changes as scatter
700 } else { // the first time this particle appears
701 --pit; // AV This is confusing
702 theFirst = (*pit).scptr();
703 break;
704 }
705 }
706#else
707 if (!foundBC) {
708 foundBC = true;
709 theFirst = (*pit).cptr();
710 pdgFinal = (*pit)->pdg_id();
711 } else {
712 if ((*pit)->pdg_id() == pdgFinal) {
713 auto pit_p = *pit;
714 if ((theFirst != pit_p.cptr()) && ((*pit).cptr()->momentum().t() != ePrev))
715 ++scat; // if the particle has not changed pdgid after the first step count as scatter. also avoid counting
716 // pure interface changes as scatter
717 } else { // the first time this particle appears
718 --pit;
719 theFirst = (*pit).cptr();
720 break;
721 }
722 }
723#endif
724 ATH_MSG_DEBUG("getFirst() : pt = " << particle->momentum().perp() << " scat = " << scat);
725 ePrev = particle->momentum().t(); // prepare for comparing this entry with the next one
726 }
727 }
728 // sanity check
729 if (theFirst && theFirst->pdg_id() != pdgFinal) ATH_MSG_ERROR("Wrong pdgId association in getFirst()");
730 ATH_MSG_DEBUG("Number of scatters = " << scat << " pdgId = " << pdgFinal);
731
732 thePair.first = theFirst;
733 thePair.second = scat;
734 return thePair;
735 }
736
738 return getInitialPair(traj, barcodeIn).first;
739 }
740
741 unsigned int MuonTrackTruthTool::getNumberOfScatters(const TruthTrajectory& traj, const int barcodeIn) const {
742 return (getInitialPair(traj, barcodeIn)).second;
743 }
744} // namespace Muon
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
ATLAS-specific HepMC functions.
DataVector< Trk::Track > TrackCollection
This typedef represents a collection of Trk::Track objects.
AtlasHitsVector< TrackRecord > TrackRecordCollection
AtlasHitsVector< TrackRecord >::const_iterator TrackRecordConstIterator
bool empty() const
const_iterator begin() const
size_type size() const
const_iterator end() 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.
const T * front() const
Access the first element in the collection as an rvalue.
size_type size() const noexcept
Returns the number of elements in the collection.
bool empty() const noexcept
Returns true if the collection is empty.
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
Class for competing MuonClusters, it extends the Trk::CompetingRIOsOnTrack base class.
unsigned int numberOfContainedROTs() const
Number of RIO_OnTracks to be contained by this CompetingRIOsOnTrack.
const MuonClusterOnTrack & rioOnTrack(unsigned int) const
returns the RIO_OnTrack (also known as ROT) objects depending on the integer
This class represents the corrected MDT measurements, where the corrections include the effects of wi...
double driftRadius() const
Returns the value of the drift radius.
Base class for Muon cluster RIO_OnTracks.
This is the common class for 3D segments used in the muon spectrometer.
std::set< Identifier > wrongHits
std::set< Identifier > matchedHits
std::set< Identifier > missedChambers
std::set< Identifier > wrongChambers
std::set< Identifier > missedHits
std::set< Identifier > matchedChambers
ToolHandle< Trk::ITruthTrajectoryBuilder > m_truthTrajectoryBuilder
MuonTrackTruth getTruth(const TruthTree &truth_tree, const Trk::Track &track, bool restrictedTruth=false) const
get track truth
void addClusterTruth(MuonTechnologyTruth &trackTruth, const Identifier &id, const Trk::MeasurementBase &meas, const MuonSimDataCollection &simCol) const
bool selectPdg(int pdg) const
Gaudi::Property< unsigned int > m_minHits
void addCscSimDataToTree(TruthTree &truth_tree, std::map< int, int > &barcode_map, const CscSimDataCollection *simDataCol) const
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Gaudi::Property< std::vector< int > > m_pdgsToBeConsidered
const TruthTree createTruthTree(const TrackRecordCollection *truthTrackCol, const McEventCollection *mcEventCollection, const std::vector< const MuonSimDataCollection * > &muonSimData, const CscSimDataCollection *cscSimDataMap) const
create truth tree from sim data
void addMissedHits(MuonTechnologyTruth &truth, const std::set< Identifier > &ids, const std::set< Identifier > &chids, const MuonSimDataCollection &simCol, bool restrictedTruth) const
int manipulateBarCode(int barcode) const
ResultVec match(const TruthTree &truth_tree, const TrackCollection &tracks) const
perform truth matching for a given set of tracks
Gaudi::Property< bool > m_manipulateBarCode
HepMC::ConstGenParticlePtr getInitial(const TruthTrajectory &traj, const int barcodeIn) const
Returns the initial particle of the particle with barcodeIn if it is found in the truth trajectory.
unsigned int getNumberOfScatters(const TruthTrajectory &traj, const int barcodeIn) const
Returns the number of steps a particle took while maintaining its PDG ID.
Gaudi::Property< bool > m_matchAllParticles
HepMC::ConstGenParticlePtr getMother(const TruthTrajectory &traj, const int barcodeIn) const
Returns the mother particle of the particle with barcodeIn if it is found in the truth trajectory.
void addMdtTruth(MuonTechnologyTruth &trackTruth, const Identifier &id, const Trk::MeasurementBase &meas, const MuonSimDataCollection &simCol) const
StatusCode initialize()
AlgTool initilize.
Gaudi::Property< bool > m_doSummary
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
const std::pair< HepMC::ConstGenParticlePtr, unsigned int > getInitialPair(const TruthTrajectory &traj, const int barcodeIn) const
Returns the initial particle of the particle with barcodeIn if it is found in the truth trajectory.
void addSimDataToTree(TruthTree &truth_tree, std::map< int, int > &barcode_map, const MuonSimDataCollection *simDataCol) const
HepMC::ConstGenParticlePtr getAncestor(const TruthTrajectory &traj, const int barcodeIn) const
Returns the ancestor particle of the particle with barcodeIn if it is found in the truth trajectory.
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
This class is the pure abstract base class for all fittable tracking measurements.
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
Class to handle pseudo-measurements in fitters and on track objects.
Class to handle RIO On Tracks ROT) for InDet and Muons, it inherits from the common MeasurementBase.
Definition RIO_OnTrack.h:70
virtual const Trk::PrepRawData * prepRawData() const =0
returns the PrepRawData (also known as RIO) object to which this RIO_OnTrack is associated.
Identifier identify() const
return the identifier -extends MeasurementBase
static void extract(std::vector< const RIO_OnTrack * > &rots, const std::vector< const MeasurementBase * > &measurements)
const std::vector< const Trk::MeasurementBase * > & containedMeasurements() const
returns the vector of Trk::MeasurementBase objects
A TruthTrajectory is a chain of charged MC particles connected through the mother-daughter relationsh...
int uniqueID(const T &p)
constexpr int UNDEFINED_ID
const GenParticle * ConstGenParticlePtr
Definition GenParticle.h:38
bool isStable(const T &p)
Identify if the particle is stable, i.e. has not decayed.
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
void stable_sort(DataModel_detail::iterator< DVL > beg, DataModel_detail::iterator< DVL > end)
Specialization of stable_sort for DataVector/List.
bool operator()(const MatchResult &r1, const MatchResult &r2) const