ATLAS Offline Software
Loading...
Searching...
No Matches
ResidualPullCalculator.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6// ResidualPullCalculator.cxx
7// Source file for class ResidualPullCalculator
9// (c) ATLAS Detector software
11// Sebastian.Fleischmann@cern.ch
13
15
24#include <Eigen/Geometry>
25#include <algorithm>
26#include <cmath>
27
31Trk::ResidualPullCalculator::ResidualPullCalculator(const std::string& type, const std::string& name, const IInterface* parent)
32 : AthAlgTool(type,name,parent),
33m_SCTresidualTool("InDet::SCT_ResidualPullCalculator/SCT_ResidualPullCalculator"),
34m_RPCresidualTool("Muon::RPC_ResidualPullCalculator/RPC_ResidualPullCalculator"),
35m_TGCresidualTool("Muon::TGC_ResidualPullCalculator/TGC_ResidualPullCalculator"),
36m_idHelper(nullptr) {
37 declareInterface<IResidualPullCalculator>(this);
38 declareProperty("ResidualPullCalculatorForSCT", m_SCTresidualTool, "Tool to calculate residuals and pulls in the SCT (including module rotation)");
39 declareProperty("ResidualPullCalculatorForRPC", m_RPCresidualTool, "Tool to calculate residuals and pulls in the RPC (including phi/eta detection)");
40 declareProperty("ResidualPullCalculatorForTGC", m_TGCresidualTool, "Tool to calculate residuals and pulls in the SCT (including module rotation)");
41
42}
43
48
49 // ---------------------------------------
50 //Set up ATLAS ID helper to be able to identify the RIO's det-subsystem.
51 ATH_CHECK(detStore()->retrieve(m_idHelper, "AtlasID"));
52 // ----------------------------------
53 // get the SCT residual/pull calculator
54 if ( ! m_SCTresidualTool.empty() ) {
55 ATH_CHECK( m_SCTresidualTool.retrieve());
56 } else {
57 ATH_MSG_DEBUG ("No residual calculator for SCT given, will ignore SCT measurements!");
58 }
59
60 // ----------------------------------
61 // get the RPC residual/pull calculator
62 if ( ! m_RPCresidualTool.empty() ) {
63 ATH_CHECK( m_RPCresidualTool.retrieve());
64 } else {
65 ATH_MSG_DEBUG ("No residual calculator for RPC given, will ignore RPC measurements!");
66 }
67
68 // ----------------------------------
69 // get the TGC residual/pull calculator
70 if ( ! m_TGCresidualTool.empty() ) {
71 ATH_CHECK( m_TGCresidualTool.retrieve());
72 } else {
73 ATH_MSG_DEBUG ("No residual calculator for TGC given, will ignore TGC measurements!");
74 }
75
76 return StatusCode::SUCCESS;
77}
78
80 ATH_MSG_DEBUG ("starting finalize() in " << name());
81 return StatusCode::SUCCESS;
82}
83
85// calc residuals with determination of detector/MBase type
87std::array<double,5>
89 const Trk::MeasurementBase* measurement,
90 const Trk::TrackParameters* trkPar,
92 const Trk::TrackState::MeasurementType detType) const {
93
94 std::array<double,5> residuals{-999.,-999.,-999.,-999.,-999};
95 Trk::TrackState::MeasurementType measType = detType;
96 if (detType == Trk::TrackState::unidentified) {
98 measType = helper.defineType(measurement);
99 }
100 switch(measType) {
102 ATH_MSG_VERBOSE ("Pixel dim calculation ");
103 // calc residual and pull for the second coordinate, first coord postponed to 1-dim case
104 residuals[Trk::loc1] = measurement->localParameters()[Trk::loc1] - trkPar->parameters()[Trk::loc1];
105 residuals[Trk::loc2] = measurement->localParameters()[Trk::loc2] - trkPar->parameters()[Trk::loc2];
106 break;
111 ATH_MSG_VERBOSE ("One dim calculation ");
112 // 1-dim measurement
113 // calc residual and pull for the first coordinate
114 residuals[Trk::loc1] = measurement->localParameters()[Trk::loc1] - trkPar->parameters()[Trk::loc1];
115 break;
117 ATH_MSG_VERBOSE ("One dim calculation ");
118 // 1-dim measurement
119 // calc residual and pull for the first coordinate
120 if( measurement->localParameters().contains(Trk::loc1) )
121 residuals[Trk::loc1] = measurement->localParameters()[Trk::loc1] - trkPar->parameters()[Trk::loc1];
122 else
123 residuals[Trk::loc2] = measurement->localParameters()[Trk::loc2] - trkPar->parameters()[Trk::loc2];
124 break;
126 // special case, has to be handed down to the SCT tool
127 if ( ! m_SCTresidualTool.empty() ) {
128 ATH_MSG_VERBOSE ("Calling SCT tool ");
129 return m_SCTresidualTool->residuals(measurement, trkPar, resType, Trk::TrackState::SCT);
130 } else {
131 ATH_MSG_WARNING ("No SCT ResidualPullCalculator given, cannot calculate residual and pull for SCT measurement!");
132 }
133 break;
135 // special case, has to be handed down to the RPC tool
136 if ( ! m_RPCresidualTool.empty() ) {
137 ATH_MSG_VERBOSE ("Calling RPC tool ");
138 return m_RPCresidualTool->residuals(measurement, trkPar, resType, Trk::TrackState::RPC);
139 } else {
140 ATH_MSG_WARNING ("No RPC ResidualPullCalculator given, cannot calculate residual and pull for RPC measurement!");
141 }
142 break;
144 // special case, has to be handed down to the TGC tool
145 if ( ! m_TGCresidualTool.empty() ) {
146 ATH_MSG_VERBOSE ("Calling TGC tool ");
147 return m_TGCresidualTool->residuals(measurement, trkPar, resType, Trk::TrackState::TGC);
148 } else {
149 ATH_MSG_WARNING ("No TGC ResidualPullCalculator given, cannot calculate residual and pull for TGC measurement!");
150 }
151 break;
156 default:
157 ATH_MSG_VERBOSE ("Bit-key calculation ");
158 // PMs, Segments etc: use LocalParameters bit-key scheme
159 for (unsigned int i=0; i<5; ++i) {
161 if (measurement->localParameters().contains(iPar)) {
162 residuals[i] = measurement->localParameters()[iPar]
163 - trkPar->parameters()[iPar];
164 }
165 }
166 break;
167 }
168 return residuals;
169
170}
171
173// calc residual and pull with determination of detector/MBase type
175std::optional<Trk::ResidualPull> Trk::ResidualPullCalculator::residualPull(
176 const Trk::MeasurementBase* measurement,
177 const Trk::TrackParameters* trkPar,
179 const Trk::TrackState::MeasurementType detType) const {
180
181 if (!measurement || !trkPar) return std::nullopt;
182
183 // if no covariance for the track parameters is given the pull calculation is not valid
184 bool pullIsValid = trkPar->covariance();
185
186 Trk::TrackState::MeasurementType measType = detType;
187 if (detType == Trk::TrackState::unidentified) {
189 measType = helper.defineType(measurement);
190 }
191 unsigned int dimOfLocPars = (unsigned int)measurement->localParameters().dimension();
192 std::vector<double> residual(dimOfLocPars);
193 std::vector<double> pull(dimOfLocPars);
194
195 unsigned int iColRow=0;
196 ATH_MSG_VERBOSE ("Calculating residual for type " << measType << " dimension " << dimOfLocPars);
197
198 // do the calculations for the different detector types
199 switch(measType) {
201 ATH_MSG_VERBOSE ("Pixel dim calculation ");
202 // calc residual and pull for the second coordinate, first coord postponed to 1-dim case
203 residual[Trk::loc2] = measurement->localParameters()[Trk::loc2] - trkPar->parameters()[Trk::loc2];
204 if (pullIsValid) {
205 pull[Trk::loc2] = calcPull(residual[Trk::loc2],
206 measurement->localCovariance()(Trk::loc2,Trk::loc2),
207 (*trkPar->covariance())(Trk::loc2,Trk::loc2),
208 resType);
209 } else {
210 pull[Trk::loc2] = calcPull(residual[Trk::loc2],
211 measurement->localCovariance()(Trk::loc2,Trk::loc2),
212 0,
213 resType);
214 }
215 // do not break here, but also fill the first coordinate...
216 /* FALLTHROUGH */
222 ATH_MSG_VERBOSE ("One dim calculation ");
223 // 1-dim measurement
224 // calc residual and pull for the first coordinate
225 residual[Trk::loc1] = measurement->localParameters()[Trk::loc1] - trkPar->parameters()[Trk::loc1];
226 if (pullIsValid) {
227 pull[Trk::loc1] = calcPull(residual[Trk::loc1],
228 measurement->localCovariance()(Trk::loc1,Trk::loc1),
229 (*trkPar->covariance())(Trk::loc1,Trk::loc1),
230 resType);
231 } else {
232 pull[Trk::loc1] = calcPull(residual[Trk::loc1],
233 measurement->localCovariance()(Trk::loc1,Trk::loc1),
234 0,
235 resType);
236 }
237 break;
239 // special case, has to be handed down to the SCT tool
240 if ( ! m_SCTresidualTool.empty() ) {
241 ATH_MSG_VERBOSE ("Calling SCT tool ");
242 return m_SCTresidualTool->residualPull(measurement, trkPar, resType, Trk::TrackState::SCT);
243 } else {
244 ATH_MSG_WARNING ("No SCT ResidualPullCalculator given, cannot calculate residual and pull for SCT measurement!");
245 return std::nullopt;
246 }
247 break;
249 // special case, has to be handed down to the RPC tool
250 if ( ! m_RPCresidualTool.empty() ) {
251 ATH_MSG_VERBOSE ("Calling RPC tool ");
252 return m_RPCresidualTool->residualPull(measurement, trkPar, resType, Trk::TrackState::RPC);
253 } else {
254 ATH_MSG_WARNING ("No RPC ResidualPullCalculator given, cannot calculate residual and pull for RPC measurement!");
255 return std::nullopt;
256 }
257 break;
259 // special case, has to be handed down to the TGC tool
260 if ( ! m_TGCresidualTool.empty() ) {
261 ATH_MSG_VERBOSE ("Calling TGC tool ");
262 return m_TGCresidualTool->residualPull(measurement, trkPar, resType, Trk::TrackState::TGC);
263 } else {
264 ATH_MSG_WARNING ("No TGC ResidualPullCalculator given, cannot calculate residual and pull for TGC measurement!");
265 return std::nullopt;
266 }
267 break;
272 ATH_MSG_VERBOSE ("Bit-key calculation ");
273
274 // PMs, Segments etc: use LocalParameters bit-key scheme
275 for (unsigned int i=0; i<5; ++i) {
277 if (measurement->localParameters().contains(iPar)) {
278 residual[iColRow] = measurement->localParameters()[iPar]
279 - trkPar->parameters()[iPar];
280 if (pullIsValid)
281 pull[iColRow] = calcPull(residual[iColRow],
283 (*trkPar->covariance())(Trk::ParamDefsAccessor::pardef[iColRow],Trk::ParamDefsAccessor::pardef[iColRow]),
284 resType);
285 ++iColRow;
286 }
287 }
288 break;
289 default:
290 ATH_MSG_VERBOSE ("Default calculation ");
291 // use HEPvector to calculate the residual
292 // r = m - H.p
293 Amg::VectorX HEPresidual = measurement->localParameters() - (measurement->localParameters().expansionMatrix() * trkPar->parameters());
294 residual.resize(HEPresidual.rows());
295 pull.resize(HEPresidual.rows());
296 for (int i = 0; i < HEPresidual.rows(); i++) {
297 residual[i] = HEPresidual[i];
298 }
299
300 }
301 return std::make_optional<Trk::ResidualPull>(
302 std::move(residual), std::move(pull), pullIsValid, resType,
303 measurement->localParameters().parameterKey());
304}
305
307// calc residual and pull with determination of detector/MBase type
309std::optional<Trk::ResidualPull> Trk::ResidualPullCalculator::residualPull(
310 const Trk::MeasurementBase* measurement,
311 const Trk::TrackParameters* originalTrkPar,
314 const std::vector<const Trk::AlignmentEffectsOnTrack*>& aeots) const {
315
316 //bool veryVerbose = true;
317
318 Trk::TrackState::MeasurementType measType = detType;
319 if (detType == Trk::TrackState::unidentified) {
321 measType = helper.defineType(measurement);
322 }
323
324 // time to shift the parameter - do this rather than the measurement so we can call the original method.
325 Amg::Vector3D loc3Dframe;
326 Amg::Vector2D localPos;
327 Amg::Vector2D localPosSimple;
328 Amg::Vector3D globalPos;
329 AmgVector(5) parameters;
330
331 std::unique_ptr<Trk::TrackParameters> trkPar = originalTrkPar->uniqueClone();
332 parameters = trkPar->parameters();
333
334 ATH_MSG_VERBOSE( " ResidualPullCalculator aeots size " << aeots.size() << " parameters[0] " << parameters[0] );
335 double residual = measurement->localParameters()[Trk::loc1] - trkPar->parameters()[Trk::loc1];
336 ATH_MSG_VERBOSE(" parameters[0] "
337 << parameters[0] << " trkPar->parameters()[Trk::loc1] "
338 << trkPar->parameters()[Trk::loc1]
339 << " measurement->localParameters()[Trk::loc1] "
340 << measurement->localParameters()[Trk::loc1] << " resi "
341 << residual);
342
343 localPos[0] = parameters[0];
344 localPosSimple[0] = parameters[0];
345 for ( const auto & aeot : aeots ){
346 ATH_MSG_VERBOSE( " ResidualPullCalculator aeots deltaTranslation " << aeot->deltaTranslation() << " angle " << aeot->deltaAngle());
347
348 Trk::DistanceSolution solution = aeot->associatedSurface().straightLineDistanceEstimate(originalTrkPar->position(),originalTrkPar->momentum().unit());
349 double distance = solution.currentDistance(true);
350// calculate sign of distance
351 Amg::Vector3D displacementVector =
352 Amg::Vector3D(originalTrkPar->position().x() -
353 aeot->associatedSurface().center().x(),
354 originalTrkPar->position().y() -
355 aeot->associatedSurface().center().y(),
356 originalTrkPar->position().z() -
357 aeot->associatedSurface().center().z());
358 if (displacementVector.dot(originalTrkPar->momentum().unit()) < 0)
359 distance = -distance;
360
361 if(measType == Trk::TrackState::MDT) {
362// MDT
363 double distanceX = distance*originalTrkPar->momentum().unit().x();
364 double distanceY = distance*originalTrkPar->momentum().unit().y();
365 const double originalPhi=originalTrkPar->momentum().phi();
366 double distanceR = std::cos(originalPhi)*distanceX + std::sin(originalPhi)*distanceY; //< Is this quicker than hypotenuse?
367 ATH_MSG_VERBOSE(" originalTrkPar->position() x "
368 << originalTrkPar->position().x() << " y "
369 << originalTrkPar->position().y() << " z "
370 << originalTrkPar->position().z());
371 ATH_MSG_VERBOSE(" aeot->associatedSurface().center() x "
372 << aeot->associatedSurface().center().x() << " y "
373 << aeot->associatedSurface().center().y() << " z "
374 << aeot->associatedSurface().center().z());
375
376 // use drift (circle) derivatives as in TrkiPatFitterUtils
377
378 Amg::Vector3D sensorDirection = Amg::Vector3D(measurement->associatedSurface().transform().rotation().col(2));
379 Amg::Vector3D driftDirection = Amg::Vector3D(sensorDirection.cross(originalTrkPar->momentum().unit()));
380 driftDirection = driftDirection.unit();
381 ATH_MSG_VERBOSE( " cos(theta) " << std::cos(originalTrkPar->momentum().theta()) << " phi " << originalPhi );
382 ATH_MSG_VERBOSE( " sensorDirection x " << sensorDirection.x() << " y " << sensorDirection.y() << " z " << sensorDirection.z() );
383 ATH_MSG_VERBOSE( " driftDirection x " << driftDirection.x() << " y " << driftDirection.y() << " z " << driftDirection.z() );
384
385
386// Barrel
387 double projection = driftDirection.z();
388// dz because of a dhteta change: factor = dz/dtheta
389 const double originalTheta=originalTrkPar->momentum().theta();
390 const double sinOriginalTheta=std::sin(originalTheta);
391 double factor = (distanceR/sinOriginalTheta)/sinOriginalTheta; //preserve calc. order
392 const Surface& surface = aeot->associatedSurface();
393 ATH_MSG_VERBOSE( " fabs(surface.normal().z()) " << std::fabs(surface.normal().z()) );
394 if(std::fabs(surface.normal().z()) > 0.5) {
395// endcap
396 projection = (driftDirection.x()*surface.center().x() + driftDirection.y()*surface.center().y()) /
397 surface.center().perp();
398// dr because of a dhteta change : factor = dR/dtheta
399 factor = -(distanceR/std::sin(originalTheta))/(std::cos(originalTheta)); //preserve calc. order
400 ATH_MSG_VERBOSE( " distance " << distance << " Endcap projection " << projection << " factor " << factor );
401 } else {
402 ATH_MSG_VERBOSE( " distance " << distance << " Barrel projection " << projection << " factor " << factor );
403 }
404
405
406 localPos[0] += projection*aeot->deltaTranslation() - projection*factor*aeot->deltaAngle(); // Shift in precision direction.
407
408 ATH_MSG_VERBOSE( " MDT old localPos " << parameters[0] << " new localPos " << localPos[0] );
409
410 } else {
411
412// CSC or MM clusters
413
414 double projection = aeot->associatedSurface().normal().dot(originalTrkPar->momentum().unit());
415 localPos[0] += aeot->deltaTranslation()*projection + distance*aeot->deltaAngle();
416
417 ATH_MSG_VERBOSE(" CSC old localPos "
418 << parameters[0] << " distance " << distance
419 << " proj " << projection << " new localPos "
420 << localPos[0] << " simple " << localPosSimple[0]);
421 }
422 }
423
424 parameters[0] = localPos[0];
425 residual = measurement->localParameters()[Trk::loc1] - parameters[0];
426 ATH_MSG_VERBOSE( " new residual after end aeots loop " << residual );
427
428 // Set parameters to the new values;
429 const AmgSymMatrix(5)* originalCov = trkPar->covariance();
430 if(originalCov) {
431 trkPar->updateParameters(parameters, AmgSymMatrix(5)( *originalCov ) );
432 } else {
433 trkPar->updateParameters(parameters);
434 }
435
436 // Now call original method.
437 return residualPull(measurement, trkPar.get(), resType, detType );
438}
439
440
445 const double residual,
446 const double locMesCov,
447 const double locTrkCov,
448 const Trk::ResidualPull::ResidualType& resType ) const {
449
450 double CovarianceSum = 0.0;
451 if (resType == Trk::ResidualPull::Unbiased) {
452 CovarianceSum = locMesCov + locTrkCov;
453 } else if (resType == Trk::ResidualPull::Biased) {
454 CovarianceSum = locMesCov - locTrkCov;
455 } else CovarianceSum = locMesCov;
456
457 if (CovarianceSum <= 0.0) {
458 ATH_MSG_DEBUG("instable calculation: total covariance is non-positive, MeasCov = "<<
459 locMesCov<<", TrkCov = "<<locTrkCov<<", resType = "<<resType);
460 return 0.0;
461 }
462 return residual/sqrt(CovarianceSum);
463}
#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)
This class provides an interface to generate or decode an identifier for the upper levels of the dete...
#define AmgSymMatrix(dim)
#define AmgVector(rows)
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
Access to distance solutions.
double currentDistance(bool signedDist=false) const
Current distance to surface (spatial), signed (along/opposite to surface normal) if input argument tr...
int parameterKey() const
Identifier key for matrix expansion/reduction.
bool contains(ParamDefs par) const
The simple check for the clients whether the parameter is contained.
int dimension() const
Dimension of this localParameters() vector.
This class is the pure abstract base class for all fittable tracking measurements.
const LocalParameters & localParameters() const
Interface method to get the LocalParameters.
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
const Amg::MatrixX & localCovariance() const
Interface method to get the localError.
classifies a MeasurementBase into one of the known inherited flavours or one of the detector types fo...
const Amg::Vector3D & momentum() const
Access method for the momentum.
const Amg::Vector3D & position() const
Access method for the position.
std::unique_ptr< ParametersBase< DIM, T > > uniqueClone() const
clone method for polymorphic deep copy returning unique_ptr; it is not overriden, but uses the existi...
double calcPull(const double residual, const double locMesCov, const double locTrkCov, const Trk::ResidualPull::ResidualType &resType) const
calc pull in 1 dimension
ResidualPullCalculator(const std::string &type, const std::string &name, const IInterface *parent)
constructor
virtual StatusCode initialize() override final
initialize
virtual std::array< double, 5 > residuals(const Trk::MeasurementBase *measurement, const Trk::TrackParameters *trkPar, const Trk::ResidualPull::ResidualType resType, const Trk::TrackState::MeasurementType) const override final
This function is a light-weight version of the function above, designed for track fitters where speed...
const AtlasDetectorID * m_idHelper
Used to know the sub-det from PRD->identify().
ToolHandle< IResidualPullCalculator > m_SCTresidualTool
the ResidualPullCalculator for the SCT
virtual std::optional< Trk::ResidualPull > residualPull(const Trk::MeasurementBase *measurement, const Trk::TrackParameters *trkPar, const Trk::ResidualPull::ResidualType resType, const Trk::TrackState::MeasurementType) const override final
This function returns (creates!) a Trk::ResidualPull object, which contains the values of residual an...
ToolHandle< IResidualPullCalculator > m_TGCresidualTool
the ResidualPullCalculator for the TGC
virtual StatusCode finalize() override final
ToolHandle< IResidualPullCalculator > m_RPCresidualTool
the ResidualPullCalculator for the RPC
@ Biased
RP with track state including the hit.
@ Unbiased
RP with track state that has measurement not included.
Abstract Base Class for tracking surfaces.
virtual const Amg::Vector3D & normal() const
Returns the normal vector of the Surface (i.e.
const Amg::Transform3D & transform() const
Returns HepGeom::Transform3D by reference.
const Amg::Vector3D & center() const
Returns the center position of the Surface.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
Eigen::Matrix< double, Eigen::Dynamic, 1 > VectorX
Dynamic Vector - dynamic allocation.
MeasurementType
enum describing the flavour of MeasurementBase
ParamDefs
This file defines the parameter enums in the Trk namespace.
Definition ParamDefs.h:32
@ loc2
generic first and second local coordinate
Definition ParamDefs.h:35
@ loc1
Definition ParamDefs.h:34
static const double helper[9]
ParametersBase< TrackParametersDim, Charged > TrackParameters
static constexpr std::array< ParamDefs, 6 > pardef
Constructor.
Definition ParamDefs.h:94