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
22
24
27
28
29#include "Acts/Utilities/MathHelpers.hpp"
30#include "Acts/Utilities/Enumerate.hpp"
31
32
33namespace {
34 constexpr double c_inv = 1./ Gaudi::Units::c_light;
35 static const SG::Decorator<int> dec_trackSign{"segmentFitDriftSign"};
36}
37
38namespace MuonR4{
39 using namespace Acts::UnitLiterals;
43 using namespace SegmentFit;
44
46 ATH_CHECK(m_geoCtxKey.initialize());
47 ATH_CHECK(m_idHelperSvc.retrieve());
48 ATH_CHECK(m_mdtCalibrationTool.retrieve(EnableTool{m_idHelperSvc->hasMDT()}));
49 ATH_CHECK(m_nswCalibTool.retrieve(EnableTool{m_idHelperSvc->hasMM() || m_idHelperSvc->hasSTGC()}));
50 ATH_CHECK(detStore()->retrieve(m_detMgr));
51 return StatusCode::SUCCESS;
52 }
53
55 const Amg::Vector3D& trackDir,
56 CalibSpacePointVec& hitsToCalib) const {
57 std::vector<int> signs = SeedingAux::strawSigns(trackPos, trackDir,
58 hitsToCalib);
59 for (const auto [spIdx, sp]: Acts::enumerate(hitsToCalib)) {
60 sp->setDriftRadius(sp->driftRadius() * signs[spIdx]);
61 }
62 }
64 const CalibratedSpacePoint& spacePoint,
65 const Amg::Vector3D& segPos,
66 const Amg::Vector3D& segDir,
67 const double timeDelay) const {
68 CalibSpacePointPtr calibSP{};
69 if (spacePoint.type() != xAOD::UncalibMeasType::Other){
70 calibSP = calibrate(ctx, spacePoint.spacePoint(), segPos, segDir, timeDelay);
71 } else {
72 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint);
73 }
74 if (spacePoint.fitState() == State::Outlier) {
75 calibSP->setFitState(State::Outlier);
76 } else if (spacePoint.fitState() == State::Duplicate) {
77 calibSP->setFitState(State::Duplicate);
78 }
79 return calibSP;
80 }
81
82 CalibSpacePointVec SpacePointCalibrator::calibrate(const Acts::CalibrationContext& cctx,
83 const Amg::Vector3D& segPos,
84 const Amg::Vector3D& segDir,
85 const double timeDelay,
86 const CalibSpacePointVec& spacePoints) const {
87 CalibSpacePointVec newCalib{};
88 const EventContext* ctx = cctx.get<const EventContext*>();
89 newCalib.reserve(spacePoints.size());
90 for (const CalibSpacePointPtr& sp : spacePoints){
91 newCalib.emplace_back(calibrate(*ctx, *sp, segPos, segDir, timeDelay));
92 }
93 return newCalib;
94 }
95
97 const SpacePoint* spacePoint,
98 const Amg::Vector3D& posInChamb,
99 const Amg::Vector3D& dirInChamb,
100 const double timeOffset) const {
101
102 const ActsTrk::GeometryContext* gctx{nullptr};
103 if (!SG::get(gctx, m_geoCtxKey, ctx).isSuccess()) {
104 return nullptr;
105 }
106 const Amg::Vector3D& spPos{spacePoint->localPosition()};
107 const Amg::Transform3D& locToGlob{spacePoint->msSector()->localToGlobalTrans(*gctx)};
108 const Amg::Vector3D& chDir{spacePoint->sensorDirection()};
109
110 // Adjust the space point position according to the external seed. But only if the space point
111 // is a 1D strip
112 Amg::Vector3D calibSpPos = spacePoint->dimension() == 2 ? spPos
113 : spPos + Amg::intersect<3>(posInChamb, dirInChamb, spPos, chDir).value_or(0) * chDir;
114
115 SpacePoint::Cov_t cov = spacePoint->covariance();
116 CalibSpacePointPtr calibSP{};
117 ATH_MSG_VERBOSE("Calibrate "<<(*spacePoint) <<" -> updated pos "<<Amg::toString(calibSpPos));
118 switch (spacePoint->type()) {
120 const Amg::Vector3D locClosestApproach = posInChamb
121 + Amg::intersect<3>(spPos, chDir,
122 posInChamb, dirInChamb).value_or(0) * dirInChamb;
123
124 Amg::Vector3D closestApproach{locToGlob* locClosestApproach};
125 const double timeOfArrival = closestApproach.mag() * c_inv + timeOffset;
126
127 if (ATH_LIKELY(spacePoint->dimension() == 1)) {
128 auto* dc = static_cast<const xAOD::MdtDriftCircle*>(spacePoint->primaryMeasurement());
129 MdtCalibInput calibInput{*dc, *gctx};
130 calibInput.setTrackDirection(locToGlob.linear() * dirInChamb,
131 Acts::abs(dirInChamb.phi() - 90._degree) > 1.e-7 );
132 calibInput.setTimeOfFlight(timeOfArrival);
133 calibInput.setClosestApproach(std::move(closestApproach));
134 ATH_MSG_VERBOSE("Parse hit calibration "<<m_idHelperSvc->toString(dc->identify())<<", "<<calibInput);
135 MdtCalibOutput calibOutput = m_mdtCalibrationTool->calibrate(ctx, calibInput);
136 ATH_MSG_VERBOSE("Returned calibration object "<<calibOutput);
137 State fitState{State::Valid};
139 if (calibOutput.status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
140 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
141 <<std::endl<<calibInput<<std::endl<<calibOutput);
142 fitState = State::FailedCalib;
143 cov[Acts::toUnderlying(AxisDefs::etaCov)] = dc->readoutElement()->innerTubeRadius();
144 } else {
145 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(calibOutput.driftRadiusUncert());
146 }
147 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos), fitState);
148 calibSP->setCovariance(cov);
149 calibSP->setDriftRadius(calibOutput.driftRadius());
150 } else {
151 auto* dc = static_cast<const xAOD::MdtTwinDriftCircle*>(spacePoint->primaryMeasurement());
152 MdtCalibInput calibInput{*dc, *gctx};
153 calibInput.setClosestApproach(closestApproach);
154 calibInput.setTimeOfFlight(timeOfArrival);
155
156 MdtCalibInput twinInput{dc->twinIdentify(), dc->twinAdc(), dc->twinTdc(), dc->readoutElement(), *gctx};
157 twinInput.setClosestApproach(closestApproach);
158 twinInput.setTimeOfFlight(timeOfArrival);
159
160 MdtCalibTwinOutput calibOutput = m_mdtCalibrationTool->calibrateTwinTubes(ctx,
161 std::move(calibInput),
162 std::move(twinInput));
163
164 State fitState{State::Valid};
165 if (calibOutput.primaryStatus() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
166 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
167 <<std::endl<<calibOutput);
168 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(dc->readoutElement()->innerTubeRadius());
169 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(0.5* dc->readoutElement()->activeTubeLength(dc->measurementHash()));
170 fitState = State::FailedCalib;
171 } else {
172 cov[Acts::toUnderlying(AxisDefs::etaCov)] = Acts::square(calibOutput.uncertPrimaryR());
173 cov[Acts::toUnderlying(AxisDefs::phiCov)] = Acts::square(calibOutput.sigmaZ());
174 }
175 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos), fitState);
176 calibSP->setCovariance(cov);
177 calibSP->setDriftRadius(calibOutput.primaryDriftR());
178 }
179 break;
180 }
182 auto* strip = static_cast<const xAOD::RpcMeasurement*>(spacePoint->primaryMeasurement());
183
185 const Amg::Transform3D toGasGap{strip->readoutElement()->globalToLocalTrans(*gctx, strip->layerHash()) * locToGlob};
186 const Amg::Vector3D lPos = toGasGap * calibSpPos;
188 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
189
190 cov[Acts::toUnderlying(AxisDefs::timeCov)] = Acts::square(m_rpcTimeResolution);
191
192 const double time1 = strip->time()
193 - strip->readoutElement()->distanceToEdge(strip->layerHash(), lPos,
194 EdgeSide::readOut) /m_rpcSignalVelocity;
195
196 if (spacePoint->dimension() == 2) {
197 auto* strip2 = static_cast<const xAOD::RpcMeasurement*>(spacePoint->secondaryMeasurement());
198
199 const double time2 = strip2->time() -
200 strip2->readoutElement()->distanceToEdge(strip2->layerHash(),lPos, EdgeSide::readOut)/m_rpcSignalVelocity;
202 calibSP->setTimeMeasurement(0.5*(time1 + time2));
204 cov[Acts::toUnderlying(AxisDefs::timeCov)] += Acts::square(0.5*(time1 - time2));
205 }
206 calibSP->setCovariance(cov);
207 ATH_MSG_VERBOSE("Create rpc space point "<<m_idHelperSvc->toString(strip->identify())<<", dimension "<<spacePoint->dimension()
208 << ", at "<<Amg::toString(calibSP->localPosition())<<", uncalib time: "
209 <<strip->time()<<", calib time: "<<calibSP->time()<<" cov " <<calibSP->covariance());
210 break;
211 }
213 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
214 calibSP->setCovariance(cov);
215 break;
216 }
218 const xAOD::MMCluster* cluster = static_cast<const xAOD::MMCluster*>(spacePoint->primaryMeasurement());
219 Amg::Vector3D globalPos{locToGlob * posInChamb};
220 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
221
222 std::pair<double, double> calibPosCov {calibrateMM(ctx, *gctx, *cluster, globalPos, globalDir)};
223
224 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPosCov.first << " " << calibPosCov.second);
225 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibPosCov.second;
226 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTrans(*gctx, cluster->layerHash())};
227
228 // 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
229 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
230 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
231 calibSpPosInLayer.x() = calibPosCov.first;
232 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
233 calibSpPos = toChamberTrans * calibSpPosInLayer;
234
235 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
236 calibSP->setCovariance(cov);
237 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());
238
239 break;
240 }
242 const auto* cluster = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->primaryMeasurement());
243
244 // We do not apply any correction for pads or wire only space points
245 if (cluster->channelType() != sTgcIdHelper::sTgcChannelTypes::Strip) {
246 ATH_MSG_DEBUG("Calibrating an sTGC Pad or wire " << m_idHelperSvc->toString(cluster->identify()));
247 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
248 calibSP->setCovariance(cov);
249 break;
250 }
251
252 std::optional<double> posAlongTheStrip{std::nullopt};
253
254 // check if the space point is a strip/wire combination and take the position along the strip from the wire measurement
255 if(spacePoint->secondaryMeasurement()) {
256 const auto* secMeas = static_cast<const xAOD::sTgcMeasurement*>(spacePoint->secondaryMeasurement());
257 ATH_MSG_VERBOSE("Using secondary measurement "<< m_idHelperSvc->toString(secMeas->identify())<<" for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
258 posAlongTheStrip =static_cast<double>(spacePoint->secondaryMeasurement()->localPosition<1>()[0]);
259 } else {
260 ATH_MSG_VERBOSE("No secondary measurement for sTGC strip cluster " << m_idHelperSvc->toString(cluster->identify()));
261 }
262
263 Amg::Vector3D globalPos{locToGlob * posInChamb};
264 Amg::Vector3D globalDir{locToGlob.linear() * dirInChamb};
265
266 const auto* stripClus = static_cast<const xAOD::sTgcStripCluster*>(cluster);
267 const auto [calibPos, calibCov] = calibratesTGC(ctx, *gctx, *stripClus, posAlongTheStrip, globalPos, globalDir);
268
269 ATH_MSG_DEBUG("Calibrated pos and cov" << calibPos << " " << calibCov);
270 cov[Acts::toUnderlying(AxisDefs::etaCov)] = calibCov;
271 Amg::Transform3D toChamberTrans{ locToGlob.inverse() * cluster->readoutElement()->localToGlobalTrans(*gctx, cluster->layerHash())};
272
273 // 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
274 Amg::Vector3D calibSpPosInLayer = toChamberTrans.inverse() * calibSpPos;
275 ATH_MSG_DEBUG("in layer before calibration" << Amg::toString(calibSpPosInLayer));
276 calibSpPosInLayer.x() = calibPos;
277 ATH_MSG_DEBUG("in layer after calibration" << Amg::toString(calibSpPosInLayer));
278 calibSpPos = toChamberTrans * calibSpPosInLayer;
279
280 calibSP = std::make_unique<CalibratedSpacePoint>(spacePoint, std::move(calibSpPos));
281 calibSP->setCovariance(cov);
282 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());
283 break;
284 }
285
286 default:
287 ATH_MSG_WARNING("Do not know how to calibrate "<<m_idHelperSvc->toString(spacePoint->identify()));
288 }
289 return calibSP;
290 }
291
293 const std::vector<const SpacePoint*>& spacePoints,
294 const Amg::Vector3D& posInChamb,
295 const Amg::Vector3D& dirInChamb,
296 const double timeOffset) const {
297 CalibSpacePointVec calibSpacePoints{};
298 calibSpacePoints.reserve(spacePoints.size());
299 for(const SpacePoint* spacePoint : spacePoints) {
300 CalibSpacePointPtr hit = calibrate(ctx, spacePoint, posInChamb, dirInChamb, timeOffset);
301 if (hit) {
302 calibSpacePoints.push_back(std::move(hit));
303 }
304 }
305 return calibSpacePoints;
306 }
307 double SpacePointCalibrator::driftVelocity(const Acts::CalibrationContext& ctx,
308 const CalibratedSpacePoint& spacePoint) const {
310
311 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
312 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
313 return calibConsts->rtRelation->rt()->driftVelocity(driftTime.value_or(0.));
314 }
315 return 0.;
316 }
317 double SpacePointCalibrator::driftAcceleration(const Acts::CalibrationContext& ctx,
318 const CalibratedSpacePoint& spacePoint) const {
320 const MuonCalib::MdtFullCalibData* calibConsts = m_mdtCalibrationTool->getCalibConstants(*ctx.get<const EventContext*>(), spacePoint.spacePoint()->identify());
321 const std::optional<double> driftTime = calibConsts->rtRelation->tr()->driftTime(spacePoint.driftRadius());
322 return calibConsts->rtRelation->rt()->driftAcceleration(driftTime.value_or(0.));
323 }
324 return 0.;
325 }
326
327 std::pair<double, double> SpacePointCalibrator::calibrateMM(const EventContext& ctx,
328 const ActsTrk::GeometryContext& gctx,
329 const xAOD::MMCluster& cluster,
330 const Amg::Vector3D& globalPos,
331 const Amg::Vector3D& globalDir) const {
332 std::vector<NSWCalib::CalibratedStrip> calibClus;
333 StatusCode sc = m_nswCalibTool->calibrateClus(ctx, gctx, cluster, globalPos, calibClus);
334 if(sc.isFailure()) {
335 ATH_MSG_WARNING("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
336 return std::make_pair(0., 0.);
337 }
338
339 Amg::Vector2D locPos{cluster.localPosition<1>()[0] * Amg::Vector2D::UnitX()};
340 Amg::Vector3D locDir = Muon::NswClustering::toLocal(cluster.readoutElement()->globalToLocalTrans(gctx, cluster.layerHash()), globalDir);
341
342 Amg::MatrixX calibCov{};
343 calibCov.resize(1,1);
344 calibCov(0,0) = cluster.localCovariance<1>()(0, 0);
345 ATH_MSG_DEBUG("old loc pos " << locPos[0] << " old cov" << calibCov(0,0) );
346
347 Muon::IMMClusterBuilderTool::RIO_Author rotAuthor = m_clusterBuilderToolMM->getCalibratedClusterPosition(ctx, calibClus, locDir ,locPos, calibCov);
348 if(rotAuthor == Muon::IMMClusterBuilderTool::RIO_Author::unKnownAuthor){
349 THROW_EXCEPTION("Failed to calibrate MM cluster "<<m_idHelperSvc->toString(cluster.identify()));
350 }
351 ATH_MSG_DEBUG("new loc pos " << locPos[0] << " new cov" << calibCov(0,0) );
352 return std::make_pair(locPos[0], calibCov(0,0));
353 }
354
355 std::pair<double, double> SpacePointCalibrator::calibratesTGC(const EventContext& /*ctx*/,
356 const ActsTrk::GeometryContext& gctx,
357 const xAOD::sTgcStripCluster& cluster,
358 std::optional<double> posAlongTheStrip,
359 const Amg::Vector3D& globalPos,
360 const Amg::Vector3D& /*globalDir*/) const{
361
362 // if the second coordiante was not provided by the wire, take it from the seed track position
363 if(!posAlongTheStrip) {
364 Amg::Vector3D extPosLocal = cluster.readoutElement()->globalToLocalTrans(gctx, cluster.layerHash()) * globalPos;
365 posAlongTheStrip = extPosLocal[1];
366 }
367
368 // For now just copying over the local position and covariance. Eventually this should apply corrections from B-Lines and as build geometry
369
370 return std::make_pair(cluster.localPosition<1>()[0], cluster.localCovariance<1>()(0,0));
371 }
372 void SpacePointCalibrator::calibrateCombinedPrd(const EventContext& /*ctx*/,
373 const ActsTrk::GeometryContext& /*gctx*/,
374 const xAOD::CombinedMuonStrip* combinedPrd,
375 ActsTrk::MutableTrackContainer::TrackStateProxy state) const {
376 const auto sl = ActsTrk::detail::xAODUncalibMeasCalibrator::pack(combinedPrd);
377 if (combinedPrd->type() == xAOD::UncalibMeasType::RpcStripType) {
378 if (m_useRpcTime) {
379 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
380 }
381 Amg::Vector2D cmbPos{combinedPrd->primaryStrip()->localPosition<1>()[0],
382 combinedPrd->secondaryStrip()->localPosition<1>()[0]};
383 AmgSymMatrix(2) cmbCov{AmgSymMatrix(2)::Identity()};
384 cmbCov (0, 0) = combinedPrd->primaryStrip()->localCovariance<1>()(0,0);
385 cmbCov (1, 1) = combinedPrd->secondaryStrip()->localCovariance<1>()(0,0);
387
388
389 } else if (combinedPrd->type() == xAOD::UncalibMeasType::TgcStripType) {
390 if (m_useTgcTime) {
391 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<" Implement me");
392 }
393 const auto* wireMeas = static_cast<const xAOD::TgcStrip*>(combinedPrd->primaryStrip());
394 const auto* stripMeas = static_cast<const xAOD::TgcStrip*>(combinedPrd->secondaryStrip());
395
396 const auto& radialDesign = stripMeas->readoutElement()->stripLayout(stripMeas->layerHash());
397 const auto& wireDesign = wireMeas->readoutElement()->wireGangLayout(wireMeas->layerHash());
398
399 const double dirDots = radialDesign.stripDir(stripMeas->channelNumber()).dot(wireDesign.stripNormal());
401 AmgSymMatrix(2) stereoTrf{AmgSymMatrix(2)::Identity()};
402 const double invDist = 1. / (1. - Acts::square(dirDots));
403 stereoTrf(0, 0) = stereoTrf(1, 1) = invDist;
404 stereoTrf(0, 1) = stereoTrf(1, 0) = -dirDots * invDist;
405
406 Amg::Vector2D cmbPos{wireMeas->localPosition<1>()[0],
407 stripMeas->localPosition<1>()[0]};
408 AmgSymMatrix(2) cmbCov{AmgSymMatrix(2)::Identity()};
409 cmbCov (0, 0) = wireMeas->localCovariance<1>()(0,0);
410 cmbCov (1, 1) = stripMeas->localCovariance<1>()(0,0);
411
413 stereoTrf*cmbCov*stereoTrf.transpose(), sl, state);
414 } else {
415 THROW_EXCEPTION("Undefined uncalibrated measurement "
416 <<m_idHelperSvc->toString(xAOD::identify(combinedPrd)));
417 }
418 }
419 void SpacePointCalibrator::calibrateSourceLink(const Acts::GeometryContext& geoctx,
420 const Acts::CalibrationContext& cctx,
421 const Acts::SourceLink& link,
422 ActsTrk::MutableTrackContainer::TrackStateProxy trackState) const {
423
425 const Acts::BoundTrackParameters trackPars{trackState.referenceSurface().getSharedPtr(),
426 trackState.parameters(), trackState.covariance(),
427 Acts::ParticleHypothesis::muon()};
428
429
430 const auto* muonMeas = ActsTrk::detail::xAODUncalibMeasCalibrator::unpack(link);
431 const ActsTrk::GeometryContext* gctx = geoctx.get<const ActsTrk::GeometryContext*>();
432 const EventContext* ctx = cctx.get<const EventContext*>();
433 ATH_MSG_VERBOSE("Calibrate measurement "<<m_idHelperSvc->toString(xAOD::identify(muonMeas))
434 <<" @ surface "<<trackState.referenceSurface().geometryId());
436 if (muonMeas->numDimensions() == 0u) {
437 calibrateCombinedPrd(*ctx, *gctx, static_cast<const xAOD::CombinedMuonStrip*>(muonMeas),
438 trackState);
439 return;
440
441 }
442 const Amg::Vector3D trackPos{trackPars.position(geoctx)};
443 const Amg::Vector3D trackDir{trackPars.direction()};
444
445 switch (muonMeas->type()){
446 using enum xAOD::UncalibMeasType;
447 case MdtDriftCircleType: {
448 const auto* dc = static_cast<const xAOD::MdtDriftCircle*>(muonMeas);
449 MdtCalibInput calibInput{*dc, *gctx};
450 calibInput.setClosestApproach(trackPos);
451 //calibInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
452 calibInput.setTrackDirection(trackDir, true);
453 const double driftSign = m_MdtSignFromSegment ?
454 static_cast<double>(dec_trackSign(*dc)) :
455 sign(trackPars.parameters()[Acts::eBoundLoc0]);
456
458 if (ATH_LIKELY(muonMeas->numDimensions() == 1)) {
459 MdtCalibOutput calibOutput = m_mdtCalibrationTool->calibrate(*ctx, calibInput);
460 ATH_MSG_VERBOSE("Returned calibration object "<<calibOutput);
461 AmgVector(1) pos{AmgVector(1)::Zero()};
462 AmgSymMatrix(1) cov{AmgSymMatrix(1)::Identity()};
464 if (calibOutput.status() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
465 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
466 <<std::endl<<calibInput<<std::endl<<calibOutput);
467 cov(Acts::eBoundLoc0,Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
468 } else {
469 pos[Acts::eBoundLoc0] = driftSign*calibOutput.driftRadius();
470 cov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.driftRadiusUncert(), 2);
471 }
473 }
475 else {
476 const auto* twinDC = static_cast<const xAOD::MdtTwinDriftCircle*>(muonMeas);
477 MdtCalibInput twinInput{twinDC->twinIdentify(), twinDC->twinAdc(), twinDC->twinTdc(), twinDC->readoutElement(), *gctx};
478 twinInput.setClosestApproach(trackPos);
479 twinInput.setTimeOfFlight(trackPars.parameters()[Acts::eBoundTime]);
480
481 MdtCalibTwinOutput calibOutput = m_mdtCalibrationTool->calibrateTwinTubes(*ctx,
482 std::move(calibInput),
483 std::move(twinInput));
484 Amg::Vector2D locPos{Amg::Vector2D::Zero()};
485 AmgSymMatrix(2) locCov{AmgSymMatrix(2)::Identity()};
486 if (calibOutput.primaryStatus() != Muon::MdtDriftCircleStatus::MdtStatusDriftTime) {
487 ATH_MSG_DEBUG("Failed to create a valid hit from "<<m_idHelperSvc->toString(dc->identify())
488 <<std::endl<<calibOutput);
489 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(dc->readoutElement()->innerTubeRadius(), 2);
490 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(0.5* dc->readoutElement()->activeTubeLength(dc->measurementHash()), 2);
491 } else {
492 locCov(Acts::eBoundLoc0, Acts::eBoundLoc0) = std::pow(calibOutput.uncertPrimaryR(), 2);
493 locCov(Acts::eBoundLoc1, Acts::eBoundLoc1) = std::pow(calibOutput.sigmaZ(), 2);
494 locPos[Acts::eBoundLoc0] = driftSign*calibOutput.primaryDriftR();
495 locPos[Acts::eBoundLoc1] = calibOutput.locZ();
496 }
498 }
499 break;
500 } case RpcStripType: {
501 const auto* rpcClust = static_cast<const xAOD::RpcMeasurement*>(muonMeas);
503 if (ATH_LIKELY(rpcClust->numDimensions() == 1)) {
504
505 if (!m_useRpcTime) {
506 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotNoTime
509 rpcClust->localPosition<1>(),
510 rpcClust->localCovariance<1>(), link, trackState);
511 } else {
512 AmgVector(2) measPars{AmgVector(2)::Zero()};
513 AmgSymMatrix(2) measCov{AmgSymMatrix(2)::Identity()};
514 measPars[0] = rpcClust->localPosition<1>()[0];
515 measCov(0,0) = rpcClust->localCovariance<1>()(0, 0);
516 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
517 measCov(1,1) = std::pow(m_rpcTimeResolution, 2);
518 const auto proj = rpcClust->measuresPhi() ? ProjectorType::e1DimRotWithTime
521 measPars, measCov, link, trackState);
522 }
523 }
525 else {
526 if (!m_useRpcTime) {
528 rpcClust->localPosition<2>(),
529 rpcClust->localCovariance<2>(), link, trackState);
530 } else {
531 AmgVector(3) measPars{AmgVector(3)::Zero()};
532 AmgSymMatrix(3) measCov{AmgSymMatrix(3)::Identity()};
533 measPars.block<2,1>(0,0) = xAOD::toEigen(rpcClust->localPosition<2>());
534 measCov.block<2,2>(0,0) = xAOD::toEigen(rpcClust->localCovariance<2>());
535 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
536 measCov(2,2) = std::pow(m_rpcTimeResolution, 2);
538 measPars, measCov, link, trackState);
539 }
540 }
541 break;
542 } case TgcStripType: {
543 const auto* tgcClust = static_cast<const xAOD::TgcStrip*>(muonMeas);
544 if (!m_useTgcTime) {
545 const auto proj = tgcClust->measuresPhi() ? ProjectorType::e1DimRotNoTime
548 tgcClust->localPosition<1>(),
549 tgcClust->localCovariance<1>(), link, trackState);
550 } else {
551 ATH_MSG_WARNING("Tgc time calibration to be implemented...");
552 }
553 break;
554 }
555 case MMClusterType: {
556 const auto* mmClust = static_cast<const xAOD::MMCluster*>(muonMeas);
557 std::pair<double, double> calibPosCov{calibrateMM(*ctx,* gctx, *mmClust, trackPos, trackDir)};
558 AmgVector(1) pos{AmgVector(1)(calibPosCov.first)};
559 AmgSymMatrix(1) cov{AmgSymMatrix(1)(calibPosCov.second)};
560
562 pos, cov, link, trackState);
563 break;
564 } case sTgcStripType: {
565 const auto* stgcClust = static_cast<const xAOD::sTgcMeasurement*>(muonMeas);
566
567 if(stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Wire) {
569 muonMeas->localPosition<1>(),
570 muonMeas->localCovariance<1>(), link, trackState);
571
572 } else if(stgcClust->channelType() == sTgcIdHelper::sTgcChannelTypes::Pad) {
574 stgcClust->localPosition<2>(),
575 stgcClust->localCovariance<2>(), link, trackState);
576
577
578 } else { // strips
579 const auto stgCluster = static_cast<const xAOD::sTgcStripCluster*>(muonMeas);
580 std::pair<double, double> calibPosCov{calibratesTGC(*ctx, *gctx, *stgCluster, std::nullopt, trackPos, trackDir)};
581 if(!m_usesTgcTime) {
582 AmgVector(1) pos{calibPosCov.first};
583 AmgSymMatrix(1) cov{calibPosCov.second};
585 pos,
586 cov, link, trackState);
587 } else {
588 ATH_MSG_WARNING("sTGC time calibration to be implemented...");
589 AmgVector(2) pos{AmgVector(2)::Zero()};
590 AmgSymMatrix(2) cov{AmgSymMatrix(2)::Zero()};
591 pos[0] = calibPosCov.first;
592 pos[1] = stgCluster->time();
593 cov(0,0) = calibPosCov.second;
594 ATH_MSG_WARNING(__FILE__<<":"<<__LINE__<<"Please fix me using the ActsInterops package");
595 cov(1,1) = std::pow(25 /*ns*/, 2);
596
598 pos,
599 cov, link, trackState);
600 }
601 break;
602
603 }
604 THROW_EXCEPTION("sTGC measurements are not yet implemented");
605 break;
606 } default: {
607 THROW_EXCEPTION("The parsed measurement is not a muon measurement. Please check.");
608 }
609 }
610 }
612 const auto [segPos, segLine] = makeLine(localSegmentPars(segment));
613 const Segment* detSeg = MuonR4::detailedSegment(segment);
614 for (const auto& meas : detSeg->measurements()) {
616 dec_trackSign(*meas->spacePoint()->primaryMeasurement()) =
617 SeedingAux::strawSign(segPos, segLine, *meas);
618 }
619 }
620 }
621}
#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.
constexpr double sign(const double x)
Returns the sign of a number.
Definition MatrixUtils.h:11
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