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#include "Acts/Utilities/MathHelpers.hpp"
28#include "Acts/Utilities/Enumerate.hpp"
29
30
31namespace {
32 constexpr double c_inv = 1./ Gaudi::Units::c_light;
33 static const SG::Decorator<int> dec_trackSign{"segmentFitDriftSign"};
34}
35
36namespace MuonR4{
37 using namespace Acts::UnitLiterals;
41 using namespace SegmentFit;
42
44 ATH_CHECK(m_geoCtxKey.initialize());
45 ATH_CHECK(m_idHelperSvc.retrieve());
46 ATH_CHECK(m_mdtCalibrationTool.retrieve(EnableTool{m_idHelperSvc->hasMDT()}));
47 ATH_CHECK(m_nswCalibTool.retrieve(EnableTool{m_idHelperSvc->hasMM() || m_idHelperSvc->hasSTGC()}));
48 ATH_CHECK(detStore()->retrieve(m_detMgr));
49 return StatusCode::SUCCESS;
50 }
51
53 const Amg::Vector3D& trackDir,
54 CalibSpacePointVec& hitsToCalib) const {
55 std::vector<int> signs = SeedingAux::strawSigns(trackPos, trackDir,
56 hitsToCalib);
57 for (const auto [spIdx, sp]: Acts::enumerate(hitsToCalib)) {
58 sp->setDriftRadius(sp->driftRadius() * signs[spIdx]);
59 }
60 }
62 const CalibratedSpacePoint& spacePoint,
63 const Amg::Vector3D& segPos,
64 const Amg::Vector3D& segDir,
65 const double timeDelay) const {
66 CalibSpacePointPtr calibSP{};
67 if (spacePoint.type() != xAOD::UncalibMeasType::Other){
68 calibSP = calibrate(ctx, spacePoint.spacePoint(), segPos, segDir, timeDelay);
69 } else {
70 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint);
71 }
72 if (spacePoint.fitState() == State::Outlier) {
73 calibSP->setFitState(State::Outlier);
74 } else if (spacePoint.fitState() == State::Duplicate) {
75 calibSP->setFitState(State::Duplicate);
76 }
77 return calibSP;
78 }
79
80 CalibSpacePointVec SpacePointCalibrator::calibrate(const Acts::CalibrationContext& cctx,
81 const Amg::Vector3D& segPos,
82 const Amg::Vector3D& segDir,
83 const double timeDelay,
84 const CalibSpacePointVec& spacePoints) const {
85 CalibSpacePointVec newCalib{};
86 const EventContext* ctx = cctx.get<const EventContext*>();
87 newCalib.reserve(spacePoints.size());
88 for (const CalibSpacePointPtr& sp : spacePoints){
89 newCalib.emplace_back(calibrate(*ctx, *sp, segPos, segDir, timeDelay));
90 }
91 return newCalib;
92 }
93
95 const SpacePoint* spacePoint,
96 const Amg::Vector3D& posInChamb,
97 const Amg::Vector3D& dirInChamb,
98 const double timeDelay) const {
99 const ActsTrk::GeometryContext* gctx{nullptr};
100 if (!SG::get(gctx, m_geoCtxKey, ctx).isSuccess()) {
101 return nullptr;
102 }
103 const Amg::Vector3D& spPos{spacePoint->localPosition()};
104 const Amg::Transform3D& locToGlob{spacePoint->msSector()->localToGlobalTransform(*gctx)};
105 const Amg::Vector3D& chDir{spacePoint->sensorDirection()};
106
107 // Adjust the space point position according to the external seed. But only if the space point
108 // is a 1D strip
109 Amg::Vector3D calibSpPos = spacePoint->dimension() == 2 ? spPos
110 : spPos + Amg::intersect<3>(posInChamb, dirInChamb, spPos, chDir).value_or(0) * chDir;
111
112 SpacePoint::Cov_t cov = spacePoint->covariance();
113 CalibSpacePointPtr calibSP{};
114 ATH_MSG_VERBOSE("Calibrate "<<(*spacePoint) <<" -> updated pos "<<Amg::toString(calibSpPos));
115 switch (spacePoint->type()) {
116 using enum xAOD::UncalibMeasType;
117 case MdtDriftCircleType: {
118 const Amg::Vector3D locClosestApproach = posInChamb
119 + Amg::intersect<3>(spPos, chDir,
120 posInChamb, dirInChamb).value_or(0) * dirInChamb;
121
122 Amg::Vector3D closestApproach{locToGlob* locClosestApproach};
123 const double timeOfArrival = closestApproach.mag() * c_inv + ActsTrk::timeToAthena(timeDelay);
124
125 if (ATH_LIKELY(spacePoint->dimension() == 1)) {
126 auto* dc = static_cast<const xAOD::MdtDriftCircle*>(spacePoint->primaryMeasurement());
127 MdtCalibInput calibInput{*dc, *gctx};
128 calibInput.setTrackDirection(locToGlob.linear() * dirInChamb,
129 Acts::abs(dirInChamb.phi() - 90._degree) > 1.e-7 );
130 calibInput.setTimeOfFlight(timeOfArrival);
131 calibInput.setClosestApproach(std::move(closestApproach));
132 ATH_MSG_VERBOSE("Parse hit calibration "<<m_idHelperSvc->toString(dc->identify())<<", "<<calibInput);
133 MdtCalibOutput calibOutput = m_mdtCalibrationTool->calibrate(ctx, calibInput);
134 ATH_MSG_VERBOSE("Returned calibration object "<<calibOutput);
135 State fitState{State::Valid};
137 if (calibOutput.status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
138 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
139 <<std::endl<<calibInput<<std::endl<<calibOutput);
140 fitState = State::FailedCalib;
141 cov[Acts::toUnderlying(AxisDefs::etaCov)] = dc->readoutElement()->innerTubeRadius();
142 } else {
143 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(calibOutput.driftRadiusUncert());
144 }
145 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos), fitState);
146 calibSP->setCovariance(cov);
147 calibSP->setDriftRadius(calibOutput.driftRadius());
149 double fastToF {(locToGlob * calibSP->localPosition()).norm() * c_inv};
150 calibSP->setTimeMeasurement(ActsTrk::timeToActs(dc->tdc() * IMdtCalibrationTool::tdcBinSize -
151 calibOutput.tubeT0() - fastToF - calibOutput.signalPropagationTime()));
152 ATH_MSG_VERBOSE("Mdt time Meas: " << ActsTrk::timeToAthena(calibSP->time())
153 << ", ToF / fastToF: " << fastToF << " / " << closestApproach.mag() * c_inv
154 << ", tubeT0: " << calibOutput.tubeT0() << ", Signal Prop Time: " << calibOutput.signalPropagationTime());
155 } else {
156 auto* dc = static_cast<const xAOD::MdtTwinDriftCircle*>(spacePoint->primaryMeasurement());
157 MdtCalibInput calibInput{*dc, *gctx};
158 calibInput.setClosestApproach(closestApproach);
159 calibInput.setTimeOfFlight(timeOfArrival);
160
161 MdtCalibInput twinInput{dc->twinIdentify(), dc->twinAdc(), dc->twinTdc(), dc->readoutElement(), *gctx};
162 twinInput.setClosestApproach(closestApproach);
163 twinInput.setTimeOfFlight(timeOfArrival);
164
165 MdtCalibTwinOutput calibOutput = m_mdtCalibrationTool->calibrateTwinTubes(ctx,
166 std::move(calibInput),
167 std::move(twinInput));
168
169 State fitState{State::Valid};
170 if (calibOutput.primaryStatus() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
171 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
172 <<std::endl<<calibOutput);
173 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(dc->readoutElement()->innerTubeRadius());
174 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(0.5* dc->readoutElement()->activeTubeLength(dc->measurementHash()));
175 fitState = State::FailedCalib;
176 } else {
177 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(calibOutput.uncertPrimaryR());
178 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(calibOutput.sigmaZ());
179 }
180 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos), fitState);
181 calibSP->setCovariance(cov);
182 calibSP->setDriftRadius(calibOutput.primaryDriftR());
184 double fastToF {(locToGlob * calibSP->localPosition()).norm() * c_inv};
185 double tubeT0 {m_mdtCalibrationTool->getCalibConstants(ctx, dc->identify())->tubeCalib->getCalib(dc->identify())->t0};
186 // Remember to add the signal propagation time!!
187 calibSP->setTimeMeasurement(ActsTrk::timeToActs(calibOutput.primaryTdc() * IMdtCalibrationTool::tdcBinSize - tubeT0 - fastToF));
188 }
189 break;
190 }
191 case RpcStripType: {
192 auto* strip = static_cast<const xAOD::RpcMeasurement*>(spacePoint->primaryMeasurement());
193
195 const Amg::Transform3D toGasGap{strip->readoutElement()->globalToLocalTransform(*gctx, strip->layerHash()) * locToGlob};
196 const Amg::Vector3D lPos = toGasGap * calibSpPos;
198 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
199
200 cov[Acts::toUnderlying(AxisDefs::timeCov)] = Acts::square(ActsTrk::timeToActs(m_rpcTimeResolution));
201
202 const double time1 = strip->time()
203 - strip->readoutElement()->distanceToEdge(strip->layerHash(), lPos,
204 EdgeSide::readOut) /m_rpcSignalVelocity;
205
206 if (spacePoint->dimension() == 2) {
207 auto* strip2 = static_cast<const xAOD::RpcMeasurement*>(spacePoint->secondaryMeasurement());
208
209 const double time2 = strip2->time() -
210 strip2->readoutElement()->distanceToEdge(strip2->layerHash(),lPos, EdgeSide::readOut)/m_rpcSignalVelocity;
212 calibSP->setTimeMeasurement(ActsTrk::timeToActs(0.5*(time1 + time2)));
214 cov[Acts::toUnderlying(AxisDefs::timeCov)] += Acts::square(ActsTrk::timeToActs(0.5*(time1 - time2)));
215 } else {
216 calibSP->setTimeMeasurement(ActsTrk::timeToActs(time1));
217 }
218 calibSP->setCovariance(cov);
219 ATH_MSG_VERBOSE("Create rpc space point "<<m_idHelperSvc->toString(strip->identify())<<", dimension "<<spacePoint->dimension()
220 << ", at "<<Amg::toString(calibSP->localPosition())<<", uncalib time: "
221 <<strip->time()<<", calib time: "<<ActsTrk::timeToAthena(calibSP->time())<<" cov " <<calibSP->covariance()
222 <<", time Uncert: "<<ActsTrk::timeToAthena(std::sqrt(calibSP->covariance()[Acts::toUnderlying(AxisDefs::timeCov)])));
223 break;
224 }
225 case TgcStripType: {
226 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
228 if (spacePoint->primaryMeasurement()->measuresPhi()) {
229 const auto* strip = static_cast<const xAOD::TgcStrip*>(spacePoint->primaryMeasurement());
230 const Amg::Transform3D toGasGap{strip->readoutElement()->globalToLocalTransform(*gctx, strip->layerHash()) * locToGlob};
231 const Amg::Vector3D lPos = toGasGap * calibSP->localPosition();
232 const auto& sensorPlane = strip->readoutElement()->sensorLayout(strip->layerHash());
233 const auto& radialDesign = strip->readoutElement()->stripLayout(strip->layerHash());
234 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(
235 radialDesign.stripPitch(strip->channelNumber(), sensorPlane->to2D(lPos,true))) / 12.;
236 }
237 calibSP->setCovariance(cov);
238 break;
239 }
240 case MMClusterType: {
241 const xAOD::MMCluster* cluster = static_cast<const xAOD::MMCluster*>(spacePoint->primaryMeasurement());
242 Amg::Vector3D globalPos{locToGlob * posInChamb};
243 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
244
245 std::pair<double, double> calibPosCov {calibrateMM(ctx, *gctx, *cluster, globalPos, globalDir)};
246
247 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPosCov.first << " " << calibPosCov.second);
248 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibPosCov.second;
249 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTransform(*gctx, cluster->layerHash())};
250
251 // 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
252 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
253 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
254 calibSpPosInLayer.x() = calibPosCov.first;
255 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
256 calibSpPos = toChamberTrans * calibSpPosInLayer;
257
258 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
259 calibSP->setCovariance(cov);
260 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());
261
262 break;
263 }
264 case sTgcStripType: {
265 const auto* cluster = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->primaryMeasurement());
266
267 // We do not apply any correction for pads or wire only space points
268 if (cluster->channelType() != sTgcIdHelper::sTgcChannelTypes::Strip) {
269 ATH_MSG_DEBUG("Calibrating an sTGC Pad or wire " << m_idHelperSvc->toString(cluster->identify()));
270 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
271 calibSP->setCovariance(cov);
272 break;
273 }
274
275 std::optional<double> posAlongTheStrip{std::nullopt};
276
277 // check if the space point is a strip/wire combination and take the position along the strip from the wire measurement
278 if(spacePoint->secondaryMeasurement()) {
279 const auto* secMeas = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->secondaryMeasurement());
280 ATH_MSG_VERBOSE("Using secondary measurement "<< m_idHelperSvc->toString(secMeas->identify())<<" for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
281 // Extract scalar value - use 2D for pads (2 dimensions), 1D for wires (1 dimension)
282 if (secMeas->numDimensions() == 2) {
283 posAlongTheStrip = static_cast<double>(secMeas->localPosition<2>()[0]);
284 } else {
285 posAlongTheStrip = static_cast<double>(secMeas->localPosition<1>()[0]);
286 }
287 } else {
288 ATH_MSG_VERBOSE("No secondary measurement for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
289 }
290
291 Amg::Vector3D globalPos{locToGlob * posInChamb};
292 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
293
294 const auto* stripClus = static_cast<const xAOD::sTgcStripCluster*>(cluster);
295 const auto [calibPos, calibCov] = calibratesTGC(ctx, *gctx, *stripClus, posAlongTheStrip, globalPos, globalDir);
296
297 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPos << " " << calibCov);
298 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibCov;
299 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTransform(*gctx, cluster->layerHash())};
300
301 // 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
302 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
303 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
304 calibSpPosInLayer.x() = calibPos;
305 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
306 calibSpPos = toChamberTrans * calibSpPosInLayer;
307
308 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
309 calibSP->setCovariance(cov);
310 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());
311 break;
312 }
313
314 default:
315 ATH_MSG_WARNING("Do not know how to calibrate "<<m_idHelperSvc->toString(spacePoint->identify()));
316 }
317 return calibSP;
318 }
319
321 const std::vector<const SpacePoint*>& spacePoints,
322 const Amg::Vector3D& posInChamb,
323 const Amg::Vector3D& dirInChamb,
324 const double timeDelay) const {
325 CalibSpacePointVec calibSpacePoints{};
326 calibSpacePoints.reserve(spacePoints.size());
327 for(const SpacePoint* spacePoint : spacePoints) {
328 CalibSpacePointPtr hit = calibrate(ctx, spacePoint, posInChamb, dirInChamb, timeDelay);
329 if (hit) {
330 calibSpacePoints.push_back(std::move(hit));
331 }
332 }
333 return calibSpacePoints;
334 }
335 double SpacePointCalibrator::driftVelocity(const Acts::CalibrationContext& ctx,
336 const CalibratedSpacePoint& spacePoint) const {
338
339 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
340 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
341 return ActsTrk::velocityToActs(calibConsts->rtRelation->rt()->driftVelocity(driftTime.value_or(0.)));
342 }
343 return 0.;
344 }
345 double SpacePointCalibrator::driftAcceleration(const Acts::CalibrationContext& ctx,
346 const CalibratedSpacePoint& spacePoint) const {
348 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
349 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
350 return ActsTrk::accelerationToActs(calibConsts->rtRelation->rt()->driftAcceleration(driftTime.value_or(0.)));
351 }
352 return 0.;
353 }
354
355 std::pair<double, double> SpacePointCalibrator::calibrateMM(const EventContext& ctx,
356 const ActsTrk::GeometryContext& gctx,
357 const xAOD::MMCluster& cluster,
358 const Amg::Vector3D& globalPos,
359 const Amg::Vector3D& globalDir) const {
360 std::vector<NSWCalib::CalibratedStrip> calibClus;
361 StatusCode sc = m_nswCalibTool->calibrateClus(ctx, gctx, cluster, globalPos, calibClus);
362 if(sc.isFailure()) {
363 ATH_MSG_WARNING("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
364 return std::make_pair(0., 0.);
365 }
366
367 Amg::Vector2D locPos{cluster.localPosition<1>()[0] * Amg::Vector2D::UnitX()};
368 Amg::Vector3D locDir = Muon::NswClustering::toLocal(cluster.readoutElement()->globalToLocalTransform(gctx, cluster.layerHash()), globalDir);
369
370 Amg::MatrixX calibCov{};
371 calibCov.resize(1,1);
372 calibCov(0,0) = cluster.localCovariance<1>()(0, 0);
373 ATH_MSG_DEBUG("old loc pos " << locPos[0] << " old cov" << calibCov(0,0) );
374
375 Muon::IMMClusterBuilderTool::RIO_Author rotAuthor = m_clusterBuilderToolMM->getCalibratedClusterPosition(ctx, calibClus, locDir ,locPos, calibCov);
376 if(rotAuthor == Muon::IMMClusterBuilderTool::RIO_Author::unKnownAuthor){
377 THROW_EXCEPTION("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
378 }
379 ATH_MSG_DEBUG("new loc pos " << locPos[0] << " new cov" << calibCov(0,0) );
380 return std::make_pair(locPos[0], calibCov(0,0));
381 }
382
383 std::pair<double, double> SpacePointCalibrator::calibratesTGC(const EventContext& /*ctx*/,
384 const ActsTrk::GeometryContext& gctx,
385 const xAOD::sTgcStripCluster& cluster,
386 std::optional<double> posAlongTheStrip,
387 const Amg::Vector3D& globalPos,
388 const Amg::Vector3D& /*globalDir*/) const{
389
390 // if the second coordiante was not provided by the wire, take it from the seed track position
391 if(!posAlongTheStrip) {
392 Amg::Vector3D extPosLocal = cluster.readoutElement()->globalToLocalTransform(gctx, cluster.layerHash()) * globalPos;
393 posAlongTheStrip = extPosLocal[1];
394 }
395
396 // For now just copying over the local position and covariance. Eventually this should apply corrections from B-Lines and as build geometry
397
398 return std::make_pair(cluster.localPosition<1>()[0], cluster.localCovariance<1>()(0,0));
399 }
400 void SpacePointCalibrator::calibrateCombinedPrd(const EventContext& ctx,
401 const ActsTrk::GeometryContext& gctx,
402 const xAOD::CombinedMuonStrip* combinedPrd,
403 ActsTrk::MutableTrackContainer::TrackStateProxy state) const {
404 const auto sl = ActsTrk::detail::xAODUncalibMeasCalibrator::pack(combinedPrd);
405
406 Amg::Vector2D cmbPos = xAOD::toEigen(combinedPrd->localPosition<2>());
407 AmgSymMatrix(2) cmbCov = xAOD::toEigen(combinedPrd->localCovariance<2>());
408 if (combinedPrd->type() == xAOD::UncalibMeasType::RpcStripType) {
409 if (m_useRpcTime) {
410 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
411 }
413
414 } else if (combinedPrd->type() == xAOD::UncalibMeasType::TgcStripType) {
415 if (m_useTgcTime) {
416 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
417 }
418
420 cmbPos, cmbCov, sl, state);
421
422 } else if(combinedPrd->type() == xAOD::UncalibMeasType::sTgcStripType) {
423 if (m_usesTgcTime) {
424 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
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
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] ,
436 trackPars.position(gctx.context()),
437 trackPars.direction())};
438 cmbPos[0] = calibPosCov.first;
439 cmbCov(0,0) = calibPosCov.second;
440 }
442
443 } else {
444 THROW_EXCEPTION("Undefined uncalibrated measurement "
445 <<m_idHelperSvc->toString(combinedPrd->identify()));
446 }
447 }
448 void SpacePointCalibrator::calibrateSourceLink(const Acts::GeometryContext& geoctx,
449 const Acts::CalibrationContext& cctx,
450 const Acts::SourceLink& link,
451 ActsTrk::MutableTrackContainer::TrackStateProxy trackState) const {
452
454 const Acts::BoundTrackParameters trackPars{trackState.referenceSurface().getSharedPtr(),
455 trackState.parameters(), trackState.covariance(),
456 Acts::ParticleHypothesis::muon()};
457
458
459 const auto* muonMeas = ActsTrk::detail::xAODUncalibMeasCalibrator::unpack(link);
460 const ActsTrk::GeometryContext* gctx = geoctx.get<const ActsTrk::GeometryContext*>();
461 const EventContext* ctx = cctx.get<const EventContext*>();
462 ATH_MSG_VERBOSE("Calibrate measurement "<<m_idHelperSvc->toString(xAOD::identify(muonMeas))
463 <<" @ surface "<<trackState.referenceSurface().geometryId());
465 if (muonMeas->numDimensions() == 0u) {
466 calibrateCombinedPrd(*ctx, *gctx, static_cast<const xAOD::CombinedMuonStrip*>(muonMeas),
467 trackState);
468 return;
469
470 }
471 const Amg::Vector3D trackPos{trackPars.position(geoctx)};
472 const Amg::Vector3D trackDir{trackPars.direction()};
473
474 switch (muonMeas->type()){
475 using enum xAOD::UncalibMeasType;
476 case MdtDriftCircleType: {
477 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(muonMeas);
478 MdtCalibInput calibInput{*dc, *gctx};
479 calibInput.setClosestApproach(trackPos);
480 //calibInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
481 calibInput.setTrackDirection(trackDir, true);
482 const double driftSign = m_MdtSignFromSegment ?
483 static_cast<double>(dec_trackSign(*dc)) :
484 Acts::copySign(1.,trackPars.parameters()[Acts::eBoundLoc0]);
485
487 if (ATH_LIKELY(muonMeas->numDimensions() == 1)) {
488 MdtCalibOutput calibOutput = m_mdtCalibrationTool->calibrate(*ctx, calibInput);
489 ATH_MSG_VERBOSE("Returned calibration object "<<calibOutput);
490 AmgVector(1) pos{AmgVector(1)::Zero()};
491 AmgSymMatrix(1) cov{AmgSymMatrix(1)::Identity()};
493 if (calibOutput.status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
494 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
495 <<std::endl<<calibInput<<std::endl<<calibOutput);
496 cov(Acts::eBoundLoc0,Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
497 } else {
498 pos[Acts::eBoundLoc0] = driftSign*calibOutput.driftRadius();
499 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.driftRadiusUncert(), 2);
500 }
502 }
504 else {
505 const auto* twinDC = static_cast<const xAOD::MdtTwinDriftCircle*>(muonMeas);
506 MdtCalibInput twinInput{twinDC->twinIdentify(), twinDC->twinAdc(), twinDC->twinTdc(), twinDC->readoutElement(), *gctx};
507 twinInput.setClosestApproach(trackPos);
508 twinInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
509
510 MdtCalibTwinOutput calibOutput = m_mdtCalibrationTool->calibrateTwinTubes(*ctx,
511 std::move(calibInput),
512 std::move(twinInput));
513 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
514 AmgSymMatrix(2) locCov{AmgSymMatrix(2)::Identity()};
515 if (calibOutput.primaryStatus() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
516 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
517 <<std::endl<<calibOutput);
518 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
519 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(0.5* dc->readoutElement()->activeTubeLength(dc->measurementHash()), 2);
520 } else {
521 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.uncertPrimaryR(), 2);
522 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(calibOutput.sigmaZ(), 2);
523 locPos[Acts::eBoundLoc0] = driftSign*calibOutput.primaryDriftR();
524 locPos[Acts::eBoundLoc1] = calibOutput.locZ();
525 }
527 }
528 break;
529 } case RpcStripType: {
530 const auto* rpcClust = static_cast<const xAOD::RpcMeasurement*>(muonMeas);
532 if (ATH_LIKELY(rpcClust->numDimensions() == 1)) {
533
534 if (!m_useRpcTime) {
535 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotNoTime
538 rpcClust->localPosition<1>(),
539 rpcClust->localCovariance<1>(), link, trackState);
540 } else {
541 AmgVector(2) measPars{AmgVector(2)::Zero()};
542 AmgSymMatrix(2) measCov{AmgSymMatrix(2)::Identity()};
543 measPars[0] = rpcClust->localPosition<1>()[0];
544 measCov(0,0) = rpcClust->localCovariance<1>()(0, 0);
545 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
546 measCov(1,1) = std::pow(m_rpcTimeResolution, 2);
547 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotWithTime
550 measPars, measCov, link, trackState);
551 }
552 }
554 else {
555 if (!m_useRpcTime) {
557 rpcClust->localPosition<2>(),
558 rpcClust->localCovariance<2>(), link, trackState);
559 } else {
560 AmgVector(3) measPars{AmgVector(3)::Zero()};
561 AmgSymMatrix(3) measCov{AmgSymMatrix(3)::Identity()};
562 measPars.block<2,1>(0,0) = xAOD::toEigen(rpcClust->localPosition<2>());
563 measCov.block<2,2>(0,0) = xAOD::toEigen(rpcClust->localCovariance<2>());
564 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
565 measCov(2,2) = std::pow(m_rpcTimeResolution, 2);
567 measPars, measCov, link, trackState);
568 }
569 }
570 break;
571 } case TgcStripType: {
572 const auto* tgcClust = static_cast<const xAOD::TgcStrip*>(muonMeas);
573 if (!m_useTgcTime) {
574 if (!tgcClust->measuresPhi()) {
576 tgcClust->localPosition<1>(),
577 tgcClust->localCovariance<1>(),
578 link, trackState);
579
580 } else {
581 const auto [pos, cov] = xAOD::positionAndCovariance(tgcClust);
583 pos, cov, link, trackState);
584
585 }
586 } else {
587 ATH_MSG_WARNING("Tgc time calibration to be implemented...");
588 }
589 break;
590 }
591 case MMClusterType: {
592 const auto* mmClust = static_cast<const xAOD::MMCluster*>(muonMeas);
593 std::pair<double, double> calibPosCov{calibrateMM(*ctx,* gctx, *mmClust, trackPos, trackDir)};
594 AmgVector(1) pos{AmgVector(1)(calibPosCov.first)};
595 AmgSymMatrix(1) cov{AmgSymMatrix(1)(calibPosCov.second)};
596
598 pos, cov, link, trackState);
599 break;
600 } case sTgcStripType: {
601 const auto* stgcClust = static_cast<const xAOD::sTgcMeasurement*>(muonMeas);
602
603 if(stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire) {
605 muonMeas->localPosition<1>(),
606 muonMeas->localCovariance<1>(), link, trackState);
607 } else if (stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad) {
609 stgcClust->localPosition<2>(),
610 stgcClust->localCovariance<2>(), link, trackState);
611 } else { // strips
612 const auto stgCluster = static_cast<const xAOD::sTgcStripCluster*>(muonMeas);
613 std::pair<double, double> calibPosCov{calibratesTGC(*ctx, *gctx, *stgCluster, std::nullopt, trackPos, trackDir)};
614 if(!m_usesTgcTime) {
615 AmgVector(1) pos{calibPosCov.first};
616 AmgSymMatrix(1) cov{calibPosCov.second};
618 pos, cov, link, trackState);
619 } else {
620 ATH_MSG_WARNING("sTGC time calibration to be implemented...");
621 AmgVector(2) pos{AmgVector(2)::Zero()};
622 AmgSymMatrix(2) cov{AmgSymMatrix(2)::Zero()};
623 pos[0] = calibPosCov.first;
624 pos[1] = stgCluster->time();
625 cov(0,0) = calibPosCov.second;
626 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
627 cov(1,1) = std::pow(25 /*ns*/, 2);
628
630 pos, cov, link, trackState);
631 }
632 }
633 break;
634 } case Other: {
636 auxCalibrator.calibrate(geoctx, cctx, link, trackState);
637 break;
638 } default: {
639 THROW_EXCEPTION("The parsed measurement is not a muon measurement. Please check.");
640 }
641 }
642 }
644 const auto [segPos, segLine] = makeLine(localSegmentPars(segment));
645 const Segment* detSeg = MuonR4::detailedSegment(segment);
646 for (const auto& meas : detSeg->measurements()) {
648 dec_trackSign(*meas->spacePoint()->primaryMeasurement()) =
649 SeedingAux::strawSign(segPos, segLine, *meas);
650 }
651 }
652 }
653
654 double SpacePointCalibrator::driftRadius(const Acts::CalibrationContext& cctx,
655 const CalibratedSpacePoint& spacePoint,
656 const double timeDelay) const {
658 const MuonCalib::MdtFullCalibData* calibConsts =
659 m_mdtCalibrationTool->getCalibConstants(*cctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
660 return calibConsts->rtRelation->rt()->radius(ActsTrk::timeToAthena(spacePoint.time() - timeDelay));
661 }
662 return 0.;
663 }
664
665 double SpacePointCalibrator::driftVelocity(const Acts::CalibrationContext& cctx,
666 const CalibratedSpacePoint& spacePoint,
667 const double timeDelay) const {
669 const MuonCalib::MdtFullCalibData* calibConsts =
670 m_mdtCalibrationTool->getCalibConstants(*cctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
671 return ActsTrk::velocityToActs(calibConsts->rtRelation->rt()->driftVelocity(ActsTrk::timeToAthena(spacePoint.time() - timeDelay)));
672 }
673 return 0.;
674 }
675 double SpacePointCalibrator::driftAcceleration(const Acts::CalibrationContext& cctx,
676 const CalibratedSpacePoint& spacePoint,
677 const double timeDelay) const {
679 const MuonCalib::MdtFullCalibData* calibConsts =
680 m_mdtCalibrationTool->getCalibConstants(*cctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
681 return ActsTrk::accelerationToActs(calibConsts->rtRelation->rt()->driftAcceleration(ActsTrk::timeToAthena(spacePoint.time() - timeDelay)));
682 }
683 return 0.;
684 }
685
686}
#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.
Source link calibrator implementation for xAOD::Uncalibrated measurements.
void calibrate(const Acts::GeometryContext &gctx, const Acts::CalibrationContext &cctx, const Acts::SourceLink &sl, const MutableTrackStateBackend::TrackStateProxy trackState) const
: Interface method for the Acts fitter to calibrate the trajectory track states from the source link ...
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.
static constexpr double tdcBinSize
Conversion to go from tdc counts -> drift Time.
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.
double signalPropagationTime() const
Returns the signal propagation time.
double tubeT0() const
Returns the point in time where the muon typically enters the chamber.
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
double time() const
Returns the measurement's recorded time.
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
double driftRadius(const Acts::CalibrationContext &cctx, const CalibratedSpacePoint &spacePoint, const double timeDelay) 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...
const Cov_t & covariance() const
Returns the covariance array.
const Identifier & identify() const
: Identifier of the primary measurement
unsigned dimension() const
Is the space point a 1D or combined 2D measurement.
std::array< double, 3 > Cov_t
Abrivation of the covariance type.
MMClusterOnTrack::Author RIO_Author
Refinement of the cluster position after the cluster calibration loop is ran with a complete external...
const xAOD::MuonMeasurement * 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 MuonGMR4::MmReadoutElement * readoutElement() const override final
Retrieve the associated MmReadoutElement.
IdentifierHash layerHash() const override final
Returns the hash of the associated layer (Needed for surface retrieval).
virtual std::uint8_t measuresPhi() const =0
Returns whether the phi coordinate is measured.
const Identifier & identify() const
Returns the Athena identifier of the measurement.
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 override final
Returns the hash of the associated gasGap layer.
const MuonGMR4::sTgcReadoutElement * readoutElement() const override final
Retrieve the associated sTgcReadoutElement.
constexpr double timeToAthena(const double actsT)
Converts a time unit from Acts to Athena units.
constexpr double velocityToActs(const double athenaV)
Converts a velocity from Athena to Acts units.
constexpr double accelerationToActs(const double athenaA)
Converts an acceleration from Athena to Acts units.
constexpr double timeToActs(const double athenaT)
Converts a time unit from Athena to 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.
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...
SG::Decorator< T, ALLOC > Decorator
Helper class to provide type-safe access to aux data, specialized for JaggedVecElt.
Definition AuxElement.h:576
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
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...
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