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()) {
117 const Amg::Vector3D locClosestApproach = posInChamb
118 + Amg::intersect<3>(spPos, chDir,
119 posInChamb, dirInChamb).value_or(0) * dirInChamb;
120
121 Amg::Vector3D closestApproach{locToGlob* locClosestApproach};
122 const double timeOfArrival = closestApproach.mag() * c_inv + ActsTrk::timeToAthena(timeDelay);
123
124 if (ATH_LIKELY(spacePoint->dimension() == 1)) {
125 auto* dc = static_cast<const xAOD::MdtDriftCircle*>(spacePoint->primaryMeasurement());
126 MdtCalibInput calibInput{*dc, *gctx};
127 calibInput.setTrackDirection(locToGlob.linear() * dirInChamb,
128 Acts::abs(dirInChamb.phi() - 90._degree) > 1.e-7 );
129 calibInput.setTimeOfFlight(timeOfArrival);
130 calibInput.setClosestApproach(std::move(closestApproach));
131 ATH_MSG_VERBOSE("Parse hit calibration "<<m_idHelperSvc->toString(dc->identify())<<", "<<calibInput);
132 MdtCalibOutput calibOutput = m_mdtCalibrationTool->calibrate(ctx, calibInput);
133 ATH_MSG_VERBOSE("Returned calibration object "<<calibOutput);
134 State fitState{State::Valid};
136 if (calibOutput.status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
137 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
138 <<std::endl<<calibInput<<std::endl<<calibOutput);
139 fitState = State::FailedCalib;
140 cov[Acts::toUnderlying(AxisDefs::etaCov)] = dc->readoutElement()->innerTubeRadius();
141 } else {
142 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(calibOutput.driftRadiusUncert());
143 }
144 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos), fitState);
145 calibSP->setCovariance(cov);
146 calibSP->setDriftRadius(calibOutput.driftRadius());
148 double fastToF {(locToGlob * calibSP->localPosition()).norm() * c_inv};
149 calibSP->setTimeMeasurement(ActsTrk::timeToActs(dc->tdc() * IMdtCalibrationTool::tdcBinSize -
150 calibOutput.tubeT0() - fastToF - calibOutput.signalPropagationTime()));
151 ATH_MSG_VERBOSE("Mdt time Meas: " << ActsTrk::timeToAthena(calibSP->time())
152 << ", ToF / fastToF: " << fastToF << " / " << closestApproach.mag() * c_inv
153 << ", tubeT0: " << calibOutput.tubeT0() << ", Signal Prop Time: " << calibOutput.signalPropagationTime());
154 } else {
155 auto* dc = static_cast<const xAOD::MdtTwinDriftCircle*>(spacePoint->primaryMeasurement());
156 MdtCalibInput calibInput{*dc, *gctx};
157 calibInput.setClosestApproach(closestApproach);
158 calibInput.setTimeOfFlight(timeOfArrival);
159
160 MdtCalibInput twinInput{dc->twinIdentify(), dc->twinAdc(), dc->twinTdc(), dc->readoutElement(), *gctx};
161 twinInput.setClosestApproach(closestApproach);
162 twinInput.setTimeOfFlight(timeOfArrival);
163
164 MdtCalibTwinOutput calibOutput = m_mdtCalibrationTool->calibrateTwinTubes(ctx,
165 std::move(calibInput),
166 std::move(twinInput));
167
168 State fitState{State::Valid};
169 if (calibOutput.primaryStatus() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
170 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
171 <<std::endl<<calibOutput);
172 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(dc->readoutElement()->innerTubeRadius());
173 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(0.5* dc->readoutElement()->activeTubeLength(dc->measurementHash()));
174 fitState = State::FailedCalib;
175 } else {
176 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(calibOutput.uncertPrimaryR());
177 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(calibOutput.sigmaZ());
178 }
179 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos), fitState);
180 calibSP->setCovariance(cov);
181 calibSP->setDriftRadius(calibOutput.primaryDriftR());
183 double fastToF {(locToGlob * calibSP->localPosition()).norm() * c_inv};
184 double tubeT0 {m_mdtCalibrationTool->getCalibConstants(ctx, dc->identify())->tubeCalib->getCalib(dc->identify())->t0};
185 // Remember to add the signal propagation time!!
186 calibSP->setTimeMeasurement(ActsTrk::timeToActs(calibOutput.primaryTdc() * IMdtCalibrationTool::tdcBinSize - tubeT0 - fastToF));
187 }
188 break;
189 }
191 auto* strip = static_cast<const xAOD::RpcMeasurement*>(spacePoint->primaryMeasurement());
192
194 const Amg::Transform3D toGasGap{strip->readoutElement()->globalToLocalTransform(*gctx, strip->layerHash()) * locToGlob};
195 const Amg::Vector3D lPos = toGasGap * calibSpPos;
197 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
198
199 cov[Acts::toUnderlying(AxisDefs::timeCov)] = Acts::square(ActsTrk::timeToActs(m_rpcTimeResolution));
200
201 const double time1 = strip->time()
202 - strip->readoutElement()->distanceToEdge(strip->layerHash(), lPos,
203 EdgeSide::readOut) /m_rpcSignalVelocity;
204
205 if (spacePoint->dimension() == 2) {
206 auto* strip2 = static_cast<const xAOD::RpcMeasurement*>(spacePoint->secondaryMeasurement());
207
208 const double time2 = strip2->time() -
209 strip2->readoutElement()->distanceToEdge(strip2->layerHash(),lPos, EdgeSide::readOut)/m_rpcSignalVelocity;
211 calibSP->setTimeMeasurement(ActsTrk::timeToActs(0.5*(time1 + time2)));
213 cov[Acts::toUnderlying(AxisDefs::timeCov)] += Acts::square(ActsTrk::timeToActs(0.5*(time1 - time2)));
214 } else {
215 calibSP->setTimeMeasurement(ActsTrk::timeToActs(time1));
216 }
217 calibSP->setCovariance(cov);
218 ATH_MSG_VERBOSE("Create rpc space point "<<m_idHelperSvc->toString(strip->identify())<<", dimension "<<spacePoint->dimension()
219 << ", at "<<Amg::toString(calibSP->localPosition())<<", uncalib time: "
220 <<strip->time()<<", calib time: "<<ActsTrk::timeToAthena(calibSP->time())<<" cov " <<calibSP->covariance()
221 <<", time Uncert: "<<ActsTrk::timeToAthena(std::sqrt(calibSP->covariance()[Acts::toUnderlying(AxisDefs::timeCov)])));
222 break;
223 }
225 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
226 calibSP->setCovariance(cov);
227 break;
228 }
230 const xAOD::MMCluster* cluster = static_cast<const xAOD::MMCluster*>(spacePoint->primaryMeasurement());
231 Amg::Vector3D globalPos{locToGlob * posInChamb};
232 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
233
234 std::pair<double, double> calibPosCov {calibrateMM(ctx, *gctx, *cluster, globalPos, globalDir)};
235
236 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPosCov.first << " " << calibPosCov.second);
237 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibPosCov.second;
238 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTransform(*gctx, cluster->layerHash())};
239
240 // 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
241 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
242 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
243 calibSpPosInLayer.x() = calibPosCov.first;
244 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
245 calibSpPos = toChamberTrans * calibSpPosInLayer;
246
247 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
248 calibSP->setCovariance(cov);
249 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());
250
251 break;
252 }
254 const auto* cluster = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->primaryMeasurement());
255
256 // We do not apply any correction for pads or wire only space points
257 if (cluster->channelType() != sTgcIdHelper::sTgcChannelTypes::Strip) {
258 ATH_MSG_DEBUG("Calibrating an sTGC Pad or wire " << m_idHelperSvc->toString(cluster->identify()));
259 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
260 calibSP->setCovariance(cov);
261 break;
262 }
263
264 std::optional<double> posAlongTheStrip{std::nullopt};
265
266 // check if the space point is a strip/wire combination and take the position along the strip from the wire measurement
267 if(spacePoint->secondaryMeasurement()) {
268 const auto* secMeas = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->secondaryMeasurement());
269 ATH_MSG_VERBOSE("Using secondary measurement "<< m_idHelperSvc->toString(secMeas->identify())<<" for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
270 // Extract scalar value - use 2D for pads (2 dimensions), 1D for wires (1 dimension)
271 if (secMeas->numDimensions() == 2) {
272 posAlongTheStrip = static_cast<double>(secMeas->localPosition<2>()[0]);
273 } else {
274 posAlongTheStrip = static_cast<double>(secMeas->localPosition<1>()[0]);
275 }
276 } else {
277 ATH_MSG_VERBOSE("No secondary measurement for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
278 }
279
280 Amg::Vector3D globalPos{locToGlob * posInChamb};
281 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
282
283 const auto* stripClus = static_cast<const xAOD::sTgcStripCluster*>(cluster);
284 const auto [calibPos, calibCov] = calibratesTGC(ctx, *gctx, *stripClus, posAlongTheStrip, globalPos, globalDir);
285
286 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPos << " " << calibCov);
287 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibCov;
288 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTransform(*gctx, cluster->layerHash())};
289
290 // 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
291 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
292 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
293 calibSpPosInLayer.x() = calibPos;
294 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
295 calibSpPos = toChamberTrans * calibSpPosInLayer;
296
297 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
298 calibSP->setCovariance(cov);
299 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());
300 break;
301 }
302
303 default:
304 ATH_MSG_WARNING("Do not know how to calibrate "<<m_idHelperSvc->toString(spacePoint->identify()));
305 }
306 return calibSP;
307 }
308
310 const std::vector<const SpacePoint*>& spacePoints,
311 const Amg::Vector3D& posInChamb,
312 const Amg::Vector3D& dirInChamb,
313 const double timeDelay) const {
314 CalibSpacePointVec calibSpacePoints{};
315 calibSpacePoints.reserve(spacePoints.size());
316 for(const SpacePoint* spacePoint : spacePoints) {
317 CalibSpacePointPtr hit = calibrate(ctx, spacePoint, posInChamb, dirInChamb, timeDelay);
318 if (hit) {
319 calibSpacePoints.push_back(std::move(hit));
320 }
321 }
322 return calibSpacePoints;
323 }
324 double SpacePointCalibrator::driftVelocity(const Acts::CalibrationContext& ctx,
325 const CalibratedSpacePoint& spacePoint) const {
327
328 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
329 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
330 return ActsTrk::velocityToActs(calibConsts->rtRelation->rt()->driftVelocity(driftTime.value_or(0.)));
331 }
332 return 0.;
333 }
334 double SpacePointCalibrator::driftAcceleration(const Acts::CalibrationContext& ctx,
335 const CalibratedSpacePoint& spacePoint) const {
337 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
338 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
339 return ActsTrk::accelerationToActs(calibConsts->rtRelation->rt()->driftAcceleration(driftTime.value_or(0.)));
340 }
341 return 0.;
342 }
343
344 std::pair<double, double> SpacePointCalibrator::calibrateMM(const EventContext& ctx,
345 const ActsTrk::GeometryContext& gctx,
346 const xAOD::MMCluster& cluster,
347 const Amg::Vector3D& globalPos,
348 const Amg::Vector3D& globalDir) const {
349 std::vector<NSWCalib::CalibratedStrip> calibClus;
350 StatusCode sc = m_nswCalibTool->calibrateClus(ctx, gctx, cluster, globalPos, calibClus);
351 if(sc.isFailure()) {
352 ATH_MSG_WARNING("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
353 return std::make_pair(0., 0.);
354 }
355
356 Amg::Vector2D locPos{cluster.localPosition<1>()[0] * Amg::Vector2D::UnitX()};
357 Amg::Vector3D locDir = Muon::NswClustering::toLocal(cluster.readoutElement()->globalToLocalTransform(gctx, cluster.layerHash()), globalDir);
358
359 Amg::MatrixX calibCov{};
360 calibCov.resize(1,1);
361 calibCov(0,0) = cluster.localCovariance<1>()(0, 0);
362 ATH_MSG_DEBUG("old loc pos " << locPos[0] << " old cov" << calibCov(0,0) );
363
364 Muon::IMMClusterBuilderTool::RIO_Author rotAuthor = m_clusterBuilderToolMM->getCalibratedClusterPosition(ctx, calibClus, locDir ,locPos, calibCov);
365 if(rotAuthor == Muon::IMMClusterBuilderTool::RIO_Author::unKnownAuthor){
366 THROW_EXCEPTION("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
367 }
368 ATH_MSG_DEBUG("new loc pos " << locPos[0] << " new cov" << calibCov(0,0) );
369 return std::make_pair(locPos[0], calibCov(0,0));
370 }
371
372 std::pair<double, double> SpacePointCalibrator::calibratesTGC(const EventContext& /*ctx*/,
373 const ActsTrk::GeometryContext& gctx,
374 const xAOD::sTgcStripCluster& cluster,
375 std::optional<double> posAlongTheStrip,
376 const Amg::Vector3D& globalPos,
377 const Amg::Vector3D& /*globalDir*/) const{
378
379 // if the second coordiante was not provided by the wire, take it from the seed track position
380 if(!posAlongTheStrip) {
381 Amg::Vector3D extPosLocal = cluster.readoutElement()->globalToLocalTransform(gctx, cluster.layerHash()) * globalPos;
382 posAlongTheStrip = extPosLocal[1];
383 }
384
385 // For now just copying over the local position and covariance. Eventually this should apply corrections from B-Lines and as build geometry
386
387 return std::make_pair(cluster.localPosition<1>()[0], cluster.localCovariance<1>()(0,0));
388 }
389 void SpacePointCalibrator::calibrateCombinedPrd(const EventContext& ctx,
390 const ActsTrk::GeometryContext& gctx,
391 const xAOD::CombinedMuonStrip* combinedPrd,
392 ActsTrk::MutableTrackContainer::TrackStateProxy state) const {
393 const auto sl = ActsTrk::detail::xAODUncalibMeasCalibrator::pack(combinedPrd);
394
395 auto [cmbPos, cmbCov] = xAOD::positionAndCovariance(combinedPrd);
396 if (combinedPrd->type() == xAOD::UncalibMeasType::RpcStripType) {
397 if (m_useRpcTime) {
398 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
399 }
401
402 } else if (combinedPrd->type() == xAOD::UncalibMeasType::TgcStripType) {
403 if (m_useTgcTime) {
404 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
405 }
406
408 cmbPos, cmbCov, sl, state);
409
410 } else if(combinedPrd->type() == xAOD::UncalibMeasType::sTgcStripType) {
411 if (m_usesTgcTime) {
412 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
413 }
414 // combined sTGC Space points can be strip/wire, strip/pad or pad/wire combinations.
415 const auto* primMeas = static_cast<const xAOD::sTgcMeasurement*>(combinedPrd->primaryStrip());
416
417 if(primMeas->channelType() == sTgcIdHelper::sTgcChannelTypes::Strip) {
418 const auto* primStripMeas = static_cast<const xAOD::sTgcStripCluster*>(primMeas);
420 const Acts::BoundTrackParameters trackPars{state.referenceSurface().getSharedPtr(),
421 state.parameters(), state.covariance(),
422 Acts::ParticleHypothesis::muon()};
423 std::pair<double, double> calibPosCov{calibratesTGC(ctx, gctx, *primStripMeas, cmbPos[1] ,
424 trackPars.position(gctx.context()),
425 trackPars.direction())};
426 cmbPos[0] = calibPosCov.first;
427 cmbCov(0,0) = calibPosCov.second;
428 }
430
431 } else {
432 THROW_EXCEPTION("Undefined uncalibrated measurement "
433 <<m_idHelperSvc->toString(xAOD::identify(combinedPrd)));
434 }
435 }
436 void SpacePointCalibrator::calibrateSourceLink(const Acts::GeometryContext& geoctx,
437 const Acts::CalibrationContext& cctx,
438 const Acts::SourceLink& link,
439 ActsTrk::MutableTrackContainer::TrackStateProxy trackState) const {
440
442 const Acts::BoundTrackParameters trackPars{trackState.referenceSurface().getSharedPtr(),
443 trackState.parameters(), trackState.covariance(),
444 Acts::ParticleHypothesis::muon()};
445
446
447 const auto* muonMeas = ActsTrk::detail::xAODUncalibMeasCalibrator::unpack(link);
448 const ActsTrk::GeometryContext* gctx = geoctx.get<const ActsTrk::GeometryContext*>();
449 const EventContext* ctx = cctx.get<const EventContext*>();
450 ATH_MSG_VERBOSE("Calibrate measurement "<<m_idHelperSvc->toString(xAOD::identify(muonMeas))
451 <<" @ surface "<<trackState.referenceSurface().geometryId());
453 if (muonMeas->numDimensions() == 0u) {
454 calibrateCombinedPrd(*ctx, *gctx, static_cast<const xAOD::CombinedMuonStrip*>(muonMeas),
455 trackState);
456 return;
457
458 }
459 const Amg::Vector3D trackPos{trackPars.position(geoctx)};
460 const Amg::Vector3D trackDir{trackPars.direction()};
461
462 switch (muonMeas->type()){
463 using enum xAOD::UncalibMeasType;
464 case MdtDriftCircleType: {
465 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(muonMeas);
466 MdtCalibInput calibInput{*dc, *gctx};
467 calibInput.setClosestApproach(trackPos);
468 //calibInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
469 calibInput.setTrackDirection(trackDir, true);
470 const double driftSign = m_MdtSignFromSegment ?
471 static_cast<double>(dec_trackSign(*dc)) :
472 Acts::copySign(1.,trackPars.parameters()[Acts::eBoundLoc0]);
473
475 if (ATH_LIKELY(muonMeas->numDimensions() == 1)) {
476 MdtCalibOutput calibOutput = m_mdtCalibrationTool->calibrate(*ctx, calibInput);
477 ATH_MSG_VERBOSE("Returned calibration object "<<calibOutput);
478 AmgVector(1) pos{AmgVector(1)::Zero()};
479 AmgSymMatrix(1) cov{AmgSymMatrix(1)::Identity()};
481 if (calibOutput.status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
482 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
483 <<std::endl<<calibInput<<std::endl<<calibOutput);
484 cov(Acts::eBoundLoc0,Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
485 } else {
486 pos[Acts::eBoundLoc0] = driftSign*calibOutput.driftRadius();
487 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.driftRadiusUncert(), 2);
488 }
490 }
492 else {
493 const auto* twinDC = static_cast<const xAOD::MdtTwinDriftCircle*>(muonMeas);
494 MdtCalibInput twinInput{twinDC->twinIdentify(), twinDC->twinAdc(), twinDC->twinTdc(), twinDC->readoutElement(), *gctx};
495 twinInput.setClosestApproach(trackPos);
496 twinInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
497
498 MdtCalibTwinOutput calibOutput = m_mdtCalibrationTool->calibrateTwinTubes(*ctx,
499 std::move(calibInput),
500 std::move(twinInput));
501 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
502 AmgSymMatrix(2) locCov{AmgSymMatrix(2)::Identity()};
503 if (calibOutput.primaryStatus() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
504 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
505 <<std::endl<<calibOutput);
506 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
507 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(0.5* dc->readoutElement()->activeTubeLength(dc->measurementHash()), 2);
508 } else {
509 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.uncertPrimaryR(), 2);
510 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(calibOutput.sigmaZ(), 2);
511 locPos[Acts::eBoundLoc0] = driftSign*calibOutput.primaryDriftR();
512 locPos[Acts::eBoundLoc1] = calibOutput.locZ();
513 }
515 }
516 break;
517 } case RpcStripType: {
518 const auto* rpcClust = static_cast<const xAOD::RpcMeasurement*>(muonMeas);
520 if (ATH_LIKELY(rpcClust->numDimensions() == 1)) {
521
522 if (!m_useRpcTime) {
523 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotNoTime
526 rpcClust->localPosition<1>(),
527 rpcClust->localCovariance<1>(), link, trackState);
528 } else {
529 AmgVector(2) measPars{AmgVector(2)::Zero()};
530 AmgSymMatrix(2) measCov{AmgSymMatrix(2)::Identity()};
531 measPars[0] = rpcClust->localPosition<1>()[0];
532 measCov(0,0) = rpcClust->localCovariance<1>()(0, 0);
533 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
534 measCov(1,1) = std::pow(m_rpcTimeResolution, 2);
535 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotWithTime
538 measPars, measCov, link, trackState);
539 }
540 }
542 else {
543 if (!m_useRpcTime) {
545 rpcClust->localPosition<2>(),
546 rpcClust->localCovariance<2>(), link, trackState);
547 } else {
548 AmgVector(3) measPars{AmgVector(3)::Zero()};
549 AmgSymMatrix(3) measCov{AmgSymMatrix(3)::Identity()};
550 measPars.block<2,1>(0,0) = xAOD::toEigen(rpcClust->localPosition<2>());
551 measCov.block<2,2>(0,0) = xAOD::toEigen(rpcClust->localCovariance<2>());
552 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
553 measCov(2,2) = std::pow(m_rpcTimeResolution, 2);
555 measPars, measCov, link, trackState);
556 }
557 }
558 break;
559 } case TgcStripType: {
560 const auto* tgcClust = static_cast<const xAOD::TgcStrip*>(muonMeas);
561 if (!m_useTgcTime) {
562 const auto proj = tgcClust->measuresPhi() ? ProjectorType::e1DimRotNoTime
565 tgcClust->localPosition<1>(),
566 tgcClust->localCovariance<1>(), link, trackState);
567 } else {
568 ATH_MSG_WARNING("Tgc time calibration to be implemented...");
569 }
570 break;
571 }
572 case MMClusterType: {
573 const auto* mmClust = static_cast<const xAOD::MMCluster*>(muonMeas);
574 std::pair<double, double> calibPosCov{calibrateMM(*ctx,* gctx, *mmClust, trackPos, trackDir)};
575 AmgVector(1) pos{AmgVector(1)(calibPosCov.first)};
576 AmgSymMatrix(1) cov{AmgSymMatrix(1)(calibPosCov.second)};
577
579 pos, cov, link, trackState);
580 break;
581 } case sTgcStripType: {
582 const auto* stgcClust = static_cast<const xAOD::sTgcMeasurement*>(muonMeas);
583
584 if(stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire) {
586 muonMeas->localPosition<1>(),
587 muonMeas->localCovariance<1>(), link, trackState);
588 } else if (stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad) {
590 stgcClust->localPosition<2>(),
591 stgcClust->localCovariance<2>(), link, trackState);
592 } else { // strips
593 const auto stgCluster = static_cast<const xAOD::sTgcStripCluster*>(muonMeas);
594 std::pair<double, double> calibPosCov{calibratesTGC(*ctx, *gctx, *stgCluster, std::nullopt, trackPos, trackDir)};
595 if(!m_usesTgcTime) {
596 AmgVector(1) pos{calibPosCov.first};
597 AmgSymMatrix(1) cov{calibPosCov.second};
599 pos, cov, link, trackState);
600 } else {
601 ATH_MSG_WARNING("sTGC time calibration to be implemented...");
602 AmgVector(2) pos{AmgVector(2)::Zero()};
603 AmgSymMatrix(2) cov{AmgSymMatrix(2)::Zero()};
604 pos[0] = calibPosCov.first;
605 pos[1] = stgCluster->time();
606 cov(0,0) = calibPosCov.second;
607 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
608 cov(1,1) = std::pow(25 /*ns*/, 2);
609
611 pos, cov, link, trackState);
612 }
613 }
614 break;
615 } case Other: {
617 auxCalibrator.calibrate(geoctx, cctx, link, trackState);
618 break;
619 } default: {
620 THROW_EXCEPTION("The parsed measurement is not a muon measurement. Please check.");
621 }
622 }
623 }
625 const auto [segPos, segLine] = makeLine(localSegmentPars(segment));
626 const Segment* detSeg = MuonR4::detailedSegment(segment);
627 for (const auto& meas : detSeg->measurements()) {
629 dec_trackSign(*meas->spacePoint()->primaryMeasurement()) =
630 SeedingAux::strawSign(segPos, segLine, *meas);
631 }
632 }
633 }
634
635 double SpacePointCalibrator::driftRadius(const Acts::CalibrationContext& cctx,
636 const CalibratedSpacePoint& spacePoint,
637 const double timeDelay) const {
639 const MuonCalib::MdtFullCalibData* calibConsts =
640 m_mdtCalibrationTool->getCalibConstants(*cctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
641 return calibConsts->rtRelation->rt()->radius(ActsTrk::timeToAthena(spacePoint.time() - timeDelay));
642 }
643 return 0.;
644 }
645
646 double SpacePointCalibrator::driftVelocity(const Acts::CalibrationContext& cctx,
647 const CalibratedSpacePoint& spacePoint,
648 const double timeDelay) const {
650 const MuonCalib::MdtFullCalibData* calibConsts =
651 m_mdtCalibrationTool->getCalibConstants(*cctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
652 return ActsTrk::velocityToActs(calibConsts->rtRelation->rt()->driftVelocity(ActsTrk::timeToAthena(spacePoint.time() - timeDelay)));
653 }
654 return 0.;
655 }
656 double SpacePointCalibrator::driftAcceleration(const Acts::CalibrationContext& cctx,
657 const CalibratedSpacePoint& spacePoint,
658 const double timeDelay) const {
660 const MuonCalib::MdtFullCalibData* calibConsts =
661 m_mdtCalibrationTool->getCalibConstants(*cctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
662 return ActsTrk::accelerationToActs(calibConsts->rtRelation->rt()->driftAcceleration(ActsTrk::timeToAthena(spacePoint.time() - timeDelay)));
663 }
664 return 0.;
665 }
666
667}
#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...
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 * 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.
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...
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
std::pair< Amg::Vector2D, AmgSymMatrix(2)> positionAndCovariance(const CombinedMuonStrip *combinedPrd)
Returns the position and covariance from a combined strip measurement.
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