ATLAS Offline Software
Loading...
Searching...
No Matches
xAODSegmentCnvAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4#include "xAODSegmentCnvAlg.h"
5
9
14
15#include "Acts/Utilities/Enumerate.hpp"
16#include "Acts/Surfaces/StrawSurface.hpp"
17#include "Acts/Surfaces/LineBounds.hpp"
18#include "Acts/Definitions/Units.hpp"
19
20using namespace Acts::UnitLiterals;
21namespace MuonR4{
22 using namespace SegmentFit;
31 using PrdLinkVec_t = std::vector<PrdLink_t>;
33 using SegPars_t = xAOD::PosAccessor<Acts::toUnderlying(ParamDefs::nPars)>::element_type;
35 using SegCov_t = xAOD::PosAccessor<Acts::sumUpToN(Acts::toUnderlying(ParamDefs::nPars))>::element_type;
37 ATH_CHECK(m_idHelperSvc.retrieve());
38 ATH_CHECK(m_readKeys.initialize());
39 ATH_CHECK(m_geoCtxKey.initialize());
40 ATH_CHECK(m_writeKey.initialize());
41 ATH_CHECK(m_prdLinkKey.initialize());
42 ATH_CHECK(m_localSegParKey.initialize());
43 ATH_CHECK(m_localSegCovKey.initialize());
44 ATH_CHECK(m_parentSegKey.initialize());
45 ATH_CHECK(m_combMeasKey.initialize());
46 ATH_CHECK(m_prdStateKey.initialize());
48 return StatusCode::SUCCESS;
49 }
50 StatusCode xAODSegmentCnvAlg::execute(const EventContext& ctx) const {
51 const ActsTrk::GeometryContext* gctx{nullptr};
52 ATH_CHECK(SG::get(gctx, m_geoCtxKey, ctx));
53
54 SG::WriteHandle outContainer{m_writeKey, ctx};
55 ATH_CHECK(outContainer.record(std::make_unique<xAOD::MuonSegmentContainer>(),
56 std::make_unique<xAOD::MuonSegmentAuxContainer>()));
57
58 SG::WriteHandle prdCombContainer{m_combMeasKey, ctx};
59 ATH_CHECK(prdCombContainer.record(std::make_unique<xAOD::CombinedMuonStripContainer>(),
60 std::make_unique<xAOD::CombinedMuonStripAuxContainer>()));
61
65
68
70 // Cache all measurements that can be combined to two measurements in a single gas gap
71 std::vector< std::tuple<const xAOD::MuonMeasurement*, State, std::size_t>> combineMap{};
72 std::vector< std::tuple<const xAOD::UncalibratedMeasurement*, State, std::size_t>> linkMap{};
73
74 const xAOD::UncalibratedMeasurement* beamSpotMeas{};
75
76 auto beamSpotMeasCreator = m_auxMeasProv.makeHandle(ctx, gctx->context());
77
84 auto decorateLinks = [&](const Segment& inSegment, xAOD::MuonSegment& outSegment) {
85 PrdLinkVec_t& links = dec_prdLinks(outSegment);
86 std::vector<char>& linkStates = dec_prdStates(outSegment);
87 links.reserve(2*inSegment.measurements().size());
88 linkStates.reserve(2*inSegment.measurements().size());
89
92 auto combine = [this,&prdCombContainer](const xAOD::MuonMeasurement* m1,
93 const xAOD::MuonMeasurement* m2) {
94 auto cmbMeas = prdCombContainer->push_back(std::make_unique<xAOD::CombinedMuonStrip>());
95
96 cmbMeas->setPrimaryStrip(m1);
97 cmbMeas->setSecondaryStrip(m2);
98 const auto [locPos, locCov] = xAOD::positionAndCovariance(m1, m2);
99 cmbMeas->localCovariance<2>() = xAOD::toStorage(locCov);
100 cmbMeas->localPosition<2>() = xAOD::toStorage(locPos);
101 const Identifier id1{m1->identify()}, id2{m2->identify()};
102 ATH_MSG_VERBOSE("Combine "<<m_idHelperSvc->toString(id1)
103 <<" & "<<m_idHelperSvc->toString(id2));
104 if ((m1->type() != xAOD::UncalibMeasType::sTgcStripType ||
105 m_idHelperSvc->stgcIdHelper().channelType(id1) ==
106 m_idHelperSvc->stgcIdHelper().channelType(id2))&&
107 m_idHelperSvc->measuresPhi(id1) == m_idHelperSvc->measuresPhi(id2)) {
108 THROW_EXCEPTION("Cannot combine "<<m_idHelperSvc->toString(id1)
109 <<" & "<<m_idHelperSvc->toString(id2));
110 }
111 return cmbMeas;
112 };
113 // Loop over the measurements
114 for (const auto [segIdx, meas] : Acts::enumerate(inSegment.measurements())) {
115 const SpacePoint* sp = meas->spacePoint();
116 if (!sp) {
117 if (!m_convertBeamSpot) {
118 continue;
119 }
120 // Up to now, there's no variety on the beamspot across the segments
121 if (!beamSpotMeas) {
122 if (!beamSpotMeasCreator.ok()) {
123 ATH_MSG_ERROR("Cannot create a beamspot measurement");
124 return StatusCode::FAILURE;
125 }
126
127 const Amg::Vector3D beamSpot = inSegment.msSector()->localToGlobalTransform(*gctx) *
128 meas->localPosition();
129 AmgSymMatrix(2) covariance{AmgSymMatrix(2)::Identity()};
130 using CovIdx = SpacePoint::CovIdx;
131 using ProjectorType = xAOD::AuxiliaryMeasurement::ProjectorType;
132 covariance(0,0) = meas->covariance()[Acts::toUnderlying(CovIdx::etaCov)];
133 covariance(1,1) = meas->covariance()[Acts::toUnderlying(CovIdx::phiCov)];
135 auto surf = Acts::Surface::makeShared<Acts::StrawSurface>(Amg::getTranslate3D(beamSpot),
136 std::make_shared<Acts::LineBounds>(std::sqrt(covariance(0,0)), 20._m));
137
138 beamSpotMeas = beamSpotMeasCreator->newMeasurement<2>(surf,
139 ProjectorType::e2DimNoTime, covariance);
140 ATH_MSG_DEBUG("Created beamspot measurement "<<(*meas)<<", "
141 <<surf->toString(gctx->context()));
142 }
143 linkMap.emplace_back(beamSpotMeas, meas->fitState(), segIdx);
144 continue;
145 }
146 switch (sp->type()) {
147 using enum xAOD::UncalibMeasType;
148 // Mdt & micromegas are never combined
149 case MdtDriftCircleType:
150 case MMClusterType: {
151 linkMap.emplace_back(sp->primaryMeasurement(), meas->fitState(), segIdx);
152 break;
153 } case RpcStripType:
154 case TgcStripType:
155 case sTgcStripType: {
156 if (sp->primaryMeasurement() && sp->secondaryMeasurement()) {
157 if (sp->primaryMeasurement() != sp->secondaryMeasurement()) {
158 linkMap.emplace_back(combine(sp->primaryMeasurement(),
159 sp->secondaryMeasurement()),
160 meas->fitState(), segIdx);
161 } else { // BI - RPC measurements
162 linkMap.emplace_back(sp->primaryMeasurement(), meas->fitState(), segIdx);
163 }
164 } else {
167 ATH_MSG_VERBOSE("Append for later combination "<<(*meas));
168 combineMap.emplace_back(sp->primaryMeasurement(), meas->fitState(), segIdx);
169 }
170 break;
171 } default:
172 break;
173 }
174 }
175 // Finally we need to check whether there're measurements left to combine
176 for (std::size_t cmbIdx = 0; cmbIdx < combineMap.size(); ++cmbIdx){
177 const xAOD::MuonMeasurement* m1{std::get<0>(combineMap[cmbIdx])};
178 const State s1{std::get<1>(combineMap[cmbIdx])};
179 const std::size_t segIdx1{std::get<2>(combineMap[cmbIdx])};
180 ATH_MSG_VERBOSE("Find another measurement to combine with "
181 <<m_idHelperSvc->toString(m1->identify()));
182 if (cmbIdx +1 < combineMap.size()){
183 const xAOD::MuonMeasurement* m2{std::get<0>(combineMap[cmbIdx +1])};
184 const State s2{std::get<1>(combineMap[cmbIdx+1])};
185 ATH_MSG_VERBOSE("Check whether "<<m_idHelperSvc->toString(m2->identify())
186 <<" is a good candidate");
187 if (m1->type() == m2->type() &&
188 m1->identifierHash() == m2->identifierHash() &&
189 m1->layerHash() == m2->layerHash() &&
190 s1 == s2) {
192 ATH_MSG_VERBOSE("They match");
193 if (m1->measuresPhi()) {
194 linkMap.emplace_back(combine(m2, m1), s2, segIdx1);
195 } else {
196 linkMap.emplace_back(combine(m1, m2), s1, segIdx1);
197 }
198 ++cmbIdx; // skip the next measurement as it's absorbed here
199 continue;
200 }
201 }
202 ATH_MSG_VERBOSE("No match found");
203 linkMap.emplace_back(m1, s1, segIdx1);
204 }
205
206 std::ranges::sort(linkMap, [](const auto& a, const auto& b){
207 return std::get<2>(a) < std::get<2>(b);
208 });
209
210 for (const auto& [prd, state, segIdx]: linkMap) {
211 links.emplace_back(
212 *static_cast<const xAOD::UncalibratedMeasurementContainer*>(prd->container()),
213 prd->index());
214 linkStates.emplace_back(Acts::toUnderlying(state));
215 }
216 linkMap.clear();
217 combineMap.clear();
218 return StatusCode::SUCCESS;
219 };
220
222 const SegmentContainer* segmentContainer{nullptr};
223 ATH_CHECK(SG::get(segmentContainer, key, ctx));
224
226 unsigned recoSegIdx{0};
227 outContainer->reserve(outContainer->size() + segmentContainer->size());
228 for (const Segment* inSegment : *segmentContainer) {
229 const MuonGMR4::SpectrometerSector* sector = inSegment->msSector();
230
231 xAOD::MuonSegment* convertedSeg = outContainer->push_back(std::make_unique<xAOD::MuonSegment>());
232 dec_parentLink(*convertedSeg) = SegLink_t{segmentContainer, recoSegIdx};
233 ++recoSegIdx;
234
235 const Amg::Vector3D& pos{inSegment->position()};
236 const Amg::Vector3D& dir{inSegment->direction()};
237 convertedSeg->setPosition(pos.x(), pos.y(), pos.z());
238 convertedSeg->setDirection(dir.x(), dir.y(), dir.z());
239
240
241 convertedSeg->setIdentifier(sector->sector(), sector->chamberIndex(), sector->side(),
242 xAOD::toTechnologyIndex(inSegment->summary().tech));
243 convertedSeg->setFitQuality(inSegment->chi2(), inSegment->nDoF());
244 convertedSeg->setNHits(inSegment->summary().nPrecHits, inSegment->summary().nPhiHits,
245 inSegment->summary().nEtaTrigHits);
246
247 using enum ParamDefs;
248 convertedSeg->setT0Error(inSegment->segementT0(),
249 Amg::error(inSegment->covariance(), Acts::toUnderlying(t0)));
250
251 SegPars_t& localPars{dec_locPars(*convertedSeg)};
252 const Amg::Transform3D globToLoc{sector->globalToLocalTransform(*gctx)};
253 const Amg::Vector3D locPos{globToLoc * pos};
254 const Amg::Vector3D locDir{globToLoc.linear() * dir};
255
256 localPars[Acts::toUnderlying(x0)] = locPos.x();
257 localPars[Acts::toUnderlying(y0)] = locPos.y();
258 localPars[Acts::toUnderlying(theta)] = locDir.theta();
259 localPars[Acts::toUnderlying(phi)] = locDir.phi();
260 localPars[Acts::toUnderlying(t0)] = inSegment->segementT0();
261
262 SegCov_t& localCov{dec_locCov(*convertedSeg)};
263 constexpr std::size_t n = Acts::toUnderlying(ParamDefs::nPars);
264 for (std::size_t p = 1; p < n; ++p) {
265 for (std::size_t p1 = 0 ; p1 <=p;++p1) {
266 localCov[Acts::vecIdxFromSymMat<n>(p,p1)] = inSegment->covariance()(p, p1);
267 }
268 }
269 ATH_CHECK(decorateLinks(*inSegment, *convertedSeg));
270 }
271 }
272 return StatusCode::SUCCESS;
273 }
274}
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
#define AmgSymMatrix(dim)
static Double_t sp
static Double_t a
static Double_t t0
Handle class for adding a decoration to an object.
Handle class for recording to StoreGate.
Acts::GeometryContext context() const
size_type size() const noexcept
Returns the number of elements in the collection.
A spectrometer sector forms the envelope of all chambers that are placed in the same MS sector & laye...
int8_t side() const
Returns the side of the MS-sector 1 -> A side ; -1 -> C side.
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &gctx) const
Returns the local -> global tarnsformation from the sector.
Amg::Transform3D globalToLocalTransform(const ActsTrk::GeometryContext &gctx) const
Returns the global -> local transformation from the ATLAS global.
int sector() const
Returns the sector of the MS-sector.
Muon::MuonStationIndex::ChIndex chamberIndex() const
Returns the chamber index scheme.
State
State flag to distinguish different space point states.
Placeholder for what will later be the muon segment EDM representation.
double segementT0() const
Returns the fitted segment time, if there's any.
unsigned int nDoF() const
Returns the number of degrees of freedom.
const SegmentFit::Covariance & covariance() const
Returns the uncertainties of the defining parameters.
const MuonGMR4::SpectrometerSector * msSector() const
Returns the associated MS sector.
const MeasVec & measurements() const
Returns the associated measurements.
const Amg::Vector3D & position() const
Returns the global segment position.
const Amg::Vector3D & direction() const
Returns the global segment direction.
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
DecorKey_t m_prdStateKey
Decoration to the PrdLink state (I.e.
DecorKey_t m_localSegParKey
Decoration of the local segment parameters.
DecorKey_t m_localSegCovKey
Decoration of the local fit covariance parameters.
DecorKey_t m_parentSegKey
Decoration of the original segment.
SG::WriteHandleKey< xAOD::MuonSegmentContainer > m_writeKey
Output segment container key.
SG::WriteHandleKey< xAOD::CombinedMuonStripContainer > m_combMeasKey
Auxiliary container to model two measurements in the same gas gap as a single track state.
DecorKey_t m_prdLinkKey
Decoration to the links to the associated Uncalibrated measurements.
virtual StatusCode execute(const EventContext &ctx) const override final
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
IdHelperSvc for Identifier printing & manipulation.
virtual StatusCode initialize() override final
Gaudi::Property< bool > m_convertBeamSpot
Flag to convert the beamspot constaint as well.
ActsTrk::AuxiliaryMeasurementHandler m_auxMeasProv
Handler to parse the auxiliary beam spot constaint.
SG::ReadHandleKeyArray< SegmentContainer > m_readKeys
Input segment container key.
ActsTrk::GeoContextReadKey_t m_geoCtxKey
Alignment container key.
Property holding a SG store/key/clid from which a ReadHandle is made.
Handle class for adding a decoration to an object.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
ActsTrk::detail::MeasurementCalibratorBase::ProjectorType ProjectorType
Use the calibration projector.
void setDirection(float px, float py, float pz)
Sets the direction.
void setFitQuality(float chiSquared, float numberDoF)
Set the 'Fit Quality' information.
void setNHits(int nPrecisionHits, int nPhiLayers, int nTrigEtaLayers)
Set the number of hits/layers.
void setT0Error(float t0, float t0Error)
Sets the time error.
void setIdentifier(int sector, ::Muon::MuonStationIndex::ChIndex chamberIndex, int etaIndex, ::Muon::MuonStationIndex::TechnologyIndex technology)
Set the identifier.
void setPosition(float x, float y, float z)
Sets the global position.
Amg::Transform3D getTranslate3D(const double X, const double Y, const double Z)
: Returns a shift transformation along an arbitrary axis
double error(const Amg::MatrixX &mat, int index)
return diagonal error of the matrix caller should ensure the matrix is symmetric and the index is in ...
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 3, 1 > Vector3D
SeedingAux::FitParIndex ParamDefs
Use the same parameter indices as used by the CompSpacePointAuxiliaries.
This header ties the generic definitions in this package.
std::vector< PrdLink_t > PrdLinkVec_t
Abrivation of a collection of Prd links.
CalibratedSpacePoint::State State
ElementLink< MuonR4::SegmentContainer > SegLink_t
Abrivation of the link to the reco segment container.
xAOD::UncalibratedMeasurementContainer PrdCont_t
Abrivation to call an uncalibrated measurement container.
DataVector< Segment > SegmentContainer
ElementLink< PrdCont_t > PrdLink_t
Abrivation to call the link to an element inside an uncalibrated measurement container.
xAOD::PosAccessor< Acts::sumUpToN(Acts::toUnderlying(ParamDefs::nPars))>::element_type SegCov_t
Abrivation of the decorated local segment covariance.
xAOD::PosAccessor< Acts::toUnderlying(ParamDefs::nPars)>::element_type SegPars_t
Abrivation of the decorated local segment parameters.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
SG::AuxElement::Accessor< std::array< float, N > > PosAccessor
xAOD Accessor to the position
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.
MuonMeasurement_v1 MuonMeasurement
::Muon::MuonStationIndex::TechnologyIndex toTechnologyIndex(const UncalibMeasType aodType)
Transforms the uncalibrated measurement type to a technology index.
MeasVector< N > toStorage(const AmgVector(N)&amgVec)
Converts the double precision of the AmgVector into the floating point storage precision of the MeasV...
UncalibMeasType
Define the type of the uncalibrated measurement.
std::pair< Amg::Vector2D, AmgSymMatrix(2)> positionAndCovariance(const MuonMeasurement *oneDimMeas)
Returns the 1D position of the uncalibrated measurement expressed in the coordinate system of the mea...
UncalibratedMeasurementContainer_v1 UncalibratedMeasurementContainer
Define the version of the uncalibrated measurement container.
MuonSegment_v1 MuonSegment
Reference the current persistent version:
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10