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
84 std::stable_sort(result.begin(), result.end(), SortResultByMatchedHits());
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
103 std::stable_sort(result.begin(), result.end(), SortResultByMatchedHits());
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 (barcode>HepMC::UNDEFINED_ID) ? genEvent->particles().at(barcode-1) : nullptr; // FIXME implement HepMC::id_to_particle/vertex explicitly
149 if (genParticle) {
150 truthTrajectory = std::make_unique<TruthTrajectory>();
151 m_truthTrajectoryBuilder->buildTruthTrajectory(truthTrajectory.get(), genParticle);
152 if (!truthTrajectory->empty()) {
153 // always use barcode of the 'final' particle in chain in map
154 barcode = HepMC::uniqueID(truthTrajectory->front());
155
156 if (msgLvl(MSG::VERBOSE)) {
157 auto particle = truthTrajectory->front().cptr();
158 ATH_MSG_VERBOSE(" found GenParticle: size " << truthTrajectory->size() << " fs barcode " << barcode << "particle "<< particle);
159 if (particle->production_vertex()) {
160 ATH_MSG_VERBOSE(" vertex: r " << particle->production_vertex()->position().perp() << " z "
161 << particle->production_vertex()->position().z());
162 }
163 }
164
165 // now collect all barcodes beloning to this TruthTrajectory
166 std::vector<HepMcParticleLink>::const_iterator pit = truthTrajectory->begin();
167 std::vector<HepMcParticleLink>::const_iterator pit_end = truthTrajectory->end();
168 for (; pit != pit_end; ++pit) {
169 int code = HepMC::uniqueID(*pit);
170
171 if (msgLvl(MSG::VERBOSE) && code != barcode) {
172 auto particle = (*pit).cptr();
173 ATH_MSG_VERBOSE(" secondary barcode: " << code << "particle "<< particle);
174 if (particle->production_vertex())
175 ATH_MSG_VERBOSE(" vertex: r " <<particle->production_vertex()->position().perp() << " z "
176 << particle->production_vertex()->position().z());
177 // sanity check
178 if (barcode_map.count(code)) ATH_MSG_VERBOSE(" pre-existing barcode " << code);
179 }
180
181 // enter barcode
182 barcode_map[code] = barcode;
183 }
184 } else {
185 ATH_MSG_WARNING(" empty truth trajectory " << barcode);
186 }
187 }
188 } else {
189 // add one to one relation
190 barcode_map[barcode] = barcode;
191 }
192
193 if (truth_tree.count(barcode)) {
194 ATH_MSG_WARNING(" found muon barcode twice in truth record: " << barcode);
195 continue;
196 }
197
198 TruthTreeEntry& entry = truth_tree[barcode];
199 entry.truthTrack = &(*tr_it);
200 // entry.truthTrajectory = truthTrajectory.get();
201 entry.truthTrajectory = std::move(truthTrajectory);
202 // m_truthTrajectoriesToBeDeleted.push_back(std::move(truthTrajectory));
203 }
204
205 // add sim data collections
206 for (const MuonSimDataCollection* simDataMap : muonSimData) { addSimDataToTree(truth_tree, barcode_map, simDataMap); }
207 if (cscSimDataMap) { addCscSimDataToTree(truth_tree, barcode_map, cscSimDataMap); }
208
209 unsigned int ngood(0);
210 std::vector<int> badBarcodes;
211 // erase entries with too few hits or no track record
212 TruthTreeIt it = truth_tree.begin();
213 for (; it != truth_tree.end(); ++it) {
214 bool erase = false;
215 unsigned int nhits = it->second.mdtHits.size() + it->second.rpcHits.size() + it->second.tgcHits.size() +
216 it->second.cscHits.size() + it->second.stgcHits.size() + it->second.mmHits.size();
217 if (!it->second.truthTrack) erase = true;
218 if (nhits < m_minHits) erase = true;
219
220 if (erase) {
221 ATH_MSG_VERBOSE(" Erasing entry: barcode " << HepMC::uniqueID(it->second.truthTrack) << " hits " << nhits);
222 badBarcodes.push_back(it->first);
223 } else {
224 ++ngood;
225 ATH_MSG_VERBOSE(" Keeping entry: barcode " << HepMC::uniqueID(it->second.truthTrack) << " hits " << nhits);
226 }
227 }
228
229 std::vector<int>::iterator badIt = badBarcodes.begin();
230 std::vector<int>::iterator badIt_end = badBarcodes.end();
231 for (; badIt != badIt_end; ++badIt) truth_tree.erase(*badIt);
232
233 if (ngood != truth_tree.size()) {
234 ATH_MSG_WARNING(" Problem cleaning map: size " << truth_tree.size() << " accepted entries " << ngood);
235 }
236
237 if (m_doSummary || msgLvl(MSG::DEBUG)) {
238 ATH_MSG_INFO(" summarizing truth tree: number of particles " << truth_tree.size());
239 TruthTreeIt it = truth_tree.begin();
240 TruthTreeIt it_end = truth_tree.end();
241 for (; it != it_end; ++it) {
242 if (!it->second.truthTrack)
243 ATH_MSG_INFO(" no TrackRecord ");
244 else {
245 ATH_MSG_INFO(" PDG " << it->second.truthTrack->GetPDGCode() << " barcode " << HepMC::uniqueID(it->second.truthTrack));
246 }
247 if (!it->second.mdtHits.empty()) ATH_MSG_INFO(" mdt " << it->second.mdtHits.size());
248 if (!it->second.rpcHits.empty()) ATH_MSG_INFO(" rpc " << it->second.rpcHits.size());
249 if (!it->second.tgcHits.empty()) ATH_MSG_INFO(" tgc " << it->second.tgcHits.size());
250 if (!it->second.cscHits.empty()) ATH_MSG_INFO(" csc " << it->second.cscHits.size());
251 if (!it->second.stgcHits.empty()) ATH_MSG_INFO(" stgc " << it->second.stgcHits.size());
252 if (!it->second.mmHits.empty()) ATH_MSG_INFO(" mm " << it->second.mmHits.size());
253 if (it->second.mdtHits.empty() && it->second.rpcHits.empty() && it->second.tgcHits.empty() && it->second.cscHits.empty() &&
254 it->second.stgcHits.empty() && it->second.mmHits.empty())
255 ATH_MSG_INFO(" no hits ");
256 }
257 }
258
259 return truth_tree;
260 }
261
262 void MuonTrackTruthTool::addSimDataToTree(TruthTree& truth_tree, std::map<int, int>& barcode_map,
263 const MuonSimDataCollection* simDataCol) const {
264 // loop over sim collection and check whether identifiers are on track
265 MuonSimDataCollection::const_iterator it = simDataCol->begin();
266 MuonSimDataCollection::const_iterator it_end = simDataCol->end();
267 for (; it != it_end; ++it) {
268 Identifier id = it->first;
269
270 // loop over deposits
271 std::vector<MuonSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
272 std::vector<MuonSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
273 for (; dit != dit_end; ++dit) {
274 int barcodeIn = HepMC::uniqueID(dit->first);
275 std::map<int, int>::const_iterator bit = barcode_map.find(barcodeIn);
276 if (bit == barcode_map.end()) {
277 ATH_MSG_VERBOSE(" discarding "
278 << " " << m_idHelperSvc->toString(id) << " barcode " << barcodeIn);
279 continue;
280 }
281 // replace barcode with barcode from map
282 int barcode = bit->second;
283
284 TruthTreeIt eit = truth_tree.find(barcode);
285 if (eit == truth_tree.end()) {
286 ATH_MSG_VERBOSE(" discarding "
287 << " " << m_idHelperSvc->toString(id) << " barcode " << barcode);
288 continue;
289 }
290
291 if (m_idHelperSvc->isMdt(id)) {
292 eit->second.mdtHits.insert(*it);
293 } else if (m_idHelperSvc->isRpc(id)) {
294 if (m_idHelperSvc->stationIndex(id) == StIndex::BO && m_idHelperSvc->rpcIdHelper().doubletR(id) == 2) {
295 ATH_MSG_VERBOSE(" Discarding non existing RPC hit " << m_idHelperSvc->toString(id));
296 continue;
297 }
298
299 eit->second.rpcHits.insert(*it);
300 } else if (m_idHelperSvc->isTgc(id)) {
301 eit->second.tgcHits.insert(*it);
302 } else if (m_idHelperSvc->issTgc(id)) {
303 eit->second.stgcHits.insert(*it);
304 } else if (m_idHelperSvc->isMM(id)) {
305 eit->second.mmHits.insert(*it);
306 }
307 if (msgLvl(MSG::VERBOSE)) {
308 ATH_MSG_VERBOSE(" adding hit " << m_idHelperSvc->toString(id) << " barcode " << barcode);
309 if (barcode != barcodeIn) ATH_MSG_VERBOSE(" hit barcode " << barcodeIn);
310 }
311 }
312 }
313 }
314
315 void MuonTrackTruthTool::addCscSimDataToTree(TruthTree& truth_tree, std::map<int, int>& barcode_map,
316 const CscSimDataCollection* simDataCol) const {
317 // loop over sim collection and check whether identifiers are on track
318 CscSimDataCollection::const_iterator it = simDataCol->begin();
319 CscSimDataCollection::const_iterator it_end = simDataCol->end();
320 for (; it != it_end; ++it) {
321 Identifier id = it->first;
322
323 // loop over deposits
324 std::vector<CscSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
325 std::vector<CscSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
326 for (; dit != dit_end; ++dit) {
327 int barcodeIn = HepMC::uniqueID(dit->first);
328 std::map<int, int>::const_iterator bit = barcode_map.find(barcodeIn);
329 if (bit == barcode_map.end()) {
330 ATH_MSG_VERBOSE(" discarding "
331 << " " << m_idHelperSvc->toString(id) << " barcode " << barcodeIn);
332 continue;
333 }
334 // replace barcode with barcode from map
335 int barcode = bit->second;
336
337 TruthTreeIt eit = truth_tree.find(barcode);
338 if (eit == truth_tree.end()) {
339 ATH_MSG_VERBOSE(" discarding "
340 << " " << m_idHelperSvc->toString(id) << " barcode " << barcode);
341 continue;
342 }
343
344 if (msgLvl(MSG::VERBOSE)) {
345 ATH_MSG_VERBOSE(" adding hit " << m_idHelperSvc->toString(id) << " barcode " << barcode);
346 if (barcode != barcodeIn) ATH_MSG_VERBOSE(" hit barcode " << barcodeIn);
347 }
348 eit->second.cscHits.insert(*it);
349 }
350 }
351 }
352
353 MuonTrackTruth MuonTrackTruthTool::getTruth(const TruthTree& truth_tree, const Muon::MuonSegment& segment) const {
354 return getTruth(truth_tree, segment.containedMeasurements(), true);
355 }
356
357 MuonTrackTruth MuonTrackTruthTool::getTruth(const TruthTree& truth_tree, const Trk::Track& track, bool restrictedTruth) const {
358 if (track.measurementsOnTrack()) return getTruth(truth_tree, track.measurementsOnTrack()->stdcont(), restrictedTruth);
359 return {};
360 }
361
362 MuonTrackTruth MuonTrackTruthTool::getTruth(const TruthTree& truth_tree, const std::vector<const MuonSegment*>& segments,
363 bool restrictedTruth) const {
364 std::set<Identifier> ids;
365 std::vector<const Trk::MeasurementBase*> measurements;
366 std::vector<const MuonSegment*>::const_iterator sit = segments.begin();
367 std::vector<const MuonSegment*>::const_iterator sit_end = segments.end();
368 for (; sit != sit_end; ++sit) {
369 std::vector<const Trk::MeasurementBase*>::const_iterator mit = (*sit)->containedMeasurements().begin();
370 std::vector<const Trk::MeasurementBase*>::const_iterator mit_end = (*sit)->containedMeasurements().end();
371 for (; mit != mit_end; ++mit) {
372 const Trk::MeasurementBase* meas = *mit;
373 const Trk::RIO_OnTrack* rot = nullptr;
375 if (!rot) {
376 if (!dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas)) ATH_MSG_WARNING(" Could not get rot from measurement ");
377 continue;
378 }
379 Identifier id = rot->identify();
380 if (!id.is_valid() || !m_idHelperSvc->mdtIdHelper().is_muon(id)) continue;
381 if (ids.count(id)) continue;
382 measurements.push_back(meas);
383 ids.insert(id);
384 }
385 }
386 return getTruth(truth_tree, measurements, restrictedTruth);
387 }
388
389 MuonTrackTruth MuonTrackTruthTool::getTruth(const TruthTree& truth_tree, const std::vector<const Trk::MeasurementBase*>& measurements,
390 bool restrictedTruth) const {
391 MuonTrackTruth bestMatch;
392 bestMatch.truthTrack = nullptr;
393 bestMatch.truthTrajectory = nullptr;
394
395 unsigned int nmatchedHitsBest = 0;
396 // loop over muons and match hits
397 TruthTreeConstIt tit = truth_tree.begin();
398 TruthTreeConstIt tit_end = truth_tree.end();
399 for (; tit != tit_end; ++tit) {
400 unsigned int nhits = tit->second.mdtHits.size() + tit->second.cscHits.size() + tit->second.rpcHits.size() +
401 tit->second.tgcHits.size() + tit->second.stgcHits.size() + tit->second.mmHits.size();
402 if (nhits == 0) continue;
403
404 MuonTrackTruth trackTruth = getTruth(measurements, tit->second, restrictedTruth);
405 unsigned int nmatchedHits = trackTruth.numberOfMatchedHits();
406 ATH_MSG_DEBUG(" performed truth match for particle with barcode: " << tit->first << " overlap " << nmatchedHits << " fraction "
407 << (double)nmatchedHits / (double)nhits);
408 if (nmatchedHits > 0 && nmatchedHits > nmatchedHitsBest) {
409 bestMatch = trackTruth;
410 nmatchedHitsBest = nmatchedHits;
411 }
412 }
413
414 return bestMatch;
415 }
416
417 MuonTrackTruth MuonTrackTruthTool::getTruth(const std::vector<const Trk::MeasurementBase*>& measurements,
418 const TruthTreeEntry& truthEntry, bool restrictedTruth) const {
419 MuonTrackTruth trackTruth;
420 trackTruth.truthTrack = truthEntry.truthTrack;
421 trackTruth.truthTrajectory = truthEntry.truthTrajectory;
422
423 std::vector<const Trk::MeasurementBase*>::const_iterator mit = measurements.begin();
424 std::vector<const Trk::MeasurementBase*>::const_iterator mit_end = measurements.end();
425 for (; mit != mit_end; ++mit) {
426 // check whether state is a measurement
427 const Trk::MeasurementBase* meas = *mit;
428 if (!meas) { continue; }
429
430 const Trk::RIO_OnTrack* rot = nullptr;
432 if (!rot) {
433 if (!dynamic_cast<const Trk::PseudoMeasurementOnTrack*>(meas)) ATH_MSG_WARNING(" Could not get rot from measurement ");
434 continue;
435 }
436 Identifier id = rot->identify();
437 if (!id.is_valid() || !m_idHelperSvc->mdtIdHelper().is_muon(id)) continue;
438
439 if (m_idHelperSvc->isMdt(id)) {
440 addMdtTruth(trackTruth.mdts, id, *meas, truthEntry.mdtHits);
441 } else if (m_idHelperSvc->isCsc(id)) {
442 addClusterTruth(trackTruth.cscs, id, *meas, truthEntry.cscHits);
443 } else if (m_idHelperSvc->isRpc(id)) {
444 addClusterTruth(trackTruth.rpcs, id, *meas, truthEntry.rpcHits);
445 } else if (m_idHelperSvc->isTgc(id)) {
446 addClusterTruth(trackTruth.tgcs, id, *meas, truthEntry.tgcHits);
447 } else if (m_idHelperSvc->issTgc(id)) {
448 addClusterTruth(trackTruth.stgcs, id, *meas, truthEntry.stgcHits);
449 } else if (m_idHelperSvc->isMM(id)) {
450 addClusterTruth(trackTruth.mms, id, *meas, truthEntry.mmHits);
451 }
452 }
453
454 addMissedHits(trackTruth.mdts, trackTruth.mdts.matchedHits, trackTruth.mdts.matchedChambers, truthEntry.mdtHits, restrictedTruth);
455 addMissedHits(trackTruth.cscs, trackTruth.cscs.matchedHits, trackTruth.cscs.matchedChambers, truthEntry.cscHits, restrictedTruth);
456 addMissedHits(trackTruth.rpcs, trackTruth.rpcs.matchedHits, trackTruth.rpcs.matchedChambers, truthEntry.rpcHits, restrictedTruth);
457 addMissedHits(trackTruth.tgcs, trackTruth.tgcs.matchedHits, trackTruth.tgcs.matchedChambers, truthEntry.tgcHits, restrictedTruth);
458 addMissedHits(trackTruth.stgcs, trackTruth.stgcs.matchedHits, trackTruth.stgcs.matchedChambers, truthEntry.stgcHits,
459 restrictedTruth);
460 addMissedHits(trackTruth.mms, trackTruth.mms.matchedHits, trackTruth.mms.matchedChambers, truthEntry.mmHits, restrictedTruth);
461
462 return trackTruth;
463 }
464
465 void MuonTrackTruthTool::addMissedHits(MuonTechnologyTruth& truth, const std::set<Identifier>& ids, const std::set<Identifier>& chids,
466 const MuonSimDataCollection& simCol, bool restrictedTruth) const {
467 // loop over sim collection and check whether identifiers are on track
468 MuonSimDataCollection::const_iterator it = simCol.begin();
469 MuonSimDataCollection::const_iterator it_end = simCol.end();
470 for (; it != it_end; ++it) {
471 Identifier id = it->first;
472 // for trigger chambers use layer id
473 if (m_idHelperSvc->isTrigger(id) || m_idHelperSvc->isCsc(id)) id = m_idHelperSvc->layerId(id);
474
475 int isOnTrack = ids.count(id);
476 if (isOnTrack) continue;
477
478 // if restricted truth mode, skip if chamber has not hits
479 Identifier chid = m_idHelperSvc->chamberId(id);
480 bool chamberHasHits = chids.count(chid);
481 if (restrictedTruth && !chamberHasHits) continue;
482
483 // loop over deposits
484 std::vector<MuonSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
485 std::vector<MuonSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
486 for (; dit != dit_end; ++dit) {
487 truth.missedHits.insert(id);
488 // only fill a missed chamber if the chamber had no hits
489 if (!chamberHasHits) truth.missedChambers.insert(chid);
490 }
491 }
492 }
493
494 void MuonTrackTruthTool::addMissedHits(MuonTechnologyTruth& truth, const std::set<Identifier>& ids, const std::set<Identifier>& chids,
495 const CscSimDataCollection& simCol, bool restrictedTruth) const {
496 // loop over sim collection and check whether identifiers are on track
497 CscSimDataCollection::const_iterator it = simCol.begin();
498 CscSimDataCollection::const_iterator it_end = simCol.end();
499 for (; it != it_end; ++it) {
500 Identifier id = m_idHelperSvc->layerId(it->first);
501
502 int isOnTrack = ids.count(id);
503 if (isOnTrack) continue;
504
505 // if restricted truth mode, skip if chamber has not hits
506 Identifier chid = m_idHelperSvc->chamberId(id);
507 bool chamberHasHits = chids.count(chid);
508 if (restrictedTruth && !chamberHasHits) continue;
509
510 // loop over deposits
511 std::vector<CscSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
512 std::vector<CscSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
513 for (; dit != dit_end; ++dit) {
514 truth.missedHits.insert(id);
515 // only fill a missed chamber if the chamber had no hits
516 if (!chamberHasHits) truth.missedChambers.insert(chid);
517 }
518 }
519 }
520
522 const MuonSimDataCollection& simCol) const {
523 const MdtDriftCircleOnTrack* mdt = dynamic_cast<const MdtDriftCircleOnTrack*>(&meas);
524 if (!mdt) {
525 ATH_MSG_WARNING(" dynamic_cast to MdtDriftCircleOnTrack failed for measurement with id " << m_idHelperSvc->toString(id));
526 return;
527 }
528
529 Identifier chid = m_idHelperSvc->chamberId(id);
530
531 // find SimData corresponding to identifier
532 MuonSimDataCollection::const_iterator it = simCol.find(id);
533 if (it == simCol.end()) {
534 truth.wrongHits.insert(id);
535 truth.wrongChambers.insert(chid);
536 return;
537 }
538
539 std::vector<MuonSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
540 std::vector<MuonSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
541 for (; dit != dit_end; ++dit) {
542 double radius = dit->second.firstEntry();
543
544 // check whether SDO and hit have same sign, don't check sign if drift radius < 0.3 mm as it will be badly determined
545 double checkSign = fabs(mdt->driftRadius()) > 0.3 ? radius * mdt->driftRadius() : 1;
546 if (checkSign >= 0) {
547 truth.matchedHits.insert(id);
548 truth.matchedChambers.insert(chid);
549 } else {
550 truth.wrongHits.insert(id);
551 truth.wrongChambers.insert(chid);
552 }
553 }
554 }
555
557 const MuonSimDataCollection& simCol) const {
558 Identifier layid = m_idHelperSvc->layerId(id);
559 Identifier chid = m_idHelperSvc->chamberId(id);
560
561 MuonSimDataCollection::const_iterator it = simCol.end();
562
563 bool goodCluster = false;
564 const CompetingMuonClustersOnTrack* crot = dynamic_cast<const CompetingMuonClustersOnTrack*>(&meas);
565 if (crot) {
566 for (unsigned int i = 0; i < crot->numberOfContainedROTs(); ++i) {
567 const MuonClusterOnTrack* cluster = &crot->rioOnTrack(i);
568 if (!cluster) continue;
569 // find SimData corresponding to identifier
570 it = simCol.find(cluster->identify());
571 if (it != simCol.end()) {
572 goodCluster = true;
573 break;
574 }
575 }
576 } else {
577 // Find SimData corresponding to identifier
578 const Trk::RIO_OnTrack* rot = nullptr;
579 Trk::RoT_Extractor::extract(rot, &meas);
580 const Trk::PrepRawData* prd = rot->prepRawData();
581 if (prd) {
582 // check if an identifier from the list of RDOs is matched to that in the SDO collection
583 const std::vector<Identifier> &rdoList = prd->rdoList();
584 std::vector<Identifier>::const_iterator rit = rdoList.begin();
585 std::vector<Identifier>::const_iterator rit_end = rdoList.end();
586 for (; rit != rit_end; ++rit) {
587 it = simCol.find(*rit);
588 if (it != simCol.end()) {
589 goodCluster = true;
590 break;
591 }
592 }
593 } else {
594 it = simCol.find(id);
595 if (it != simCol.end()) goodCluster = true;
596 }
597 }
598
599 if (!goodCluster || it == simCol.end()) {
600 truth.wrongHits.insert(id);
601 return;
602 }
603
604 std::vector<MuonSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
605 std::vector<MuonSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
606 for (; dit != dit_end; ++dit) {
607 truth.matchedHits.insert(layid);
608 truth.matchedChambers.insert(chid);
609 }
610 }
611
613 const CscSimDataCollection& simCol) const {
614 Identifier layid = m_idHelperSvc->layerId(id);
615 Identifier chid = m_idHelperSvc->chamberId(id);
616 // find SimData corresponding to identifier
617 CscSimDataCollection::const_iterator it = simCol.find(id);
618 if (it == simCol.end()) {
619 truth.wrongHits.insert(layid);
620 truth.wrongChambers.insert(chid);
621 return;
622 }
623
624 std::vector<CscSimData::Deposit>::const_iterator dit = it->second.getdeposits().begin();
625 std::vector<CscSimData::Deposit>::const_iterator dit_end = it->second.getdeposits().end();
626 for (; dit != dit_end; ++dit) {
627 truth.matchedHits.insert(layid);
628 truth.matchedChambers.insert(chid);
629 }
630 }
631
633 ATH_MSG_DEBUG("getMother() : size = " << traj.size());
634 int pdgFinal = ((traj.empty()) ? -999 : traj.front().cptr()->pdg_id());
635 bool foundBC = false;
636 for (const auto& pit : traj) {
637 if (!pit) continue;
638 if (HepMC::uniqueID(pit) == barcodeIn || foundBC) {
639 foundBC = true;
640 ATH_MSG_DEBUG("getMother() : " << pit );
641 auto particle = pit.scptr();
642 if (particle->pdg_id() != pdgFinal) { // the first case a track had a different flavour
643 break;
644 }
645 }
646 }
647 return nullptr;
648 }
649
651 bool foundBC = false;
652 for (const auto& pit : traj) {
653 if (!pit) continue;
654 if (HepMC::uniqueID(pit) == barcodeIn || foundBC) {
655 foundBC = true;
656 auto particle = pit.scptr();
657 if (!MC::isStable(particle)) { // first non final state particle
658 return particle;
659 }
660 }
661 }
662 return nullptr;
663 }
664
665 const std::pair<HepMC::ConstGenParticlePtr, unsigned int> MuonTrackTruthTool::getInitialPair(const TruthTrajectory& traj,
666 const int barcodeIn) const {
667 std::pair<HepMC::ConstGenParticlePtr, unsigned int> thePair(nullptr, 0);
668 unsigned int scat = 0;
669 ATH_MSG_DEBUG("getFirst() : size = " << traj.size());
670 bool foundBC = false;
671 int pdgFinal = 0;
672 double ePrev = 0.;
673 HepMC::ConstGenParticlePtr theFirst{nullptr};
674 for (auto pit = traj.begin(); pit != traj.end(); ++pit) {
675 if (HepMC::uniqueID(*pit) == barcodeIn || foundBC) {
676 auto particle = (*pit).scptr();
677 if (!foundBC) {
678 foundBC = true;
679 theFirst = particle;
680 pdgFinal = particle->pdg_id();
681 } else {
682 if (particle->pdg_id() == pdgFinal) {
683 const auto& pit_p = *pit;
684 if ((theFirst != pit_p.scptr()) && (particle->momentum().t() != ePrev))
685 ++scat; // if the particle has not changed pdgid after the first step count as scatter. also avoid counting
686 // pure interface changes as scatter
687 } else { // the first time this particle appears
688 --pit; // AV This is confusing
689 theFirst = (*pit).scptr();
690 break;
691 }
692 }
693 ATH_MSG_DEBUG("getFirst() : pt = " << particle->momentum().perp() << " scat = " << scat);
694 ePrev = particle->momentum().t(); // prepare for comparing this entry with the next one
695 }
696 }
697 // sanity check
698 if (theFirst && theFirst->pdg_id() != pdgFinal) ATH_MSG_ERROR("Wrong pdgId association in getFirst()");
699 ATH_MSG_DEBUG("Number of scatters = " << scat << " pdgId = " << pdgFinal);
700
701 thePair.first = theFirst;
702 thePair.second = scat;
703 return thePair;
704 }
705
707 return getInitialPair(traj, barcodeIn).first;
708 }
709
710 unsigned int MuonTrackTruthTool::getNumberOfScatters(const TruthTrajectory& traj, const int barcodeIn) const {
711 return (getInitialPair(traj, barcodeIn)).second;
712 }
713} // 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.
void operator()(T1)
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
HepMC3::ConstGenParticlePtr ConstGenParticlePtr
Definition GenParticle.h:20
HepMC3::GenEvent GenEvent
Definition GenEvent.h:39
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