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 CalibSpacePointPtr{};
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 // @TODO the constants could be converted to what is needed here (units, inverse) at initialization/construction time
201 // in particular 1/m_rpcSignalVelocity
202 cov[Acts::toUnderlying(AxisDefs::timeCov)] = Acts::square(ActsTrk::timeToActs(m_rpcTimeResolution.value()));
203
204 const double time1 = strip->time()
205 - strip->readoutElement()->distanceToEdge(strip->layerHash(), lPos,
206 EdgeSide::readOut) /m_rpcSignalVelocity;
207
208 if (spacePoint->dimension() == 2) {
209 auto* strip2 = static_cast<const xAOD::RpcMeasurement*>(spacePoint->secondaryMeasurement());
210
211 const double time2 = strip2->time() -
212 strip2->readoutElement()->distanceToEdge(strip2->layerHash(),lPos, EdgeSide::readOut)/m_rpcSignalVelocity;
214 calibSP->setTimeMeasurement(ActsTrk::timeToActs(0.5*(time1 + time2)));
216 cov[Acts::toUnderlying(AxisDefs::timeCov)] += Acts::square(ActsTrk::timeToActs(0.5*(time1 - time2)));
217 } else {
218 calibSP->setTimeMeasurement(ActsTrk::timeToActs(time1));
219 }
220 calibSP->setCovariance(cov);
221 ATH_MSG_VERBOSE("Create rpc space point "<<m_idHelperSvc->toString(strip->identify())<<", dimension "<<spacePoint->dimension()
222 << ", at "<<Amg::toString(calibSP->localPosition())<<", uncalib time: "
223 <<strip->time()<<", calib time: "<<ActsTrk::timeToAthena(calibSP->time())<<" cov " <<calibSP->covariance()
224 <<", time Uncert: "<<ActsTrk::timeToAthena(std::sqrt(calibSP->covariance()[Acts::toUnderlying(AxisDefs::timeCov)])));
225 break;
226 }
227 case TgcStripType: {
228 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
230 if (spacePoint->primaryMeasurement()->measuresPhi()) {
231 const auto* strip = static_cast<const xAOD::TgcStrip*>(spacePoint->primaryMeasurement());
232 const Amg::Transform3D toGasGap{strip->readoutElement()->globalToLocalTransform(*gctx, strip->layerHash()) * locToGlob};
233 const Amg::Vector3D lPos = toGasGap * calibSP->localPosition();
234 const auto& sensorPlane = strip->readoutElement()->sensorLayout(strip->layerHash());
235 const auto& radialDesign = strip->readoutElement()->stripLayout(strip->layerHash());
236 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(
237 radialDesign.stripPitch(strip->channelNumber(), sensorPlane->to2D(lPos,true))) / 12.;
238 }
239 calibSP->setCovariance(cov);
240 break;
241 }
242 case MMClusterType: {
243 const xAOD::MMCluster* cluster = static_cast<const xAOD::MMCluster*>(spacePoint->primaryMeasurement());
244 Amg::Vector3D globalPos{locToGlob * posInChamb};
245 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
246
247 std::pair<double, double> calibPosCov {calibrateMM(ctx, *gctx, *cluster, globalPos, globalDir)};
248
249 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPosCov.first << " " << calibPosCov.second);
250 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibPosCov.second;
251 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTransform(*gctx, cluster->layerHash())};
252
253 // 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
254 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
255 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
256 calibSpPosInLayer.x() = calibPosCov.first;
257 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
258 calibSpPos = toChamberTrans * calibSpPosInLayer;
259
260 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
261 calibSP->setCovariance(cov);
262 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());
263
264 break;
265 }
266 case sTgcStripType: {
267 const auto* cluster = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->primaryMeasurement());
268
269 // We do not apply any correction for pads or wire only space points
270 if (cluster->channelType() != sTgcIdHelper::sTgcChannelTypes::Strip) {
271 ATH_MSG_DEBUG("Calibrating an sTGC Pad or wire " << m_idHelperSvc->toString(cluster->identify()));
272 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
273 calibSP->setCovariance(cov);
274 break;
275 }
276
277 std::optional<double> posAlongTheStrip{std::nullopt};
278
279 // check if the space point is a strip/wire combination and take the position along the strip from the wire measurement
280 if(spacePoint->secondaryMeasurement()) {
281 const auto* secMeas = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->secondaryMeasurement());
282 ATH_MSG_VERBOSE("Using secondary measurement "<< m_idHelperSvc->toString(secMeas->identify())<<" for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
283 // Extract scalar value - use 2D for pads (2 dimensions), 1D for wires (1 dimension)
284 if (secMeas->numDimensions() == 2) {
285 posAlongTheStrip = static_cast<double>(secMeas->localPosition<2>()[0]);
286 } else {
287 posAlongTheStrip = static_cast<double>(secMeas->localPosition<1>()[0]);
288 }
289 } else {
290 ATH_MSG_VERBOSE("No secondary measurement for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
291 }
292
293 Amg::Vector3D globalPos{locToGlob * posInChamb};
294 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
295
296 const auto* stripClus = static_cast<const xAOD::sTgcStripCluster*>(cluster);
297 const auto [calibPos, calibCov] = calibratesTGC(ctx, *gctx, *stripClus, posAlongTheStrip, globalPos, globalDir);
298
299 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPos << " " << calibCov);
300 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibCov;
301 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTransform(*gctx, cluster->layerHash())};
302
303 // 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
304 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
305 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
306 calibSpPosInLayer.x() = calibPos;
307 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
308 calibSpPos = toChamberTrans * calibSpPosInLayer;
309
310 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
311 calibSP->setCovariance(cov);
312 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());
313 break;
314 }
315
316 default:
317 ATH_MSG_WARNING("Do not know how to calibrate "<<m_idHelperSvc->toString(spacePoint->identify()));
318 }
319 return calibSP;
320 }
321
323 const std::vector<const SpacePoint*>& spacePoints,
324 const Amg::Vector3D& posInChamb,
325 const Amg::Vector3D& dirInChamb,
326 const double timeDelay) const {
327 CalibSpacePointVec calibSpacePoints{};
328 calibSpacePoints.reserve(spacePoints.size());
329 for(const SpacePoint* spacePoint : spacePoints) {
330 CalibSpacePointPtr hit = calibrate(ctx, spacePoint, posInChamb, dirInChamb, timeDelay);
331 if (hit) {
332 calibSpacePoints.push_back(std::move(hit));
333 }
334 }
335 return calibSpacePoints;
336 }
337 double SpacePointCalibrator::driftVelocity(const Acts::CalibrationContext& ctx,
338 const CalibratedSpacePoint& spacePoint) const {
340
341 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
342 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
343 return ActsTrk::velocityToActs(calibConsts->rtRelation->rt()->driftVelocity(driftTime.value_or(0.)));
344 }
345 return 0.;
346 }
347 double SpacePointCalibrator::driftAcceleration(const Acts::CalibrationContext& ctx,
348 const CalibratedSpacePoint& spacePoint) const {
350 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
351 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
352 return ActsTrk::accelerationToActs(calibConsts->rtRelation->rt()->driftAcceleration(driftTime.value_or(0.)));
353 }
354 return 0.;
355 }
356
357 std::pair<double, double> SpacePointCalibrator::calibrateMM(const EventContext& ctx,
358 const ActsTrk::GeometryContext& gctx,
359 const xAOD::MMCluster& cluster,
360 const Amg::Vector3D& globalPos,
361 const Amg::Vector3D& globalDir) const {
362 std::vector<NSWCalib::CalibratedStrip> calibClus;
363 StatusCode sc = m_nswCalibTool->calibrateClus(ctx, gctx, cluster, globalPos, calibClus);
364 if(sc.isFailure()) {
365 ATH_MSG_WARNING("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
366 return std::make_pair(0., 0.);
367 }
368
369 Amg::Vector2D locPos{cluster.localPosition<1>()[0] * Amg::Vector2D::UnitX()};
370 Amg::Vector3D locDir = Muon::NswClustering::toLocal(cluster.readoutElement()->globalToLocalTransform(gctx, cluster.layerHash()), globalDir);
371
372 Amg::MatrixX calibCov{};
373 calibCov.resize(1,1);
374 calibCov(0,0) = cluster.localCovariance<1>()(0, 0);
375 ATH_MSG_DEBUG("old loc pos " << locPos[0] << " old cov" << calibCov(0,0) );
376
377 Muon::IMMClusterBuilderTool::RIO_Author rotAuthor = m_clusterBuilderToolMM->getCalibratedClusterPosition(ctx, calibClus, locDir ,locPos, calibCov);
378 if(rotAuthor == Muon::IMMClusterBuilderTool::RIO_Author::unKnownAuthor){
379 THROW_EXCEPTION("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
380 }
381 ATH_MSG_DEBUG("new loc pos " << locPos[0] << " new cov" << calibCov(0,0) );
382 return std::make_pair(locPos[0], calibCov(0,0));
383 }
384
385 std::pair<double, double> SpacePointCalibrator::calibratesTGC(const EventContext& /*ctx*/,
386 const ActsTrk::GeometryContext& gctx,
387 const xAOD::sTgcStripCluster& cluster,
388 std::optional<double> posAlongTheStrip,
389 const Amg::Vector3D& globalPos,
390 const Amg::Vector3D& /*globalDir*/) const{
391
392 // if the second coordiante was not provided by the wire, take it from the seed track position
393 if(!posAlongTheStrip) {
394 Amg::Vector3D extPosLocal = cluster.readoutElement()->globalToLocalTransform(gctx, cluster.layerHash()) * globalPos;
395 posAlongTheStrip = extPosLocal[1];
396 }
397
398 // For now just copying over the local position and covariance. Eventually this should apply corrections from B-Lines and as build geometry
399
400 return std::make_pair(cluster.localPosition<1>()[0], cluster.localCovariance<1>()(0,0));
401 }
402 void SpacePointCalibrator::calibrateCombinedPrd(const EventContext& ctx,
403 const ActsTrk::GeometryContext& gctx,
404 const xAOD::CombinedMuonStrip* combinedPrd,
405 ActsTrk::MutableTrackContainer::TrackStateProxy state) const {
406 const auto sl = ActsTrk::detail::xAODUncalibMeasCalibrator::pack(combinedPrd);
407
408 Amg::Vector2D cmbPos = xAOD::toEigen(combinedPrd->localPosition<2>());
409 AmgSymMatrix(2) cmbCov = xAOD::toEigen(combinedPrd->localCovariance<2>());
410 if (combinedPrd->type() == xAOD::UncalibMeasType::RpcStripType) {
411 if (m_useRpcTime) {
412 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
413 }
415
416 } else if (combinedPrd->type() == xAOD::UncalibMeasType::TgcStripType) {
417 if (m_useTgcTime) {
418 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
419 }
420
422 cmbPos, cmbCov, sl, state);
423
424 } else if(combinedPrd->type() == xAOD::UncalibMeasType::sTgcStripType) {
425 if (m_usesTgcTime) {
426 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
427 }
428 // combined sTGC Space points can be strip/wire, strip/pad or pad/wire combinations.
429 const auto* primMeas = static_cast<const xAOD::sTgcMeasurement*>(combinedPrd->primaryStrip());
430
431 if(primMeas->channelType() == sTgcIdHelper::sTgcChannelTypes::Strip) {
432 const auto* primStripMeas = static_cast<const xAOD::sTgcStripCluster*>(primMeas);
434 const Acts::BoundTrackParameters trackPars{state.referenceSurface().getSharedPtr(),
435 state.parameters(), state.covariance(),
436 Acts::ParticleHypothesis::muon()};
437 std::pair<double, double> calibPosCov{calibratesTGC(ctx, gctx, *primStripMeas, cmbPos[1] ,
438 trackPars.position(gctx.context()),
439 trackPars.direction())};
440 cmbPos[0] = calibPosCov.first;
441 cmbCov(0,0) = calibPosCov.second;
442 }
444
445 } else {
446 THROW_EXCEPTION("Undefined uncalibrated measurement "
447 <<m_idHelperSvc->toString(combinedPrd->identify()));
448 }
449 }
450 void SpacePointCalibrator::calibrateSourceLink(const Acts::GeometryContext& geoctx,
451 const Acts::CalibrationContext& cctx,
452 const Acts::SourceLink& link,
453 ActsTrk::MutableTrackContainer::TrackStateProxy trackState) const {
454
456 const Acts::BoundTrackParameters trackPars{trackState.referenceSurface().getSharedPtr(),
457 trackState.parameters(), trackState.covariance(),
458 Acts::ParticleHypothesis::muon()};
459
460
461 const auto* muonMeas = ActsTrk::detail::xAODUncalibMeasCalibrator::unpack(link);
462 const ActsTrk::GeometryContext* gctx = geoctx.get<const ActsTrk::GeometryContext*>();
463 const EventContext* ctx = cctx.get<const EventContext*>();
464 ATH_MSG_VERBOSE("Calibrate measurement "<<m_idHelperSvc->toString(xAOD::identify(muonMeas))
465 <<" @ surface "<<trackState.referenceSurface().geometryId());
467 if (muonMeas->numDimensions() == 0u) {
468 calibrateCombinedPrd(*ctx, *gctx, static_cast<const xAOD::CombinedMuonStrip*>(muonMeas),
469 trackState);
470 return;
471
472 }
473 const Amg::Vector3D trackPos{trackPars.position(geoctx)};
474 const Amg::Vector3D trackDir{trackPars.direction()};
475
476 switch (muonMeas->type()){
477 using enum xAOD::UncalibMeasType;
478 case MdtDriftCircleType: {
479 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(muonMeas);
480 MdtCalibInput calibInput{*dc, *gctx};
481 calibInput.setClosestApproach(trackPos);
482 //calibInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
483 calibInput.setTrackDirection(trackDir, true);
484 const double driftSign = m_MdtSignFromSegment ?
485 static_cast<double>(dec_trackSign(*dc)) :
486 Acts::copySign(1.,trackPars.parameters()[Acts::eBoundLoc0]);
487
489 if (ATH_LIKELY(muonMeas->numDimensions() == 1)) {
490 MdtCalibOutput calibOutput = m_mdtCalibrationTool->calibrate(*ctx, calibInput);
491 ATH_MSG_VERBOSE("Returned calibration object "<<calibOutput);
492 AmgVector(1) pos{AmgVector(1)::Zero()};
493 AmgSymMatrix(1) cov{AmgSymMatrix(1)::Identity()};
495 if (calibOutput.status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
496 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
497 <<std::endl<<calibInput<<std::endl<<calibOutput);
498 cov(Acts::eBoundLoc0,Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
499 } else {
500 pos[Acts::eBoundLoc0] = driftSign*calibOutput.driftRadius();
501 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.driftRadiusUncert(), 2);
502 }
504 }
506 else {
507 const auto* twinDC = static_cast<const xAOD::MdtTwinDriftCircle*>(muonMeas);
508 MdtCalibInput twinInput{twinDC->twinIdentify(), twinDC->twinAdc(), twinDC->twinTdc(), twinDC->readoutElement(), *gctx};
509 twinInput.setClosestApproach(trackPos);
510 twinInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
511
512 MdtCalibTwinOutput calibOutput = m_mdtCalibrationTool->calibrateTwinTubes(*ctx,
513 std::move(calibInput),
514 std::move(twinInput));
515 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
516 AmgSymMatrix(2) locCov{AmgSymMatrix(2)::Identity()};
517 if (calibOutput.primaryStatus() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
518 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
519 <<std::endl<<calibOutput);
520 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
521 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(0.5* dc->readoutElement()->activeTubeLength(dc->measurementHash()), 2);
522 } else {
523 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.uncertPrimaryR(), 2);
524 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(calibOutput.sigmaZ(), 2);
525 locPos[Acts::eBoundLoc0] = driftSign*calibOutput.primaryDriftR();
526 locPos[Acts::eBoundLoc1] = calibOutput.locZ();
527 }
529 }
530 break;
531 } case RpcStripType: {
532 const auto* rpcClust = static_cast<const xAOD::RpcMeasurement*>(muonMeas);
534 if (ATH_LIKELY(rpcClust->numDimensions() == 1)) {
535
536 if (!m_useRpcTime) {
537 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotNoTime
540 rpcClust->localPosition<1>(),
541 rpcClust->localCovariance<1>(), link, trackState);
542 } else {
543 AmgVector(2) measPars{AmgVector(2)::Zero()};
544 AmgSymMatrix(2) measCov{AmgSymMatrix(2)::Identity()};
545 measPars[0] = rpcClust->localPosition<1>()[0];
546 measCov(0,0) = rpcClust->localCovariance<1>()(0, 0);
547 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
548 measCov(1,1) = std::pow(m_rpcTimeResolution, 2);
549 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotWithTime
552 measPars, measCov, link, trackState);
553 }
554 }
556 else {
557 if (!m_useRpcTime) {
559 rpcClust->localPosition<2>(),
560 rpcClust->localCovariance<2>(), link, trackState);
561 } else {
562 AmgVector(3) measPars{AmgVector(3)::Zero()};
563 AmgSymMatrix(3) measCov{AmgSymMatrix(3)::Identity()};
564 measPars.block<2,1>(0,0) = xAOD::toEigen(rpcClust->localPosition<2>());
565 measCov.block<2,2>(0,0) = xAOD::toEigen(rpcClust->localCovariance<2>());
566 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
567 measCov(2,2) = std::pow(m_rpcTimeResolution, 2);
569 measPars, measCov, link, trackState);
570 }
571 }
572 break;
573 } case TgcStripType: {
574 const auto* tgcClust = static_cast<const xAOD::TgcStrip*>(muonMeas);
575 if (!m_useTgcTime) {
576 if (!tgcClust->measuresPhi()) {
578 tgcClust->localPosition<1>(),
579 tgcClust->localCovariance<1>(),
580 link, trackState);
581
582 } else {
583 const auto [pos, cov] = xAOD::positionAndCovariance(tgcClust);
585 pos, cov, link, trackState);
586
587 }
588 } else {
589 ATH_MSG_WARNING("Tgc time calibration to be implemented...");
590 }
591 break;
592 }
593 case MMClusterType: {
594 const auto* mmClust = static_cast<const xAOD::MMCluster*>(muonMeas);
595 std::pair<double, double> calibPosCov{calibrateMM(*ctx,* gctx, *mmClust, trackPos, trackDir)};
596 AmgVector(1) pos{AmgVector(1)(calibPosCov.first)};
597 AmgSymMatrix(1) cov{AmgSymMatrix(1)(calibPosCov.second)};
598
600 pos, cov, link, trackState);
601 break;
602 } case sTgcStripType: {
603 const auto* stgcClust = static_cast<const xAOD::sTgcMeasurement*>(muonMeas);
604
605 if(stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire) {
607 muonMeas->localPosition<1>(),
608 muonMeas->localCovariance<1>(), link, trackState);
609 } else if (stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad) {
611 stgcClust->localPosition<2>(),
612 stgcClust->localCovariance<2>(), link, trackState);
613 } else { // strips
614 const auto stgCluster = static_cast<const xAOD::sTgcStripCluster*>(muonMeas);
615 std::pair<double, double> calibPosCov{calibratesTGC(*ctx, *gctx, *stgCluster, std::nullopt, trackPos, trackDir)};
616 if(!m_usesTgcTime) {
617 AmgVector(1) pos{calibPosCov.first};
618 AmgSymMatrix(1) cov{calibPosCov.second};
620 pos, cov, link, trackState);
621 } else {
622 ATH_MSG_WARNING("sTGC time calibration to be implemented...");
623 AmgVector(2) pos{AmgVector(2)::Zero()};
624 AmgSymMatrix(2) cov{AmgSymMatrix(2)::Zero()};
625 pos[0] = calibPosCov.first;
626 pos[1] = stgCluster->time();
627 cov(0,0) = calibPosCov.second;
628 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
629 cov(1,1) = std::pow(25 /*ns*/, 2);
630
632 pos, cov, link, trackState);
633 }
634 }
635 break;
636 } case Other: {
638 auxCalibrator.calibrate(geoctx, cctx, link, trackState);
639 break;
640 } default: {
641 THROW_EXCEPTION("The parsed measurement is not a muon measurement. Please check.");
642 }
643 }
644 }
646 const auto [segPos, segLine] = makeLine(localSegmentPars(segment));
647 const Segment* detSeg = MuonR4::detailedSegment(segment);
648 for (const auto& meas : detSeg->measurements()) {
650 dec_trackSign(*meas->spacePoint()->primaryMeasurement()) =
651 SeedingAux::strawSign(segPos, segLine, *meas);
652 }
653 }
654 }
655
656 double SpacePointCalibrator::driftRadius(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 calibConsts->rtRelation->rt()->radius(ActsTrk::timeToAthena(spacePoint.time() - timeDelay));
663 }
664 return 0.;
665 }
666
667 double SpacePointCalibrator::driftVelocity(const Acts::CalibrationContext& cctx,
668 const CalibratedSpacePoint& spacePoint,
669 const double timeDelay) const {
671 const MuonCalib::MdtFullCalibData* calibConsts =
672 m_mdtCalibrationTool->getCalibConstants(*cctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
673 return ActsTrk::velocityToActs(calibConsts->rtRelation->rt()->driftVelocity(ActsTrk::timeToAthena(spacePoint.time() - timeDelay)));
674 }
675 return 0.;
676 }
677 double SpacePointCalibrator::driftAcceleration(const Acts::CalibrationContext& cctx,
678 const CalibratedSpacePoint& spacePoint,
679 const double timeDelay) const {
681 const MuonCalib::MdtFullCalibData* calibConsts =
682 m_mdtCalibrationTool->getCalibConstants(*cctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
683 return ActsTrk::accelerationToActs(calibConsts->rtRelation->rt()->driftAcceleration(ActsTrk::timeToAthena(spacePoint.time() - timeDelay)));
684 }
685 return 0.;
686 }
687
688}
#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.
Acts::CloneablePtr< 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 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 timeToAthena(T actsT)
Converts a time unit from Acts to Athena units.
constexpr auto timeToActs(T 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