ATLAS Offline Software
Loading...
Searching...
No Matches
SpacePointCalibrator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
5
9
18
21
23
26
27
28#include "Acts/Utilities/MathHelpers.hpp"
29#include "Acts/Utilities/Enumerate.hpp"
30
31
32namespace {
33 constexpr double c_inv = 1./ Gaudi::Units::c_light;
34 static const SG::Decorator<int> dec_trackSign{"segmentFitDriftSign"};
35}
36
37namespace MuonR4{
38 using namespace Acts::UnitLiterals;
42 using namespace SegmentFit;
43
45 ATH_CHECK(m_geoCtxKey.initialize());
46 ATH_CHECK(m_idHelperSvc.retrieve());
47 ATH_CHECK(m_mdtCalibrationTool.retrieve(EnableTool{m_idHelperSvc->hasMDT()}));
48 ATH_CHECK(m_nswCalibTool.retrieve(EnableTool{m_idHelperSvc->hasMM() || m_idHelperSvc->hasSTGC()}));
49 ATH_CHECK(detStore()->retrieve(m_detMgr));
50 return StatusCode::SUCCESS;
51 }
52
54 const Amg::Vector3D& trackDir,
55 CalibSpacePointVec& hitsToCalib) const {
56 std::vector<int> signs = SeedingAux::strawSigns(trackPos, trackDir,
57 hitsToCalib);
58 for (const auto [spIdx, sp]: Acts::enumerate(hitsToCalib)) {
59 sp->setDriftRadius(sp->driftRadius() * signs[spIdx]);
60 }
61 }
63 const CalibratedSpacePoint& spacePoint,
64 const Amg::Vector3D& segPos,
65 const Amg::Vector3D& segDir,
66 const double timeDelay) const {
67 CalibSpacePointPtr calibSP{};
68 if (spacePoint.type() != xAOD::UncalibMeasType::Other){
69 calibSP = calibrate(ctx, spacePoint.spacePoint(), segPos, segDir, timeDelay);
70 } else {
71 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint);
72 }
73 if (spacePoint.fitState() == State::Outlier) {
74 calibSP->setFitState(State::Outlier);
75 } else if (spacePoint.fitState() == State::Duplicate) {
76 calibSP->setFitState(State::Duplicate);
77 }
78 return calibSP;
79 }
80
81 CalibSpacePointVec SpacePointCalibrator::calibrate(const Acts::CalibrationContext& cctx,
82 const Amg::Vector3D& segPos,
83 const Amg::Vector3D& segDir,
84 const double timeDelay,
85 const CalibSpacePointVec& spacePoints) const {
86 CalibSpacePointVec newCalib{};
87 const EventContext* ctx = cctx.get<const EventContext*>();
88 newCalib.reserve(spacePoints.size());
89 for (const CalibSpacePointPtr& sp : spacePoints){
90 newCalib.emplace_back(calibrate(*ctx, *sp, segPos, segDir, timeDelay));
91 }
92 return newCalib;
93 }
94
96 const SpacePoint* spacePoint,
97 const Amg::Vector3D& posInChamb,
98 const Amg::Vector3D& dirInChamb,
99 const double timeOffset) const {
100
101 const ActsTrk::GeometryContext* gctx{nullptr};
102 if (!SG::get(gctx, m_geoCtxKey, ctx).isSuccess()) {
103 return nullptr;
104 }
105 const Amg::Vector3D& spPos{spacePoint->localPosition()};
106 const Amg::Transform3D& locToGlob{spacePoint->msSector()->localToGlobalTransform(*gctx)};
107 const Amg::Vector3D& chDir{spacePoint->sensorDirection()};
108
109 // Adjust the space point position according to the external seed. But only if the space point
110 // is a 1D strip
111 Amg::Vector3D calibSpPos = spacePoint->dimension() == 2 ? spPos
112 : spPos + Amg::intersect<3>(posInChamb, dirInChamb, spPos, chDir).value_or(0) * chDir;
113
114 SpacePoint::Cov_t cov = spacePoint->covariance();
115 CalibSpacePointPtr calibSP{};
116 ATH_MSG_VERBOSE("Calibrate "<<(*spacePoint) <<" -> updated pos "<<Amg::toString(calibSpPos));
117 switch (spacePoint->type()) {
119 const Amg::Vector3D locClosestApproach = posInChamb
120 + Amg::intersect<3>(spPos, chDir,
121 posInChamb, dirInChamb).value_or(0) * dirInChamb;
122
123 Amg::Vector3D closestApproach{locToGlob* locClosestApproach};
124 const double timeOfArrival = closestApproach.mag() * c_inv + timeOffset;
125
126 if (ATH_LIKELY(spacePoint->dimension() == 1)) {
127 auto* dc = static_cast<const xAOD::MdtDriftCircle*>(spacePoint->primaryMeasurement());
128 MdtCalibInput calibInput{*dc, *gctx};
129 calibInput.setTrackDirection(locToGlob.linear() * dirInChamb,
130 Acts::abs(dirInChamb.phi() - 90._degree) > 1.e-7 );
131 calibInput.setTimeOfFlight(timeOfArrival);
132 calibInput.setClosestApproach(std::move(closestApproach));
133 ATH_MSG_VERBOSE("Parse hit calibration "<<m_idHelperSvc->toString(dc->identify())<<", "<<calibInput);
134 MdtCalibOutput calibOutput = m_mdtCalibrationTool->calibrate(ctx, calibInput);
135 ATH_MSG_VERBOSE("Returned calibration object "<<calibOutput);
136 State fitState{State::Valid};
138 if (calibOutput.status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
139 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
140 <<std::endl<<calibInput<<std::endl<<calibOutput);
141 fitState = State::FailedCalib;
142 cov[Acts::toUnderlying(AxisDefs::etaCov)] = dc->readoutElement()->innerTubeRadius();
143 } else {
144 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(calibOutput.driftRadiusUncert());
145 }
146 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos), fitState);
147 calibSP->setCovariance(cov);
148 calibSP->setDriftRadius(calibOutput.driftRadius());
149 } else {
150 auto* dc = static_cast<const xAOD::MdtTwinDriftCircle*>(spacePoint->primaryMeasurement());
151 MdtCalibInput calibInput{*dc, *gctx};
152 calibInput.setClosestApproach(closestApproach);
153 calibInput.setTimeOfFlight(timeOfArrival);
154
155 MdtCalibInput twinInput{dc->twinIdentify(), dc->twinAdc(), dc->twinTdc(), dc->readoutElement(), *gctx};
156 twinInput.setClosestApproach(closestApproach);
157 twinInput.setTimeOfFlight(timeOfArrival);
158
159 MdtCalibTwinOutput calibOutput = m_mdtCalibrationTool->calibrateTwinTubes(ctx,
160 std::move(calibInput),
161 std::move(twinInput));
162
163 State fitState{State::Valid};
164 if (calibOutput.primaryStatus() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
165 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
166 <<std::endl<<calibOutput);
167 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(dc->readoutElement()->innerTubeRadius());
168 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(0.5* dc->readoutElement()->activeTubeLength(dc->measurementHash()));
169 fitState = State::FailedCalib;
170 } else {
171 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(calibOutput.uncertPrimaryR());
172 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(calibOutput.sigmaZ());
173 }
174 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos), fitState);
175 calibSP->setCovariance(cov);
176 calibSP->setDriftRadius(calibOutput.primaryDriftR());
177 }
178 break;
179 }
181 auto* strip = static_cast<const xAOD::RpcMeasurement*>(spacePoint->primaryMeasurement());
182
184 const Amg::Transform3D toGasGap{strip->readoutElement()->globalToLocalTransform(*gctx, strip->layerHash()) * locToGlob};
185 const Amg::Vector3D lPos = toGasGap * calibSpPos;
187 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
188
189 cov[Acts::toUnderlying(AxisDefs::timeCov)] = Acts::square(m_rpcTimeResolution);
190
191 const double time1 = strip->time()
192 - strip->readoutElement()->distanceToEdge(strip->layerHash(), lPos,
193 EdgeSide::readOut) /m_rpcSignalVelocity;
194
195 if (spacePoint->dimension() == 2) {
196 auto* strip2 = static_cast<const xAOD::RpcMeasurement*>(spacePoint->secondaryMeasurement());
197
198 const double time2 = strip2->time() -
199 strip2->readoutElement()->distanceToEdge(strip2->layerHash(),lPos, EdgeSide::readOut)/m_rpcSignalVelocity;
201 calibSP->setTimeMeasurement(0.5*(time1 + time2));
203 cov[Acts::toUnderlying(AxisDefs::timeCov)] += Acts::square(0.5*(time1 - time2));
204 }
205 calibSP->setCovariance(cov);
206 ATH_MSG_VERBOSE("Create rpc space point "<<m_idHelperSvc->toString(strip->identify())<<", dimension "<<spacePoint->dimension()
207 << ", at "<<Amg::toString(calibSP->localPosition())<<", uncalib time: "
208 <<strip->time()<<", calib time: "<<calibSP->time()<<" cov " <<calibSP->covariance());
209 break;
210 }
212 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
213 calibSP->setCovariance(cov);
214 break;
215 }
217 const xAOD::MMCluster* cluster = static_cast<const xAOD::MMCluster*>(spacePoint->primaryMeasurement());
218 Amg::Vector3D globalPos{locToGlob * posInChamb};
219 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
220
221 std::pair<double, double> calibPosCov {calibrateMM(ctx, *gctx, *cluster, globalPos, globalDir)};
222
223 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPosCov.first << " " << calibPosCov.second);
224 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibPosCov.second;
225 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTransform(*gctx, cluster->layerHash())};
226
227 // since we want to take the second coordiante from the external estimate we need to transform the sp posiiton to the layer frame, replace the precission coordinate and transform back
228 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
229 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
230 calibSpPosInLayer.x() = calibPosCov.first;
231 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
232 calibSpPos = toChamberTrans * calibSpPosInLayer;
233
234 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
235 calibSP->setCovariance(cov);
236 ATH_MSG_DEBUG("calibrated MM cluster "<<m_idHelperSvc->toString(cluster->identify()) << " loc x old " << cluster->localPosition<1>()[0] << " new loc x " << calibSP->localPosition()[1] << "cov " << calibSP->covariance());
237
238 break;
239 }
241 const auto* cluster = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->primaryMeasurement());
242
243 // We do not apply any correction for pads or wire only space points
244 if (cluster->channelType() != sTgcIdHelper::sTgcChannelTypes::Strip) {
245 ATH_MSG_DEBUG("Calibrating an sTGC Pad or wire " << m_idHelperSvc->toString(cluster->identify()));
246 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
247 calibSP->setCovariance(cov);
248 break;
249 }
250
251 std::optional<double> posAlongTheStrip{std::nullopt};
252
253 // check if the space point is a strip/wire combination and take the position along the strip from the wire measurement
254 if(spacePoint->secondaryMeasurement()) {
255 const auto* secMeas = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->secondaryMeasurement());
256 ATH_MSG_VERBOSE("Using secondary measurement "<< m_idHelperSvc->toString(secMeas->identify())<<" for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
257 // Extract scalar value - use 2D for pads (2 dimensions), 1D for wires (1 dimension)
258 if (secMeas->numDimensions() == 2) {
259 posAlongTheStrip = static_cast<double>(secMeas->localPosition<2>()[0]);
260 } else {
261 posAlongTheStrip = static_cast<double>(secMeas->localPosition<1>()[0]);
262 }
263 } else {
264 ATH_MSG_VERBOSE("No secondary measurement for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
265 }
266
267 Amg::Vector3D globalPos{locToGlob * posInChamb};
268 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
269
270 const auto* stripClus = static_cast<const xAOD::sTgcStripCluster*>(cluster);
271 const auto [calibPos, calibCov] = calibratesTGC(ctx, *gctx, *stripClus, posAlongTheStrip, globalPos, globalDir);
272
273 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPos << " " << calibCov);
274 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibCov;
275 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTransform(*gctx, cluster->layerHash())};
276
277 // since we want to take the second coordiante from the external estimate we need to transform the sp posiiton to the layer frame, replace the precission coordinate and transform back
278 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
279 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
280 calibSpPosInLayer.x() = calibPos;
281 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
282 calibSpPos = toChamberTrans * calibSpPosInLayer;
283
284 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
285 calibSP->setCovariance(cov);
286 ATH_MSG_DEBUG("calibrated sTGC cluster "<<m_idHelperSvc->toString(cluster->identify()) << " loc x old " << cluster->localPosition<1>()[0] << " new loc x " << calibSP->localPosition()[1] << "cov " << calibSP->covariance());
287 break;
288 }
289
290 default:
291 ATH_MSG_WARNING("Do not know how to calibrate "<<m_idHelperSvc->toString(spacePoint->identify()));
292 }
293 return calibSP;
294 }
295
297 const std::vector<const SpacePoint*>& spacePoints,
298 const Amg::Vector3D& posInChamb,
299 const Amg::Vector3D& dirInChamb,
300 const double timeOffset) const {
301 CalibSpacePointVec calibSpacePoints{};
302 calibSpacePoints.reserve(spacePoints.size());
303 for(const SpacePoint* spacePoint : spacePoints) {
304 CalibSpacePointPtr hit = calibrate(ctx, spacePoint, posInChamb, dirInChamb, timeOffset);
305 if (hit) {
306 calibSpacePoints.push_back(std::move(hit));
307 }
308 }
309 return calibSpacePoints;
310 }
311 double SpacePointCalibrator::driftVelocity(const Acts::CalibrationContext& ctx,
312 const CalibratedSpacePoint& spacePoint) const {
314
315 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
316 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
317 return calibConsts->rtRelation->rt()->driftVelocity(driftTime.value_or(0.));
318 }
319 return 0.;
320 }
321 double SpacePointCalibrator::driftAcceleration(const Acts::CalibrationContext& ctx,
322 const CalibratedSpacePoint& spacePoint) const {
324 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
325 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
326 return calibConsts->rtRelation->rt()->driftAcceleration(driftTime.value_or(0.));
327 }
328 return 0.;
329 }
330
331 std::pair<double, double> SpacePointCalibrator::calibrateMM(const EventContext& ctx,
332 const ActsTrk::GeometryContext& gctx,
333 const xAOD::MMCluster& cluster,
334 const Amg::Vector3D& globalPos,
335 const Amg::Vector3D& globalDir) const {
336 std::vector<NSWCalib::CalibratedStrip> calibClus;
337 StatusCode sc = m_nswCalibTool->calibrateClus(ctx, gctx, cluster, globalPos, calibClus);
338 if(sc.isFailure()) {
339 ATH_MSG_WARNING("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
340 return std::make_pair(0., 0.);
341 }
342
343 Amg::Vector2D locPos{cluster.localPosition<1>()[0] * Amg::Vector2D::UnitX()};
344 Amg::Vector3D locDir = Muon::NswClustering::toLocal(cluster.readoutElement()->globalToLocalTransform(gctx, cluster.layerHash()), globalDir);
345
346 Amg::MatrixX calibCov{};
347 calibCov.resize(1,1);
348 calibCov(0,0) = cluster.localCovariance<1>()(0, 0);
349 ATH_MSG_DEBUG("old loc pos " << locPos[0] << " old cov" << calibCov(0,0) );
350
351 Muon::IMMClusterBuilderTool::RIO_Author rotAuthor = m_clusterBuilderToolMM->getCalibratedClusterPosition(ctx, calibClus, locDir ,locPos, calibCov);
352 if(rotAuthor == Muon::IMMClusterBuilderTool::RIO_Author::unKnownAuthor){
353 THROW_EXCEPTION("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
354 }
355 ATH_MSG_DEBUG("new loc pos " << locPos[0] << " new cov" << calibCov(0,0) );
356 return std::make_pair(locPos[0], calibCov(0,0));
357 }
358
359 std::pair<double, double> SpacePointCalibrator::calibratesTGC(const EventContext& /*ctx*/,
360 const ActsTrk::GeometryContext& gctx,
361 const xAOD::sTgcStripCluster& cluster,
362 std::optional<double> posAlongTheStrip,
363 const Amg::Vector3D& globalPos,
364 const Amg::Vector3D& /*globalDir*/) const{
365
366 // if the second coordiante was not provided by the wire, take it from the seed track position
367 if(!posAlongTheStrip) {
368 Amg::Vector3D extPosLocal = cluster.readoutElement()->globalToLocalTransform(gctx, cluster.layerHash()) * globalPos;
369 posAlongTheStrip = extPosLocal[1];
370 }
371
372 // For now just copying over the local position and covariance. Eventually this should apply corrections from B-Lines and as build geometry
373
374 return std::make_pair(cluster.localPosition<1>()[0], cluster.localCovariance<1>()(0,0));
375 }
376 void SpacePointCalibrator::calibrateCombinedPrd(const EventContext& ctx,
377 const ActsTrk::GeometryContext& gctx,
378 const xAOD::CombinedMuonStrip* combinedPrd,
379 ActsTrk::MutableTrackContainer::TrackStateProxy state) const {
380 const auto sl = ActsTrk::detail::xAODUncalibMeasCalibrator::pack(combinedPrd);
381 if (combinedPrd->type() == xAOD::UncalibMeasType::RpcStripType) {
382 if (m_useRpcTime) {
383 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
384 }
385 Amg::Vector2D cmbPos{combinedPrd->primaryStrip()->localPosition<1>()[0],
386 combinedPrd->secondaryStrip()->localPosition<1>()[0]};
387 AmgSymMatrix(2) cmbCov{AmgSymMatrix(2)::Identity()};
388 cmbCov (0, 0) = combinedPrd->primaryStrip()->localCovariance<1>()(0,0);
389 cmbCov (1, 1) = combinedPrd->secondaryStrip()->localCovariance<1>()(0,0);
391
392
393 } else if (combinedPrd->type() == xAOD::UncalibMeasType::TgcStripType) {
394 if (m_useTgcTime) {
395 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
396 }
397 const auto* wireMeas = static_cast<const xAOD::TgcStrip*>(combinedPrd->primaryStrip());
398 const auto* stripMeas = static_cast<const xAOD::TgcStrip*>(combinedPrd->secondaryStrip());
399
400 const auto& radialDesign = stripMeas->readoutElement()->stripLayout(stripMeas->layerHash());
401 const auto& wireDesign = wireMeas->readoutElement()->wireGangLayout(wireMeas->layerHash());
402
403 const double dirDots = radialDesign.stripDir(stripMeas->channelNumber()).dot(wireDesign.stripNormal());
405 AmgSymMatrix(2) stereoTrf{AmgSymMatrix(2)::Identity()};
406 const double invDist = 1. / (1. - Acts::square(dirDots));
407 stereoTrf(0, 0) = stereoTrf(1, 1) = invDist;
408 stereoTrf(0, 1) = stereoTrf(1, 0) = -dirDots * invDist;
409
410 Amg::Vector2D cmbPos{wireMeas->localPosition<1>()[0],
411 stripMeas->localPosition<1>()[0]};
412 AmgSymMatrix(2) cmbCov{AmgSymMatrix(2)::Identity()};
413 cmbCov (0, 0) = wireMeas->localCovariance<1>()(0,0);
414 cmbCov (1, 1) = stripMeas->localCovariance<1>()(0,0);
415
417 stereoTrf*cmbCov*stereoTrf.transpose(), sl, state);
418
419 } else if(combinedPrd->type() == xAOD::UncalibMeasType::sTgcStripType) {
420 if (m_usesTgcTime) {
421 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
422 }
423 Amg::Vector2D cmbPos {Amg::Vector2D::Zero()};
424 AmgSymMatrix(2) cmbCov{AmgSymMatrix(2)::Identity()};
425
426 // combined sTGC Space points can be strip/wire, strip/pad or pad/wire combinations.
427 const auto* primMeas = static_cast<const xAOD::sTgcMeasurement*>(combinedPrd->primaryStrip());
428 const auto* secMeas = static_cast<const xAOD::sTgcMeasurement*>(combinedPrd->secondaryStrip());
429 if(primMeas->channelType() == sTgcIdHelper::sTgcChannelTypes::Strip) {
430 const auto* primStripMeas = static_cast<const xAOD::sTgcStripCluster*>(primMeas);
432 const Acts::BoundTrackParameters trackPars{state.referenceSurface().getSharedPtr(),
433 state.parameters(), state.covariance(),
434 Acts::ParticleHypothesis::muon()};
435 std::pair<double, double> calibPosCov{calibratesTGC(ctx, gctx, *primStripMeas, cmbPos[1] , trackPars.position(gctx.context()), trackPars.direction())};
436 cmbPos[0] = calibPosCov.first;
437 cmbCov(0,0) = calibPosCov.second;
438
439 if(secMeas->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire){
440 cmbPos[1] = secMeas->localPosition<1>()[0];
441 cmbCov(1,1) = secMeas->localCovariance<1>()(0,0);
442 } else if (secMeas->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad){
443 cmbPos[1] = secMeas->localPosition<2>()[1];
444 cmbCov(1,1) = secMeas->localCovariance<2>()(1,1);
445 } else {
446 THROW_EXCEPTION("Unexpected secondary measurement type for combined sTGC space point "
447 <<m_idHelperSvc->toString(xAOD::identify(combinedPrd))
448 << "secondary measurement " << m_idHelperSvc->toString(xAOD::identify(secMeas)));
449 }
450 } else if (primMeas->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad) {
451 cmbPos[0] = primMeas->localPosition<2>()[0];
452 cmbCov(0,0) = primMeas->localCovariance<2>()(0,0);
453
454 if (secMeas->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire){
455 cmbPos[1] = secMeas->localPosition<1>()[0];
456 cmbCov(1,1) = secMeas->localCovariance<1>()(0,0);
457 } else {
458 THROW_EXCEPTION("Unexpected secondary measurement type for combined sTGC space point "
459 << m_idHelperSvc->toString(xAOD::identify(combinedPrd))
460 << "secondary measurement " << m_idHelperSvc->toString(xAOD::identify(secMeas)));
461 }
462 } else {
463 THROW_EXCEPTION("Unexpected primary measurement type for combined sTGC space point "
464 <<m_idHelperSvc->toString(xAOD::identify(combinedPrd)));
465 }
466
468
469 } else {
470 THROW_EXCEPTION("Undefined uncalibrated measurement "
471 <<m_idHelperSvc->toString(xAOD::identify(combinedPrd)));
472 }
473 }
474 void SpacePointCalibrator::calibrateSourceLink(const Acts::GeometryContext& geoctx,
475 const Acts::CalibrationContext& cctx,
476 const Acts::SourceLink& link,
477 ActsTrk::MutableTrackContainer::TrackStateProxy trackState) const {
478
480 const Acts::BoundTrackParameters trackPars{trackState.referenceSurface().getSharedPtr(),
481 trackState.parameters(), trackState.covariance(),
482 Acts::ParticleHypothesis::muon()};
483
484
485 const auto* muonMeas = ActsTrk::detail::xAODUncalibMeasCalibrator::unpack(link);
486 const ActsTrk::GeometryContext* gctx = geoctx.get<const ActsTrk::GeometryContext*>();
487 const EventContext* ctx = cctx.get<const EventContext*>();
488 ATH_MSG_VERBOSE("Calibrate measurement "<<m_idHelperSvc->toString(xAOD::identify(muonMeas))
489 <<" @ surface "<<trackState.referenceSurface().geometryId());
491 if (muonMeas->numDimensions() == 0u) {
492 calibrateCombinedPrd(*ctx, *gctx, static_cast<const xAOD::CombinedMuonStrip*>(muonMeas),
493 trackState);
494 return;
495
496 }
497 const Amg::Vector3D trackPos{trackPars.position(geoctx)};
498 const Amg::Vector3D trackDir{trackPars.direction()};
499
500 switch (muonMeas->type()){
501 using enum xAOD::UncalibMeasType;
502 case MdtDriftCircleType: {
503 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(muonMeas);
504 MdtCalibInput calibInput{*dc, *gctx};
505 calibInput.setClosestApproach(trackPos);
506 //calibInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
507 calibInput.setTrackDirection(trackDir, true);
508 const double driftSign = m_MdtSignFromSegment ?
509 static_cast<double>(dec_trackSign(*dc)) :
510 Acts::copySign(1.,trackPars.parameters()[Acts::eBoundLoc0]);
511
513 if (ATH_LIKELY(muonMeas->numDimensions() == 1)) {
514 MdtCalibOutput calibOutput = m_mdtCalibrationTool->calibrate(*ctx, calibInput);
515 ATH_MSG_VERBOSE("Returned calibration object "<<calibOutput);
516 AmgVector(1) pos{AmgVector(1)::Zero()};
517 AmgSymMatrix(1) cov{AmgSymMatrix(1)::Identity()};
519 if (calibOutput.status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
520 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
521 <<std::endl<<calibInput<<std::endl<<calibOutput);
522 cov(Acts::eBoundLoc0,Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
523 } else {
524 pos[Acts::eBoundLoc0] = driftSign*calibOutput.driftRadius();
525 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.driftRadiusUncert(), 2);
526 }
528 }
530 else {
531 const auto* twinDC = static_cast<const xAOD::MdtTwinDriftCircle*>(muonMeas);
532 MdtCalibInput twinInput{twinDC->twinIdentify(), twinDC->twinAdc(), twinDC->twinTdc(), twinDC->readoutElement(), *gctx};
533 twinInput.setClosestApproach(trackPos);
534 twinInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
535
536 MdtCalibTwinOutput calibOutput = m_mdtCalibrationTool->calibrateTwinTubes(*ctx,
537 std::move(calibInput),
538 std::move(twinInput));
539 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
540 AmgSymMatrix(2) locCov{AmgSymMatrix(2)::Identity()};
541 if (calibOutput.primaryStatus() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
542 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
543 <<std::endl<<calibOutput);
544 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
545 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(0.5* dc->readoutElement()->activeTubeLength(dc->measurementHash()), 2);
546 } else {
547 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.uncertPrimaryR(), 2);
548 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(calibOutput.sigmaZ(), 2);
549 locPos[Acts::eBoundLoc0] = driftSign*calibOutput.primaryDriftR();
550 locPos[Acts::eBoundLoc1] = calibOutput.locZ();
551 }
553 }
554 break;
555 } case RpcStripType: {
556 const auto* rpcClust = static_cast<const xAOD::RpcMeasurement*>(muonMeas);
558 if (ATH_LIKELY(rpcClust->numDimensions() == 1)) {
559
560 if (!m_useRpcTime) {
561 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotNoTime
564 rpcClust->localPosition<1>(),
565 rpcClust->localCovariance<1>(), link, trackState);
566 } else {
567 AmgVector(2) measPars{AmgVector(2)::Zero()};
568 AmgSymMatrix(2) measCov{AmgSymMatrix(2)::Identity()};
569 measPars[0] = rpcClust->localPosition<1>()[0];
570 measCov(0,0) = rpcClust->localCovariance<1>()(0, 0);
571 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
572 measCov(1,1) = std::pow(m_rpcTimeResolution, 2);
573 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotWithTime
576 measPars, measCov, link, trackState);
577 }
578 }
580 else {
581 if (!m_useRpcTime) {
583 rpcClust->localPosition<2>(),
584 rpcClust->localCovariance<2>(), link, trackState);
585 } else {
586 AmgVector(3) measPars{AmgVector(3)::Zero()};
587 AmgSymMatrix(3) measCov{AmgSymMatrix(3)::Identity()};
588 measPars.block<2,1>(0,0) = xAOD::toEigen(rpcClust->localPosition<2>());
589 measCov.block<2,2>(0,0) = xAOD::toEigen(rpcClust->localCovariance<2>());
590 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
591 measCov(2,2) = std::pow(m_rpcTimeResolution, 2);
593 measPars, measCov, link, trackState);
594 }
595 }
596 break;
597 } case TgcStripType: {
598 const auto* tgcClust = static_cast<const xAOD::TgcStrip*>(muonMeas);
599 if (!m_useTgcTime) {
600 const auto proj = tgcClust->measuresPhi() ? ProjectorType::e1DimRotNoTime
603 tgcClust->localPosition<1>(),
604 tgcClust->localCovariance<1>(), link, trackState);
605 } else {
606 ATH_MSG_WARNING("Tgc time calibration to be implemented...");
607 }
608 break;
609 }
610 case MMClusterType: {
611 const auto* mmClust = static_cast<const xAOD::MMCluster*>(muonMeas);
612 std::pair<double, double> calibPosCov{calibrateMM(*ctx,* gctx, *mmClust, trackPos, trackDir)};
613 AmgVector(1) pos{AmgVector(1)(calibPosCov.first)};
614 AmgSymMatrix(1) cov{AmgSymMatrix(1)(calibPosCov.second)};
615
617 pos, cov, link, trackState);
618 break;
619 } case sTgcStripType: {
620 const auto* stgcClust = static_cast<const xAOD::sTgcMeasurement*>(muonMeas);
621
622 if(stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire) {
624 muonMeas->localPosition<1>(),
625 muonMeas->localCovariance<1>(), link, trackState);
626 } else if (stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad) {
628 stgcClust->localPosition<2>(),
629 stgcClust->localCovariance<2>(), link, trackState);
630 } else { // strips
631 const auto stgCluster = static_cast<const xAOD::sTgcStripCluster*>(muonMeas);
632 std::pair<double, double> calibPosCov{calibratesTGC(*ctx, *gctx, *stgCluster, std::nullopt, trackPos, trackDir)};
633 if(!m_usesTgcTime) {
634 AmgVector(1) pos{calibPosCov.first};
635 AmgSymMatrix(1) cov{calibPosCov.second};
637 pos, cov, link, trackState);
638 } else {
639 ATH_MSG_WARNING("sTGC time calibration to be implemented...");
640 AmgVector(2) pos{AmgVector(2)::Zero()};
641 AmgSymMatrix(2) cov{AmgSymMatrix(2)::Zero()};
642 pos[0] = calibPosCov.first;
643 pos[1] = stgCluster->time();
644 cov(0,0) = calibPosCov.second;
645 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
646 cov(1,1) = std::pow(25 /*ns*/, 2);
647
649 pos, cov, link, trackState);
650 }
651 }
652 break;
653 } default: {
654 THROW_EXCEPTION("The parsed measurement is not a muon measurement. Please check.");
655 }
656 }
657 }
659 const auto [segPos, segLine] = makeLine(localSegmentPars(segment));
660 const Segment* detSeg = MuonR4::detailedSegment(segment);
661 for (const auto& meas : detSeg->measurements()) {
663 dec_trackSign(*meas->spacePoint()->primaryMeasurement()) =
664 SeedingAux::strawSign(segPos, segLine, *meas);
665 }
666 }
667 }
668}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define ATH_LIKELY(x)
#define AmgSymMatrix(dim)
#define AmgVector(rows)
static Double_t sp
static Double_t sc
Acts::GeometryContext context() const
@ e2DimWithTime
Project out the locY & time coordinate - (Applies to Rpc, Tgc, sTgc)
@ e2DimNoTime
Project out solely the locY - Complementary projector if the strip plane is rotated (Applies to Itk e...
@ e1DimWithTime
Project out the two spatial coordinates - (Applies to ITk pixel, BI-Rpc, sTgc pad)
@ e1DimRotNoTime
Project out solely the locX (Applies to Itk strips, Rpc, Tgc, sTgc, Mm)
@ e1DimRotWithTime
Project out the locX & time coordinate - (Applies to Rpc, Tgc, Mm, sTgc)
void setState(const ProjectorType projector, const pos_t &locpos, const cov_t &cov, Acts::SourceLink link, TrackState_t< trajectory_t > &trackState) const
Copy the local position & covariance into the Acts track state proxy.
static const xAOD::UncalibratedMeasurement * unpack(const Acts::SourceLink &sl)
Helper method to unpack an Acts source link to an uncalibrated measurement.
static Acts::SourceLink pack(const xAOD::UncalibratedMeasurement *meas)
Helper method to pack an uncalibrated measurement to an Acts source link.
void setClosestApproach(const Amg::Vector3D &approach)
Sets the closest approach.
void setTimeOfFlight(const double toF)
Sets the time of flight (Usually globPos.mag() * inverseSpeed of light)
void setTrackDirection(const Amg::Vector3D &trackDir, bool hasPhi)
Sets the direction of the externally determined track.
double driftRadiusUncert() const
Returns the uncertainty on the drift radius.
double driftRadius() const
Returns the drift radius of the calibrated object.
MdtDriftCircleStatus status() const
Status of the calibration.
MdtDriftCircleStatus primaryStatus() const
double primaryDriftR() const
double uncertPrimaryR() const
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &ctx) const
Returns the transformation from the local coordinate system of the readout element into the global AT...
Amg::Transform3D globalToLocalTransform(const ActsTrk::GeometryContext &ctx) const
Returns the transformation from the global ATLAS coordinate system into the local coordinate system o...
const Amg::Transform3D & localToGlobalTransform(const ActsTrk::GeometryContext &gctx) const
Returns the local -> global tarnsformation from the sector.
The calibrated Space point is created during the calibration process.
double driftRadius() const
: Returns the size of the drift radius
const SpacePoint * spacePoint() const
The pointer to the space point out of which this space point has been built.
xAOD::UncalibMeasType type() const
Returns the space point type.
State
State flag to distinguish different space point states.
State fitState() const
Returns the state of the calibrated space point.
std::unique_ptr< CalibratedSpacePoint > CalibSpacePointPtr
std::vector< CalibSpacePointPtr > CalibSpacePointVec
Placeholder for what will later be the muon segment EDM representation.
const MeasVec & measurements() const
Returns the associated measurements.
Gaudi::Property< bool > m_useRpcTime
Load the Rpc time on the track states for the track fit.
void calibrateCombinedPrd(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const xAOD::CombinedMuonStrip *combinedPrd, ActsTrk::MutableTrackContainer::TrackStateProxy state) const
Calibrates the track states from a combined muon strip.
ToolHandle< Muon::IMMClusterBuilderTool > m_clusterBuilderToolMM
void calibrateSourceLink(const Acts::GeometryContext &geoctx, const Acts::CalibrationContext &cctx, const Acts::SourceLink &link, ActsTrk::MutableTrackContainer::TrackStateProxy state) const override final
ToolHandle< Muon::INSWCalibTool > m_nswCalibTool
std::pair< double, double > calibratesTGC(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const xAOD::sTgcStripCluster &cluster, std::optional< double > posAlongTheStrip, const Amg::Vector3D &globalPos, const Amg::Vector3D &globalDir) const
Calibrates the position and covariance of an sTGC (small-strip Thin Gap Chamber) cluster.
double driftVelocity(const Acts::CalibrationContext &ctx, const CalibratedSpacePoint &spacePoint) const override final
ToolHandle< IMdtCalibrationTool > m_mdtCalibrationTool
CalibSpacePointPtr calibrate(const EventContext &ctx, const SpacePoint *spacePoint, const Amg::Vector3D &seedPosInChamb, const Amg::Vector3D &seedDirInChamb, const double timeDelay) const override final
Gaudi::Property< double > m_rpcSignalVelocity
How fast does an electron signal travel along an rpc strip.
void updateSigns(const Amg::Vector3D &trackPos, const Amg::Vector3D &trackDir, CalibSpacePointVec &hitsToCalib) const override final
StatusCode initialize() override final
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
const MuonGMR4::MuonDetectorManager * m_detMgr
Gaudi::Property< bool > m_MdtSignFromSegment
Gaudi::Property< bool > m_useTgcTime
Load the Tgc bunch crossing ID on the track states.
SG::ReadHandleKey< ActsTrk::GeometryContext > m_geoCtxKey
access to the ACTS geometry context
Gaudi::Property< bool > m_usesTgcTime
double driftAcceleration(const Acts::CalibrationContext &ctx, const CalibratedSpacePoint &spacePoint) const override final
Gaudi::Property< double > m_rpcTimeResolution
std::pair< double, double > calibrateMM(const EventContext &ctx, const ActsTrk::GeometryContext &gctx, const xAOD::MMCluster &cluster, const Amg::Vector3D &globalPos, const Amg::Vector3D &globalDir) const
Calibrates the position and covariance of a MicroMegas (MM) cluster.
void stampSignsOnMeasurements(const xAOD::MuonSegment &segment) const override final
The muon space point is the combination of two uncalibrated measurements one of them measures the eta...
unsigned dimension() const
Is the space point a 1D or combined 2D measurement.
const xAOD::UncalibratedMeasurement * secondaryMeasurement() const
std::array< double, 3 > Cov_t
Abrivation of the covariance type.
const Identifier & identify() const
: Identifier of the primary measurement
const Cov_t & covariance() const
Returns the covariance array.
const xAOD::UncalibratedMeasurement * primaryMeasurement() const
MMClusterOnTrack::Author RIO_Author
Refinement of the cluster position after the cluster calibration loop is ran with a complete external...
Helper class to provide type-safe access to aux data.
Definition Decorator.h:59
const xAOD::UncalibratedMeasurement * secondaryStrip() const
Returns the secondary associated measurement.
const xAOD::UncalibratedMeasurement * primaryStrip() const
Returns the primary associated measurement.
virtual xAOD::UncalibMeasType type() const override final
Returns the type of the measurement type as a simple enumeration.
const Identifier & identify() const
: Returns the Athena identifier of the micro mega cluster It's constructed from the measurementHash &...
IdentifierHash layerHash() const
Returns the hash of the associated layer (Needed for surface retrieval)
const MuonGMR4::MmReadoutElement * readoutElement() const
Retrieve the associated MmReadoutElement.
ConstMatrixMap< N > localCovariance() const
Returns the local covariance of the measurement.
ConstVectorMap< N > localPosition() const
Returns the local position of the measurement.
IdentifierHash layerHash() const
Returns the hash of the associated gasGap layer.
const MuonGMR4::sTgcReadoutElement * readoutElement() const
Retrieve the associated sTgcReadoutElement.
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.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Affine3d Transform3D
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
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.
This header ties the generic definitions in this package.
ISpacePointCalibrator::CalibSpacePointVec CalibSpacePointVec
CalibratedSpacePoint::State State
ISpacePointCalibrator::CalibSpacePointPtr CalibSpacePointPtr
const Segment * detailedSegment(const xAOD::MuonSegment &seg)
Helper function to navigate from the xAOD::MuonSegment to the MuonR4::Segment.
Amg::Vector3D toLocal(const Amg::Transform3D &toLocalTrans, const Amg::Vector3D &dir)
Rotates a direction vector into a local frame: x-axis : Parallell to the radial direction of the dete...
const T * get(const ReadCondHandleKey< T > &key, const EventContext &ctx)
Convenience function to retrieve an object given a ReadCondHandleKey.
MdtDriftCircle_v1 MdtDriftCircle
MdtTwinDriftCircle_v1 MdtTwinDriftCircle
TgcStrip_v1 TgcStrip
Definition TgcStripFwd.h:9
sTgcStripCluster_v1 sTgcStripCluster
UncalibMeasType
Define the type of the uncalibrated measurement.
const Identifier & identify(const UncalibratedMeasurement *meas)
Returns the associated identifier from the muon measurement.
RpcMeasurement_v1 RpcMeasurement
MMCluster_v1 MMCluster
sTgcMeasurement_v1 sTgcMeasurement
MuonSegment_v1 MuonSegment
Reference the current persistent version:
CombinedMuonStrip_v1 CombinedMuonStrip
class which holds the full set of calibration constants for a given tube
#define THROW_EXCEPTION(MESSAGE)
Definition throwExcept.h:10