ATLAS Offline Software
Loading...
Searching...
No Matches
SegmentActsRefitAlg.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
12
17#include "GaudiKernel/PhysicalConstants.h"
19#include "CLHEP/Random/RandGaussZiggurat.h"
24
25#include "Acts/Surfaces/PlaneSurface.hpp"
27
28using namespace Acts::UnitLiterals;
29namespace{
30 constexpr double straightQoverP = 1. / (100._TeV);
31 constexpr double pseudoSurfDist = 5.*Gaudi::Units::cm;
33}
34
35
36namespace MuonR4{
37 using namespace SegmentFit;
38
40 ATH_CHECK(m_readKey.initialize());
41 ATH_CHECK(m_writeKey.initialize());
42 ATH_CHECK(m_linkKey.initialize());
43 ATH_CHECK(m_localParsKey.initialize());
44 ATH_CHECK(m_seedParsKey.initialize());
45 ATH_CHECK(m_surfKey.initialize());
46 ATH_CHECK(m_auxMeasProv.initialize(m_writeKey.key()));
47 ATH_CHECK(m_calibTool.retrieve());
48
49 ATH_CHECK(m_idHelperSvc.retrieve());
50 ATH_CHECK(m_trackFitTool.retrieve());
53 ATH_CHECK(m_segSelector.retrieve());
54 ATH_CHECK(detStore()->retrieve(m_detMgr));
55 return StatusCode::SUCCESS;
56 }
57 std::tuple<Amg::Vector3D, Amg::Vector3D>
59 const MuonR4::Segment& segment,
60 CLHEP::HepRandomEngine* engine) const{
61 // return std::make_pair(segment.position(), segment.direction()* (segment.direction().z() < 0 ? -1. : 1.));
62 const auto segPars = localSegmentPars(gctx, segment);
63 auto smearedPars = segPars;
65 for (ParamDefs precPar : {ParamDefs::y0, ParamDefs::theta,
66 ParamDefs::x0, ParamDefs::phi}) {
67 if (precPar == ParamDefs::phi && !segment.summary().nPhiHits) {
68 break;
69 }
70 const unsigned idx = Acts::toUnderlying(precPar);
71 const double uncert = Amg::error(segment.covariance(), idx) * m_smearRange;
72 smearedPars[idx] = CLHEP::RandGaussZiggurat::shoot(engine, segPars[idx], uncert);
73 ATH_MSG_VERBOSE("Apply smearing to "<<SeedingAux::parName(precPar)
74 <<" parameter -- cov: "<<uncert
75 <<", original: "<<segPars[idx]<<", smeared: "<<smearedPars[idx]<<", deviation: "
76 <<(smearedPars[idx] - segPars[idx]) / uncert );
77
78 }
79 auto [smearLocPos, smearLocDir] = makeLine(smearedPars);
80 const auto [locPos, locDir] = makeLine(segPars);
82 if (SeedingAux::strawSigns(locPos,locDir, segment.measurements()) !=
83 SeedingAux::strawSigns(smearLocPos, smearLocDir, segment.measurements())) {
84 ATH_MSG_ALWAYS("Parameter smearng from "<<toString(segPars)<<" -> "<<toString(smearedPars)
85 <<" changes the L/R ambiguity -> avoid for this test");
86 return smearSegment(gctx, segment, engine);
87 }
88
89 const Amg::Transform3D& locToGlob{segment.msSector()->localToGlobalTrans(gctx)};
90 if (smearLocDir.z() < 0) {
91 smearLocDir = -smearLocDir;
92 }
93 return std::make_tuple(locToGlob * smearLocPos, locToGlob.linear() * smearLocDir);
94 }
95 StatusCode SegmentActsRefitAlg::execute(const EventContext& ctx) const {
96
97 const xAOD::MuonSegmentContainer* segments{nullptr};
98 ATH_CHECK(SG::get(segments, m_readKey, ctx));
100 const ActsTrk::GeometryContext& gctx{m_trackingGeometryTool->getGeometryContext(ctx)};
101 const Acts::GeometryContext tgContext = gctx.context();
102 const Acts::MagneticFieldContext mfContext = m_extrapolationTool->getMagneticFieldContext(ctx);
103 const Acts::CalibrationContext calContext = ActsTrk::getCalibrationContext(ctx);
104
106 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, name());
107 rngWrapper->setSeed(name(), ctx);
108 CLHEP::HepRandomEngine* randEngine = rngWrapper->getEngine(ctx);
109
110 SG::WriteHandle outHandle{m_writeKey, ctx};
111 ATH_CHECK(outHandle.record(std::make_unique<xAOD::MuonSegmentContainer>(),
112 std::make_unique<xAOD::MuonSegmentAuxContainer>()));
113
114 SG::WriteHandle surfaceHandle{m_surfKey, ctx};
115 ATH_CHECK(surfaceHandle.record(std::make_unique<xAOD::TrackSurfaceContainer>(),
116 std::make_unique<xAOD::TrackStateAuxContainer>()));
117
119 auto auxMeasHandle = m_auxMeasProv.makeHandle(ctx, *surfaceHandle);
120
124 xAOD::MeasVector<Acts::toUnderlying(ParamDefs::nPars)>>;
125
126 ParDecor_t dec_locPars{m_localParsKey, ctx};
127 ParDecor_t dec_seedPars{m_seedParsKey, ctx};
128
129 Acts::ObjVisualization3D visualHelper{};
130
132 for (const xAOD::MuonSegment* reFitMe: *segments){
133 const auto msSector = m_detMgr->getSectorEnvelope(reFitMe->chamberIndex(),
134 reFitMe->sector(),
135 reFitMe->etaIndex());
136 const Amg::Transform3D& sectorTrf{msSector->localToGlobalTrans(gctx)};
137
138 m_calibTool->stampSignsOnMeasurements(*reFitMe);
139
141 const auto [seedPos, seedDir] = smearSegment(gctx, *MuonR4::detailedSegment(*reFitMe), randEngine);
143 {
144 auto invTrf = sectorTrf.inverse();
145 const Amg::Vector3D locSeedPos = invTrf * seedPos;
146 const Amg::Vector3D locSeedDir = invTrf.linear() * seedDir;
147 auto& seedPars = dec_seedPars(*reFitMe);
148 seedPars[Acts::toUnderlying(ParamDefs::x0)] = locSeedPos.x();
149 seedPars[Acts::toUnderlying(ParamDefs::y0)] = locSeedPos.y();
150 seedPars[Acts::toUnderlying(ParamDefs::theta)] = locSeedDir.theta();
151 seedPars[Acts::toUnderlying(ParamDefs::phi)] = locSeedDir.phi();
152 }
153
154 const GeoTrf::CoordEulerAngles sectorAngles = GeoTrf::getCoordRotationAngles(sectorTrf);
156 std::vector<const xAOD::UncalibratedMeasurement*> startMeas = MuonR4::collectMeasurements(*reFitMe);
157
158 const auto* refMeas = startMeas.front();
159
160 const Amg::Vector3D firstSurfPos{surfAcc.get(refMeas)->transform(tgContext).translation()};
161
162 if (reFitMe->nPhiLayers() < 1) {
163 const Amg::Vector3D planeNormal = sectorTrf.linear().col(2);
164
165 const Amg::Vector3D lastSurfPos = surfAcc.get(startMeas.back())->transform(tgContext).translation();
167
168 const Amg::Transform3D trfBeneath = GeoTrf::GeoTransformRT{sectorAngles, firstSurfPos - pseudoSurfDist * planeNormal};
169 const Amg::Transform3D trfAbove = GeoTrf::GeoTransformRT{sectorAngles, lastSurfPos + pseudoSurfDist * planeNormal};
170
171 auto surfBeneath = Acts::Surface::makeShared<Acts::PlaneSurface>(trfBeneath);
172 auto surfAbove = Acts::Surface::makeShared<Acts::PlaneSurface>(trfAbove);
173 const double covVal = std::pow(10.*Gaudi::Units::cm, 2);
174 startMeas.insert(startMeas.begin(), auxMeasHandle.newMeasurement<1>(surfBeneath, ProjectorType::e1DimNoTime, AmgSymMatrix(1){covVal}));
175 startMeas.insert(startMeas.end(), auxMeasHandle.newMeasurement<1>(surfAbove, ProjectorType::e1DimNoTime, AmgSymMatrix(1){covVal}));
176
177 }
178
179 if (m_drawEvent) {
181 MuonValR4::drawSegmentLine(gctx, *reFitMe, visualHelper,
182 Acts::ViewConfig{.color = {220, 0, 0}});
183 MuonValR4::drawSegmentMeasurements(gctx, *reFitMe, visualHelper, Acts::s_viewSurface);
184 }
186 const Amg::Vector3D trfZ = sectorTrf.linear().col(2);
187 const double extDist = Amg::intersect<3>(seedPos, seedDir, trfZ,
188 firstSurfPos.dot(trfZ) - 10.*Gaudi::Units::cm).value_or(0.);
190 const Amg::Vector3D refPos = seedPos + extDist * seedDir;
191 const Amg::Transform3D trf{GeoTrf::GeoTransformRT{sectorAngles, refPos}};
192 if (msgLvl(MSG::VERBOSE)) {
193 const auto [locPos, locDir] = makeLine(localSegmentPars(*reFitMe));
194
195 std::stringstream sstr{};
196 sstr<<"pos: "<<Amg::toString(seedPos)<<", dir: "<<Amg::toString(seedDir)<<", chi2/nDoF: "
197 <<reFitMe->chiSquared() / reFitMe->numberDoF()<<", nDoF: "<<reFitMe->numberDoF()<<", "
198 <<reFitMe->nPrecisionHits()<<", "<<reFitMe->nPhiLayers()<<std::endl;
199 for (const auto& meas : MuonR4::detailedSegment(*reFitMe)->measurements()) {
200 sstr<<" **** "<<(*meas)<<", chi2: "<<SeedingAux::chi2Term(locPos, locDir, *meas)
201 <<", sign: "<<(meas->isStraw() ?
202 (SeedingAux::strawSign(locPos,locDir, *meas) == 1 ? "R" : "L") : "-")
203 <<", geoId: "<<(meas->spacePoint() ? surfAcc.get(meas->spacePoint()->primaryMeasurement())->geometryId()
204 : Acts::GeometryIdentifier{})<<std::endl;
205 }
206
207 sstr<<" Target surf: "<<Amg::toString(trf)<<", firstSurf: "<< Amg::toString(trf.inverse()*firstSurfPos)
208 <<", refPoint: "<<Amg::toString(trf.inverse()*refPos)<<std::endl;
209 ATH_MSG_VERBOSE("Run G2F fit on "<<msSector->identString()<<std::endl<<sstr.str());
210 }
212 auto target = Acts::Surface::makeShared<Acts::PlaneSurface>(trf);
213
214 auto fourPos{ActsTrk::convertPosToActs(refPos, refPos.mag() / Gaudi::Units::c_light)};
215 Acts::BoundMatrix initialCov{Acts::BoundMatrix::Identity()};
216
217 auto initialPars = Acts::BoundTrackParameters::create(tgContext, target, fourPos, seedDir, straightQoverP,
218 initialCov, Acts::ParticleHypothesis::muon());
219 if (!initialPars.ok()) {
220 ATH_MSG_WARNING("Initial estimate of the parameters failed");
221 continue;
222 }
223 if (m_drawEvent) {
224 MuonValR4::drawBoundParameters(gctx, *initialPars, visualHelper,
225 Acts::ViewConfig{.color={0,220,0}});
226 }
227 ATH_MSG_DEBUG("Initial parameters "<<Amg::toString((*initialPars).parameters()));
228 auto fitTraject = m_trackFitTool->fit(startMeas, *initialPars,
229 tgContext, mfContext, calContext, target.get());
230 if (!fitTraject) {
231 ATH_MSG_WARNING("Track fit failed.");
232 if (m_drawEvent) {
233 visualHelper.write(std::format("SegmentReFitTest_failed_{:}_{:}_{:}.obj",
234 ctx.eventID().event_number(), reFitMe->index(),
235 MuonR4::printID(*reFitMe)));
236 }
237 continue;
238 }
239
240 auto track = fitTraject->getTrack(0);
241 ATH_MSG_DEBUG("Track fit succeeded. ");
242
245 std::vector<const xAOD::UncalibratedMeasurement*> goodMeas{};
246 unsigned int itr{0};
247 fitTraject->trackStateContainer().visitBackwards(track.tipIndex(),[&](const auto& state){
248 if (!state.hasUncalibratedSourceLink()){
249 return;
250 }
251 goodMeas.insert(goodMeas.begin(),
252 ActsTrk::detail::xAODUncalibMeasCalibrator::unpack(state.getUncalibratedSourceLink()));
253
254 ATH_MSG_VERBOSE("Loop over track state: "<<(itr++)<<", "<<m_idHelperSvc->toString(xAOD::identify(goodMeas.front()))
255 <<", id: "<<surfAcc.get(goodMeas.front())->geometryId());
256
257 const xAOD::UncalibratedMeasurement* m = goodMeas.front();
258 const bool isPrecHit = (m->type() == xAOD::UncalibMeasType::MdtDriftCircleType ||
261 !m_idHelperSvc->measuresPhi(xAOD::identify(m))));
262
263 summary.nPrecHits += isPrecHit;
264 if (m->type() == xAOD::UncalibMeasType::Other ||
265 m_idHelperSvc->measuresPhi(xAOD::identify(m))){
266 ++summary.nPhiHits;
267 } else {
268 summary.nEtaTrigHits += !isPrecHit;
269 }
270 });
271
272 Acts::BoundTrackParameters parameters = track.createParametersAtReference();
273 if (m_drawEvent) {
274 MuonValR4::drawBoundParameters(gctx, parameters, visualHelper,
275 Acts::ViewConfig{.color={0, 0, 220}});
276
277 visualHelper.write(std::format("SegmentReFitTest_goodone_{:}_{:}_{:}.obj",
278 ctx.eventID().event_number(), reFitMe->index(),
279 MuonR4::printID(*reFitMe)));
280 }
282 const Amg::Vector3D globDir = parameters.direction();
284 const Amg::Transform3D globToLoc{sectorTrf.inverse()};
285 const Amg::Vector3D refitPos = globToLoc * parameters.position(tgContext);
286 const Amg::Vector3D refitDir = globToLoc.linear() * globDir;
288 const Amg::Vector3D refitSeg = refitPos + Amg::intersect<3>(refitPos, refitDir, Amg::Vector3D::UnitZ(), 0).value_or(0.) * refitDir;
289 const Amg::Vector3D globPos{msSector->localToGlobalTrans(gctx) * refitSeg};
290
291 auto newSegment = outHandle->push_back(std::make_unique<xAOD::MuonSegment>());
292 dec_segLink(*newSegment) = Link_t{*segments, reFitMe->index(), ctx};
293
294 newSegment->setDirection(globDir.x(), globDir.y(), globDir.z());
295 newSegment->setPosition(globPos.x(), globPos.y(), globPos.z());
296
297 newSegment->setFitQuality(track.chi2(), track.nDoF());
298 newSegment->setNHits(summary.nPrecHits, summary.nPhiHits, summary.nEtaTrigHits);
299 auto& locFitPars = dec_locPars(*newSegment);
300 locFitPars[Acts::toUnderlying(ParamDefs::x0)] = refitSeg.x();
301 locFitPars[Acts::toUnderlying(ParamDefs::y0)] = refitSeg.y();
302 locFitPars[Acts::toUnderlying(ParamDefs::theta)] = refitDir.theta();
303 locFitPars[Acts::toUnderlying(ParamDefs::phi)] = refitDir.phi();
304 }
305 return StatusCode::SUCCESS;
306 }
307}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_ALWAYS(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define AmgSymMatrix(dim)
if(febId1==febId2)
Handle class for adding a decoration to an object.
A wrapper class for event-slot-local random engines.
Definition RNGWrapper.h:56
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
Definition RNGWrapper.h:169
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition RNGWrapper.h:134
Acts::GeometryContext context() const
ProjectorType
Enum encoding the possible projectors used in ATLAS.
static const xAOD::UncalibratedMeasurement * unpack(const Acts::SourceLink &sl)
Helper method to unpack an Acts source link to an uncalibrated measurement.
Helper class to access the Acts::surface associated with an Uncalibrated xAOD measurement.
const Acts::Surface * get(const xAOD::UncalibratedMeasurement *meas) const
Operator.
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
const Amg::Transform3D & localToGlobalTrans(const ActsTrk::GeometryContext &gctx) const
Returns the local -> global tarnsformation from the sector.
SG::WriteHandleKey< xAOD::TrackSurfaceContainer > m_surfKey
Key to setup a surface container for the external constraints.
ServiceHandle< IAthRNGSvc > m_rndmSvc
Range service to smear the segment parameters.
ToolHandle< ActsTrk::IFitterTool > m_trackFitTool
Track fitting tool.
virtual StatusCode execute(const EventContext &ctx) const override final
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_localParsKey
Decorate directly the local segment parameters on to the object.
const MuonGMR4::MuonDetectorManager * m_detMgr
Detector manager to access the spectrometer sector surfaces.
Gaudi::Property< double > m_smearRange
Smear interval in terms of standard deviations.
ToolHandle< ISpacePointCalibrator > m_calibTool
Handle to the space point calibrator.
std::tuple< Amg::Vector3D, Amg::Vector3D > smearSegment(const ActsTrk::GeometryContext &gctx, const MuonR4::Segment &segment, CLHEP::HepRandomEngine *engine) const
Smear the segment's position and direction by one sigma defined by the segment's covariance.
SG::WriteHandleKey< xAOD::MuonSegmentContainer > m_writeKey
Declare the key for the refitted segment container.
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_seedParsKey
Decorate the seed parameters entering the fit.
ToolHandle< MuonR4::ISegmentSelectionTool > m_segSelector
Segment selection tool to pick the good quality segments.
Gaudi::Property< bool > m_drawEvent
Dump the segment line in obj files.
SG::WriteDecorHandleKey< xAOD::MuonSegmentContainer > m_linkKey
Construct a link from the refitted segment to the input segment.
ToolHandle< ActsTrk::IExtrapolationTool > m_extrapolationTool
Track extrapolation tool.
SG::ReadHandleKey< xAOD::MuonSegmentContainer > m_readKey
Declare the data dependency on the standard Mdt+Rpc+Tgc segment container.
ActsTrk::AuxiliaryMeasurementHandler m_auxMeasProv
virtual StatusCode initialize() override final
PublicToolHandle< ActsTrk::ITrackingGeometryTool > m_trackingGeometryTool
Tracking geometry tool.
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
IdHelperSvc to decode the Identifiers.
Placeholder for what will later be the muon segment EDM representation.
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.
Handle class for adding a decoration to an object.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Acts::CalibrationContext getCalibrationContext(const EventContext &ctx)
The Acts::Calibration context is piped through the Acts fitters to (re)calibrate the Acts::SourceLink...
Acts::Vector4 convertPosToActs(const Amg::Vector3D &athenaPos, const double athenaTime=0.)
Converts a position vector & time from Athena units into Acts units.
std::optional< double > intersect(const AmgVector(N)&posA, const AmgVector(N)&dirA, const AmgVector(N)&posB, const AmgVector(N)&dirB)
Calculates the point B' along the line B that's closest to a second line A.
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
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.
Parameters localSegmentPars(const xAOD::MuonSegment &seg)
Returns the localSegPars decoration from a xAODMuon::Segment.
std::pair< Amg::Vector3D, Amg::Vector3D > makeLine(const Parameters &pars)
Returns the parsed parameters into an Eigen line parametrization.
std::string toString(const Parameters &pars)
Dumps the parameters into a string with labels in front of each number.
This header ties the generic definitions in this package.
std::string printID(const xAOD::MuonSegment &seg)
Print the chamber ID of a segment, e.g.
std::vector< const xAOD::UncalibratedMeasurement * > collectMeasurements(const xAOD::MuonSegment &segment, bool skipOutlier=true)
Helper function to extract the measurements from the segment.
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::Segment.
void drawBoundParameters(const ActsTrk::GeometryContext &gctx, const Acts::BoundTrackParameters &pars, Acts::ObjVisualization3D &visualHelper, const Acts::ViewConfig &viewConfig=Acts::s_viewLine, const double standardLength=3.*Gaudi::Units::cm)
Draw a line representing the bound track parameters.
bool isPrecHit(const SpType &sp)
Define a spacepoint as precision hit if it's a Mdt or NSW eta hit.
void drawSegmentMeasurements(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, Acts::ObjVisualization3D &visualHelper, const Acts::ViewConfig &viewConfig=Acts::s_viewSensitive)
Draw all uncalibrated measurements associated to the segment.
void drawSegmentLine(const ActsTrk::GeometryContext &gctx, const xAOD::MuonSegment &segment, Acts::ObjVisualization3D &visualHelper, const Acts::ViewConfig &viewConfig=Acts::s_viewLine, const double standardLength=1.*Gaudi::Units::m)
Draw a segment line inside the obj file.
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MuonSegmentContainer_v1 MuonSegmentContainer
Definition of the current "MuonSegment container version".
Eigen::Matrix< float, N, 1 > MeasVector
Abrivation of the Matrix & Covariance definitions.
const Identifier & identify(const UncalibratedMeasurement *meas)
Returns the associated identifier from the muon measurement.
MuonSegment_v1 MuonSegment
Reference the current persistent version:
UncalibratedMeasurement_v1 UncalibratedMeasurement
Define the version of the uncalibrated measurement class.