ATLAS Offline Software
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 
9 #include "xAODMuon/MuonSegment.h"
14 #include "xAODTruth/TruthVertex.h"
16 
17 namespace 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());
27  ATH_CHECK(m_muonTrackTruthTool.retrieve());
29  m_muonSegmentCollectionName = m_muonSegmentCollectionName.key() + ".truthSegmentLink";
33  if (!(m_idHelperSvc->hasSTGC() && m_idHelperSvc->hasMM())) m_muonSimData = {"MDT_SDO", "RPC_SDO", "TGC_SDO"};
34  ATH_CHECK(m_muonSimData.initialize());
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) {
86  segments(*seg) = ElementLink<xAOD::MuonSegmentContainer>();
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 
98  SG::ReadHandle<McEventCollection> mcEventCollection(m_mcEventColl, ctx);
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
137  IMuonTrackTruthTool::SegmentResultVec segmentResultVec;
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::barcode(result.second.truthTrack); // FIXME barcode-based - requires TrackRecords to be migrated to uniqueID
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 
154  Muon::MuonStationIndex::ChIndex chIndex = m_idHelperSvc->chamberIndex(id);
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 "
220  << Muon::MuonStationIndex::chName(chIndex));
221  recoLink.toPersistent();
222  truthLink.toPersistent();
223  muonTruthSegments(*truthSegment) = recoLink;
224  segments(*recoSegment) = truthSegLink;
225  } else {
226  ATH_MSG_DEBUG("barcode mismatch " << barcode << " truthParticle->barcode " << HepMC::barcode(truthParticle));
227  }
228  }
229  }
230  return StatusCode::SUCCESS;
231  }
232 
233 } // namespace Muon
Muon::MuonStationIndex::chName
static const std::string & chName(ChIndex index)
convert ChIndex into a string
Definition: MuonStationIndex.cxx:157
get_generator_info.result
result
Definition: get_generator_info.py:21
Muon::MuonSegmentTruthAssociationAlg::m_printer
PublicToolHandle< Muon::MuonEDMPrinterTool > m_printer
Definition: MuonSegmentTruthAssociationAlg.h:37
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
Muon::MuonSegmentTruthAssociationAlg::m_trackRecord
SG::ReadHandleKey< TrackRecordCollection > m_trackRecord
Definition: MuonSegmentTruthAssociationAlg.h:50
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
index
Definition: index.py:1
MuonSegmentAuxContainer.h
TruthParticleContainer.h
MuonSegment.h
xAOD::MuonSegment_v1
Class describing a MuonSegment.
Definition: MuonSegment_v1.h:33
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:55
Muon
This class provides conversion from CSC RDO data to CSC Digits.
Definition: TrackSystemController.h:45
Muon::MuonSegmentTruthAssociationAlg::initialize
virtual StatusCode initialize() override
Definition: MuonSegmentTruthAssociationAlg.cxx:24
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
AtlasHitsVector::empty
bool empty() const
Definition: AtlasHitsVector.h:129
Muon::MuonSegmentTruthAssociationAlg::MuonSegmentTruthAssociationAlg
MuonSegmentTruthAssociationAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition: MuonSegmentTruthAssociationAlg.cxx:20
TruthParticleAuxContainer.h
inspect_truth_file.truth_tree
truth_tree
Definition: inspect_truth_file.py:75
Muon::MuonSegmentTruthAssociationAlg::m_idHelperSvc
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Definition: MuonSegmentTruthAssociationAlg.h:35
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
HepMC::barcode
int barcode(const T *p)
Definition: Barcode.h:16
xAOD::TruthParticle_v1
Class describing a truth particle in the MC record.
Definition: TruthParticle_v1.h:37
SG::WriteDecorHandle
Handle class for adding a decoration to an object.
Definition: StoreGate/StoreGate/WriteDecorHandle.h:100
WriteDecorHandle.h
Handle class for adding a decoration to an object.
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
Muon::MuonSegmentTruthAssociationAlg::m_muonTruthSegmentContainerName
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_muonTruthSegmentContainerName
Definition: MuonSegmentTruthAssociationAlg.h:41
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Muon::MuonSegmentTruthAssociationAlg::m_muonSegmentCollectionName
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_muonSegmentCollectionName
Definition: MuonSegmentTruthAssociationAlg.h:43
Muon::MuonSegmentTruthAssociationAlg::execute
virtual StatusCode execute(const EventContext &ctx) const override
Definition: MuonSegmentTruthAssociationAlg.cxx:41
min
#define min(a, b)
Definition: cfImp.cxx:40
TruthVertex.h
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:220
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
MagicNumbers.h
Muon::MuonSegmentTruthAssociationAlg::m_muonSimData
SG::ReadHandleKeyArray< MuonSimDataCollection > m_muonSimData
Definition: MuonSegmentTruthAssociationAlg.h:47
MuonSegmentTruthAssociationAlg.h
Muon::IMuonTrackTruthTool::SegmentResultVec
std::vector< SegmentMatchResult > SegmentResultVec
Definition: IMuonTrackTruthTool.h:90
SG::VarHandleBase::key
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleBase.cxx:64
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
Muon::IMuonTrackTruthTool::TruthTree
std::map< int, TruthTreeEntry > TruthTree
Definition: IMuonTrackTruthTool.h:93
Muon::MuonSegmentTruthAssociationAlg::m_muonTrackTruthTool
ToolHandle< Muon::IMuonTrackTruthTool > m_muonTrackTruthTool
Definition: MuonSegmentTruthAssociationAlg.h:38
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Muon::MuonStationIndex::ChIndex
ChIndex
enum to classify the different chamber layers in the muon spectrometer
Definition: MuonStationIndex.h:15
MuonSegment.h
SG::ConstAccessor::isAvailable
bool isAvailable(const ELT &e) const
Test to see if this variable exists in the store.
HepMC::is_sim_descendant
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,...
Definition: MagicNumbers.h:360
Muon::MuonSegment
Definition: MuonSpectrometer/MuonReconstruction/MuonRecEvent/MuonSegment/MuonSegment/MuonSegment.h:45
ConstAccessor.h
Helper class to provide constant type-safe access to aux data.
skip
bool skip
Definition: TrigGlobEffCorrValidation.cxx:190
Muon::MuonSegmentTruthAssociationAlg::m_mcEventColl
SG::ReadHandleKey< McEventCollection > m_mcEventColl
Definition: MuonSegmentTruthAssociationAlg.h:46
SG::WriteDecorHandle::isPresent
bool isPresent() const
Is the referenced container present in SG?
Muon::MuonSegmentTruthAssociationAlg::m_cscSimData
SG::ReadHandleKey< CscSimDataCollection > m_cscSimData
Definition: MuonSegmentTruthAssociationAlg.h:49
Identifier
Definition: IdentifierFieldParser.cxx:14