21 #include "GaudiKernel/PhysicalConstants.h"
23 #include <unordered_map>
30 using namespace SegmentFit;
31 template <
class ContainerType>
34 const ContainerType*& contToPush)
const {
38 return StatusCode::SUCCESS;
42 contToPush = readHandle.cptr();
43 return StatusCode::SUCCESS;
48 if (m_readKeys.empty()){
49 ATH_MSG_ERROR(
"No simulated hit containers have been parsed to build the segments from ");
50 return StatusCode::FAILURE;
61 return StatusCode::SUCCESS;
74 ATH_CHECK(retrieveContainer(ctx, m_geoCtxKey, gctx));
77 using HitsPerParticle = std::unordered_map<HepMC::ConstGenParticlePtr, std::vector<const xAOD::MuonSimHit*>>;
78 using HitCollector = std::unordered_map<const MuonGMR4::SpectrometerSector*, HitsPerParticle>;
79 HitCollector hitCollector{};
87 auto genLink = simHit->genParticleLink();
89 if (genLink.isValid()){
90 genParticle = genLink.cptr();
93 if (!genParticle || (m_useOnlyMuonHits && std::abs(simHit->pdgId()) != 13)) {
96 hitCollector[
id][genParticle].push_back(simHit);
101 ATH_CHECK(writeHandle.record(std::make_unique<xAOD::MuonSegmentContainer>(),
102 std::make_unique<xAOD::MuonSegmentAuxContainer>()));
104 using HitLinkVec = std::vector<ElementLink<xAOD::MuonSimHitContainer>>;
110 for (
auto& [
chamber, collectedParts] : hitCollector) {
113 for (
auto& [
particle, simHits]: collectedParts) {
117 return std::abs((toChamber(*gctx,
a->identify())* xAOD::toEigen(
a->localPosition())).z()) <
118 std::abs((toChamber(*gctx,
b->identify())* xAOD::toEigen(
b->localPosition())).z());
124 const Amg::Vector3D localPos{inChamb * xAOD::toEigen(simHit->localPosition())};
125 const Amg::Vector3D chamberDir = inChamb.linear() * xAOD::toEigen(simHit->localDirection());
128 const double distance = Amg::intersect<3>(localPos, chamberDir, Amg::Vector3D::UnitZ(), 0.).value_or(0.);
132 const Amg::Vector3D globDir = locToGlob.linear() * chamberDir;
133 HitLinkVec associatedHits{};
134 unsigned int nMdt{0}, nRpcEta{0}, nRpcPhi{0}, nTgcEta{0}, nTgcPhi{0};
135 unsigned int nMm{0}, nStgcEta{0}, nStgcPhi{0};
144 if (castRE->nEtaStrips()) ++nRpcEta;
145 if (castRE->nPhiStrips()) ++nRpcPhi;
149 const int gasGap = m_idHelperSvc->gasGap(assocMe->identify());
150 if (castRE->numStrips(
gasGap)) ++nTgcPhi;
151 if (castRE->numWireGangs(
gasGap)) ++nTgcEta;
162 ATH_MSG_WARNING(
"Csc are not defined "<<m_idHelperSvc->toString(simHit->identify()));
166 associatedHits.
push_back(std::move(link));
168 int nPrecisionHits = nMdt + nMm + nStgcEta;
169 int nPhiLayers = nTgcPhi + nRpcPhi + nStgcPhi;
171 if (nPrecisionHits < 3)
continue;
173 xAOD::MuonSegment* truthSegment = writeHandle->push_back(std::make_unique<xAOD::MuonSegment>());
174 ptDecor(*truthSegment) =
particle->momentum().perp();
175 qDecor(*truthSegment) =
particle->pdg_id() > 0 ? -1 : 1;
176 SegPars& locPars{parDecor(*truthSegment)};
182 truthSegment->
setPosition(globPos.x(), globPos.y(), globPos.z());
183 truthSegment->
setDirection(globDir.x(), globDir.y(), globDir.z());
186 truthSegment->
setNHits(nPrecisionHits, nPhiLayers, nTgcEta + nRpcEta);
188 m_idHelperSvc->chamberIndex(segId),
189 m_idHelperSvc->stationEta(segId),
190 m_idHelperSvc->technologyIndex(segId));
192 if (nPhiLayers == 0){
193 truthSegment->
setFitQuality(0, (nPrecisionHits + nTgcEta + nRpcEta - 3));
195 truthSegment->
setFitQuality(0, (nPrecisionHits + nPhiLayers + nTgcEta + nRpcEta - 5));
197 hitDecor(*truthSegment) = std::move(associatedHits);
200 return StatusCode::SUCCESS;