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