ATLAS Offline Software
Loading...
Searching...
No Matches
MuonSegmentTruthAssociationAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6
16
17namespace Muon {
18
19 // Constructor with parameters:
20 MuonSegmentTruthAssociationAlg::MuonSegmentTruthAssociationAlg(const std::string& name, ISvcLocator* pSvcLocator) :
21 AthReentrantAlgorithm(name, pSvcLocator) {}
22
23 // Initialize method:
25 ATH_CHECK(m_idHelperSvc.retrieve());
26 ATH_CHECK(m_printer.retrieve());
29 m_muonSegmentCollectionName = m_muonSegmentCollectionName.key() + ".truthSegmentLink";
32 ATH_CHECK(m_mcEventColl.initialize());
33 if (!(m_idHelperSvc->hasSTGC() && m_idHelperSvc->hasMM())) m_muonSimData = {"MDT_SDO", "RPC_SDO", "TGC_SDO"};
34 ATH_CHECK(m_muonSimData.initialize());
35 ATH_CHECK(m_cscSimData.initialize(m_idHelperSvc->hasCSC()));
36 ATH_CHECK(m_trackRecord.initialize());
37 return StatusCode::SUCCESS;
38 }
39
40 // Execute method:
41 StatusCode MuonSegmentTruthAssociationAlg::execute(const EventContext& ctx) const {
42 // skip if no input data found
46 ctx);
47 if (!muonTruthSegments.isPresent()) {
48 ATH_MSG_DEBUG("No muon truth segments");
49 return StatusCode::SUCCESS;
50 }
51 if (!segments.isPresent()) {
52 ATH_MSG_DEBUG("No muon segments");
53 return StatusCode::SUCCESS;
54 }
55 if (!muonTruthSegments.isValid()) {
56 ATH_MSG_ERROR("Muon truth segments not valid");
57 return StatusCode::FAILURE;
58 }
59 if (!segments.isValid()) {
60 ATH_MSG_ERROR("Muon segments not valid");
61 return StatusCode::FAILURE;
62 }
64 if (!truthTrackCol.isValid()) {
65 ATH_MSG_ERROR("Track collection " << m_trackRecord.key() << " is not present");
66 return StatusCode::FAILURE;
67 }
68 if (truthTrackCol->empty()) {
69 ATH_MSG_DEBUG("Track collection " << m_trackRecord.key() << " is empty. Skip the rest of the alg");
70 return StatusCode::SUCCESS;
71 }
72
73 std::string truthSegmentContainerName (m_muonTruthSegmentContainerName.key());
74 auto ppos = truthSegmentContainerName.find('.');
75 truthSegmentContainerName.resize(std::min(ppos,truthSegmentContainerName.size()));
76 std::string segmentCollectionName( m_muonSegmentCollectionName.key());
77 ppos = segmentCollectionName.find('.');
78 segmentCollectionName.resize(std::min(ppos,segmentCollectionName.size()));
79
80 std::vector<const Muon::MuonSegment*> muonSegments;
81 typedef std::map<const Muon::MuonSegment*, ElementLink<xAOD::MuonSegmentContainer> > MuonSegmentLinkMap;
82 MuonSegmentLinkMap muonSegmentLinkMap;
83 unsigned int segIndex = 0;
84 muonSegments.reserve(segments->size());
85 for (const auto *const seg : *segments) {
87 if (seg->muonSegment().isValid()) {
88 const Muon::MuonSegment* mseg = dynamic_cast<const Muon::MuonSegment*>(*seg->muonSegment());
89 if (mseg) {
90 ATH_MSG_DEBUG(" Reco segment " << m_printer->print(*mseg));
91 muonSegments.push_back(mseg);
92 muonSegmentLinkMap[mseg] = ElementLink<xAOD::MuonSegmentContainer>(segmentCollectionName, segIndex);
93 }
94 }
95 ++segIndex;
96 }
97
99 std::vector<const MuonSimDataCollection*> muonSimData;
100 for (SG::ReadHandle<MuonSimDataCollection>& simDataMap : m_muonSimData.makeHandles(ctx)) {
101 if (!simDataMap.isValid()) {
102 ATH_MSG_WARNING(simDataMap.key() << " not valid");
103 continue;
104 }
105 if (!simDataMap.isPresent()) continue;
106 muonSimData.push_back(simDataMap.cptr());
107 }
109 if (m_idHelperSvc->hasCSC()) {
111 if (!cscSimDataMap.isValid()) {
112 ATH_MSG_WARNING(cscSimDataMap.key() << " not valid");
113 truth_tree = m_muonTrackTruthTool->createTruthTree(truthTrackCol.cptr(), mcEventCollection.cptr(), muonSimData, nullptr);
114 } else {
115 truth_tree = m_muonTrackTruthTool->createTruthTree(truthTrackCol.cptr(), mcEventCollection.cptr(), muonSimData,
116 cscSimDataMap.cptr());
117 }
118 } else {
119 truth_tree = m_muonTrackTruthTool->createTruthTree(truthTrackCol.cptr(), mcEventCollection.cptr(), muonSimData, nullptr);
120 }
121 ATH_MSG_DEBUG("Matching reconstructed segments " << muonSegments.size());
122 IMuonTrackTruthTool::SegmentResultVec segmentMatchResult = m_muonTrackTruthTool->match(truth_tree, muonSegments);
123
124 // create a map of chamber index onto the truth segments
125 std::map<Muon::MuonStationIndex::ChIndex, std::vector<ElementLink<xAOD::MuonSegmentContainer> > > chamberTruthSegmentLinks;
126 segIndex = 0;
127 for (const auto *const truthSegment : *muonTruthSegments) {
128 muonTruthSegments(*truthSegment) = ElementLink<xAOD::MuonSegmentContainer>();
129 std::vector<ElementLink<xAOD::MuonSegmentContainer> >& linkVec = chamberTruthSegmentLinks[truthSegment->chamberIndex()];
130 linkVec.emplace_back(truthSegmentContainerName, segIndex);
131 ATH_MSG_DEBUG("New truth segment: index " << segIndex << " " << Muon::MuonStationIndex::chName(truthSegment->chamberIndex())
132 << " nlinks " << linkVec.size() << " link " << *linkVec.back());
133 ++segIndex;
134 }
135
136 // extract segment belonging to this muon
138 std::set<Muon::MuonStationIndex::ChIndex> chambers;
139 std::vector<std::pair<Muon::MuonStationIndex::ChIndex, const TrackRecord*> > chamberTruthVec;
140 for (const auto& result : segmentMatchResult) {
141 // only use segment that are matched
142 ATH_MSG_DEBUG("Match reco segment " << m_printer->print(*(result.first)) << " truth " << result.second.truthTrack);
143 if (!result.second.truthTrack) continue;
144 const int barcode = HepMC::uniqueID(result.second.truthTrack);
145
146 // get chamber Identifier
147 Identifier id;
148 if (!result.second.mdts.matchedHits.empty()) id = *result.second.mdts.matchedHits.begin();
149 if (!result.second.cscs.matchedHits.empty()) id = *result.second.cscs.matchedHits.begin();
150 if (!result.second.stgcs.matchedHits.empty()) id = *result.second.stgcs.matchedHits.begin();
151 if (!result.second.mms.matchedHits.empty()) id = *result.second.mms.matchedHits.begin();
152 if (!id.is_valid()) continue;
153
155 auto pos = chambers.insert(chIndex);
156
157 if (!pos.second) {
158 bool skip = false;
159 // select the first segment per chamber
160 for (const auto& index : chamberTruthVec) {
161 // check that it is associated to same truthTrack and skip in that case
162 if (index.first == chIndex && index.second == result.second.truthTrack) {
163 ATH_MSG_DEBUG("Skip this reco segment ");
164 skip = true;
165 break;
166 }
167 }
168 if (skip) continue;
169 }
170
171 std::pair<Muon::MuonStationIndex::ChIndex, const TrackRecord*> chPair;
172 chPair.first = chIndex;
173 chPair.second = result.second.truthTrack;
174 chamberTruthVec.push_back(chPair);
175
176 // look-up segment element link
177 auto segPos = muonSegmentLinkMap.find(result.first);
178 if (segPos == muonSegmentLinkMap.end()) {
179 ATH_MSG_WARNING("Could not find segment in container");
180 continue;
181 }
182 ElementLink<xAOD::MuonSegmentContainer> recoLink = segPos->second;
183 const xAOD::MuonSegment* recoSegment = *recoLink;
184 if (!recoLink) {
185 ATH_MSG_WARNING("Reco segment link invalid");
186 continue;
187 }
188 ATH_MSG_DEBUG("recoLink " << recoLink << " chamber index: " << Muon::MuonStationIndex::chName(chIndex));
189 // look-up truth segments in the chamber layer
190 auto truthPos = chamberTruthSegmentLinks.find(chIndex);
191 if (truthPos == chamberTruthSegmentLinks.end()) continue;
192 ATH_MSG_DEBUG("Found matching chamber index: " << Muon::MuonStationIndex::chName(chIndex) << " links "
193 << truthPos->second.size());
194
195 for (auto& truthSegLink : truthPos->second) {
196 // get truth particle for the segment
197 truthSegLink.toPersistent();
198 const xAOD::MuonSegment* truthSegment = *truthSegLink;
199 if (!truthSegment) {
200 ATH_MSG_WARNING("Invalid truth segment link " << truthSegLink);
201 continue;
202 }
203 ATH_MSG_DEBUG("truthSegLink " << truthSegLink);
205 truthParticleLinkAcc("truthParticleLink");
206 if (!truthParticleLinkAcc.isAvailable(*truthSegment)) {
207 ATH_MSG_WARNING("truthSegment without truthParticleLink ");
208 continue;
209 }
211 truthParticleLinkAcc(*truthSegment);
212 const xAOD::TruthParticle* truthParticle = *truthLink;
213 if (!truthParticle) {
214 ATH_MSG_WARNING("Invalid truth link " << truthLink);
215 continue;
216 }
217 // match barcodes
218 if (HepMC::is_sim_descendant(result.second.truthTrack,truthParticle)) { // comparing TrackRecord to xAOD::TruthParticle
219 ATH_MSG_DEBUG("Matched reconstructed segment: barcode " << barcode << " layer "
221 recoLink.toPersistent();
222 truthLink.toPersistent();
223 muonTruthSegments(*truthSegment) = recoLink;
224 segments(*recoSegment) = truthSegLink;
225 } else {
226 ATH_MSG_DEBUG("barcode mismatch " << barcode << " truthParticle->uniqueID " << HepMC::uniqueID(truthParticle));
227 }
228 }
229 }
230 return StatusCode::SUCCESS;
231 }
232
233} // namespace Muon
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Helper class to provide constant type-safe access to aux data.
Handle class for adding a decoration to an object.
An algorithm that can be simultaneously executed in multiple threads.
std::map< int, TruthTreeEntry > TruthTree
std::vector< SegmentMatchResult > SegmentResultVec
ToolHandle< Muon::IMuonTrackTruthTool > m_muonTrackTruthTool
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_muonSegmentCollectionName
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
MuonSegmentTruthAssociationAlg(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadHandleKeyArray< MuonSimDataCollection > m_muonSimData
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
SG::ReadHandleKey< McEventCollection > m_mcEventColl
SG::ReadHandleKey< CscSimDataCollection > m_cscSimData
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_muonTruthSegmentContainerName
virtual StatusCode execute(const EventContext &ctx) const override
SG::ReadHandleKey< TrackRecordCollection > m_trackRecord
This is the common class for 3D segments used in the muon spectrometer.
Helper class to provide constant type-safe access to aux data.
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
Handle class for adding a decoration to an object.
bool isPresent() const
Is the referenced container present in SG?
int uniqueID(const T &p)
bool is_sim_descendant(const T1 &p1, const T2 &p2)
Method to check if the first particle is a descendant of the second in the simulation,...
ChIndex chIndex(const std::string &index)
convert ChIndex name string to enum
const std::string & chName(ChIndex index)
convert ChIndex into a string
ChIndex
enum to classify the different chamber layers in the muon spectrometer
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
Definition index.py:1
TruthParticle_v1 TruthParticle
Typedef to implementation.
MuonSegment_v1 MuonSegment
Reference the current persistent version: