56 const Acts::GeometryContext tgContext{gctx->
context()};
58 auto extrapolate = [&](
const Acts::BoundTrackParameters& start,
63 Amg::Vector3D::Zero(),
64 Amg::Vector3D::Zero());
67 trf.linear() *
sp.sensorDirection(),
68 start.position(tgContext),
72 n.dot(target.center(tgContext)));
76 <<
Amg::toString(start.direction())<<
" onto surface: "<<target.toString(tgContext)
78 <<
" geoId: "<<target.geometryId()<<
", "<<( lambda.value_or(0.) > 0 ?
"forward" :
"backward"));
81 ? Acts::Direction::Forward()
82 : Acts::Direction::Backward(), 100._m);
85 StatusCode retCode = StatusCode::SUCCESS;
87 SeedingAux::Config cfg{};
88 cfg.parsToUse.clear();
89 cfg.calcAlongStrip =
true;
92 cfg.calcAlongStrip =
false;
95 SeedingAux::Line_t line{};
96 SeedingAux::ChiSqWithDerivatives chiSqObj{};
106 segment->etaIndex());
109 Acts::ObjVisualization3D visualHelper{};
113 Acts::ViewConfig{.color = {220, 0, 0}});
117 if (
msgLvl(MSG::VERBOSE)) {
118 std::stringstream sstr{};
121 <<
", chi2/nDoF: "<<segment->chiSquared() / segment->numberDoF()
122 <<
", nDoF: "<<segment->numberDoF()<<
", "
123 <<segment->nPrecisionHits()<<
", "<<segment->nPhiLayers()<<std::endl;
125 sstr<<
" **** "<<(*meas)<<
", chi2: "<<SeedingAux::chi2Term(line, *meas)
126 <<
", sign: "<<(meas->isStraw() ?
127 (SeedingAux::strawSign(line, *meas) == 1 ?
"R" :
"L") :
"-")
130 : Acts::GeometryIdentifier{})
133 ATH_MSG_VERBOSE(__func__<<
"() "<<__LINE__<<
" - Run propagation test on "
137 if (!meas->spacePoint() ||
138 meas->fitState() != MuonR4::CalibratedSpacePoint::State::Valid) {
141 const auto sp = meas->spacePoint();
144 const auto& bounds = targetSurf.bounds();
145 Amg::Vector2D lPos{Amg::Vector2D::Zero()}, mPos{Amg::Vector2D::Zero()};
146 const Amg::Transform3D toSurf = targetSurf.localToGlobalTransform(tgContext).inverse() *
147 sector->
surface().localToGlobalTransform(tgContext);
148 if (targetSurf.type() == Acts::Surface::SurfaceType::Plane) {
149 lPos = (toSurf * SeedingAux::extrapolateToPlane(line, *meas)).block<2,1>(0,0);
150 if (!bounds.inside(lPos, Acts::BoundaryTolerance::AbsoluteEuclidean(-2._mm))){
152 <<
" is outside the trapezoid "<<bounds
156 mPos = (toSurf * meas->localPosition()).block<2,1>(0,0);
157 }
else if (targetSurf.type() == Acts::Surface::SurfaceType::Straw) {
158 const auto cIsect = lineIntersect<3>(meas->localPosition(), meas->sensorDirection(),
159 line.position(), line.direction());
160 const auto cIsectPos = cIsect.position();
162 lPos[0] = Acts::copySign(closePos.perp(), SeedingAux::strawSign(line, *meas));
163 lPos[1] = closePos.z();
164 mPos[0] = Acts::copySign(meas->driftRadius(), lPos[0]);
165 if (meas->measuresPhi()) {
166 mPos[1] = meas->localPosition().x();
168 const auto& lBounds =
static_cast<const Acts::LineBounds&
>(bounds);
169 if (std::abs(closePos.z()) > lBounds.get(Acts::LineBounds::eHalfLengthZ) - 2._cm ||
170 closePos.perp() >lBounds.get(Acts::LineBounds::eR) - 0.2_mm) {
177 auto extpPars = extrapolate(startPars, *
sp);
178 if (!extpPars.ok()) {
179 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - Failed to propagate to "<<(*meas)
180 <<
",\n lPos: "<<
Amg::toString(toSurf * meas->localPosition())
181 <<
", expected: "<<
Amg::toString(lPos)<<
", "<<targetSurf.bounds());
182 retCode = StatusCode::FAILURE;
188 Acts::ViewConfig{.color = {0, 0, 220}}, 6._cm);
192 pullCalculator.updateSpatialResidual(line, *meas);
193 pullCalculatorChi2.updateSpatialResidual(line, *meas);
194 pullCalculatorChi2.updateChiSq(chiSqObj, meas->covariance());
196 const double segChi2 = chiSqObj.chi2;
197 const double fastChi2Term = SeedingAux::chi2Term(line, *meas);
199 if (targetSurf.type() == Acts::Surface::SurfaceType::Plane) {
205 const Amg::Vector2D dPos = (*extpPars).localPosition() - lPos;
206 if (dPos.mag() > 0.1_mm) {
207 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - Too large deviation for "<<(*meas)
209 retCode = StatusCode::FAILURE;
212 const Amg::Vector3D b1 = toSurf.linear()*(meas->measuresEta() ? meas->toNextSensor() : meas->sensorDirection());
213 const Amg::Vector3D b2 = toSurf.linear()*(!meas->measuresEta() ? meas->toNextSensor() : meas->sensorDirection());
214 const Amg::Vector2D lineRes = (pullCalculator.residual()[etaIdx] * b1 +
215 pullCalculator.residual()[phiIdx] * b2).block<2,1>(0,0);
222 covMat(0,0) = meas->covariance()[etaIdx];
223 covMat(1,1) = meas->covariance()[phiIdx];
226 surfTrf.row(0) = b1.block<2,1>(0,0);
227 surfTrf.row(1) = b2.block<2,1>(0,0);
229 const double dirDots = b1.dot(b2);
230 const double invDist = 1. / (1. - Acts::square(dirDots));
231 stereoTrf(0, 0) = stereoTrf(1, 1) = invDist;
232 stereoTrf(0, 1) = stereoTrf(1, 0) = -dirDots * invDist;
234 stereoTrf = (stereoTrf * surfTrf).inverse();
238 <<
", invdist: "<<invDist<<
" -> trf: \n"<<stereoTrf
239 <<
",\ncovariance:\n"<<covMat
240 <<
" -> transformed:\n"<<(stereoTrf * covMat * stereoTrf.transpose()));
242 covMat = stereoTrf * covMat * stereoTrf.transpose();
244 const double matChi2 = surfRes.dot(covMat.inverse() * surfRes);
246 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - Analyze plane residual residual for "
248 <<
" / "<<targetSurf.geometryId()
253 <<
", chi2: "<<matChi2
254 <<
"\n --- line fitter - projected: "
260 if (dRes.mag() > 0.1_mm) {
261 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - Surface and line residuals are too much apart for "
264 retCode = StatusCode::FAILURE;
266 const double dChi2 = std::abs(matChi2 - segChi2);
268 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - Too large deviation in chi2 calculation "<<
269 (*meas)<<
" -- line fitter: "<<segChi2<<
", matrix: "<<matChi2);
270 retCode = StatusCode::FAILURE;
275 if (Acts::abs(segChi2 - fastChi2Term) > 1.e-3) {
276 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The fast & full chi2 calculations from ACTS don't match for "
277 <<(*meas)<<
" - full: "<<segChi2<<
", fast: "<<fastChi2Term);
278 retCode = StatusCode::FAILURE;
280 if (
sp->dimension() == 2) {
282 sp->secondaryMeasurement());
284 if ((xPos - mPos).
mag() > 1.e-3) {
285 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The calibrated position from the xAOD util function "<<
286 " does not match the expectation from this test. xAOD: "
288 retCode = StatusCode::FAILURE;
290 if (!xCov.isApprox(covMat, 1.e-3)) {
291 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The calibrated covariance from the xAOD util function "<<
292 " does not match the expectation from this test. xAOD:\n"
294 retCode = StatusCode::FAILURE;
298 pullCalculatorChi2.updateSpatialResidual(line, *
sp);
299 pullCalculatorChi2.updateChiSq(chiSqObj,
sp->covariance());
301 const bool mPhi =
sp->measuresPhi();
305 const Amg::Vector2D refPos = (toSurf *
sp->localPosition()).block<2,1>(0,0);
306 const double refCov =
sp->covariance()[!mPhi];
307 if ((xPos - refPos).
mag() > 1.e-3) {
308 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The calibrated position from the xAOD util function "<<
309 " does not match the expectation from this test. xAOD: "
311 retCode = StatusCode::FAILURE;
313 if (std::abs(refCov - xCov(mPhi,mPhi)) > 1.e-3) {
314 ATH_MSG_DEBUG(__func__<<
"() "<<__LINE__<<
" - The calibrated covariance from the xAOD util function "<<
315 " does not match the expectation from this test. xAOD: "
316 <<xCov(mPhi, mPhi)<<
", test: "<<refCov);
319 const double xAODChi2 = xAODRes.dot(xCov.inverse()*xAODRes);
321 if (std::abs(xAODChi2 - chiSqObj.chi2) > 1.e-3) {
322 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - The calculated chi2 term from the xAOD util function: "
323 <<xAODChi2<<
" deviates from the line fitter chi2: "<<chiSqObj.chi2
324 <<
"\n measurement: "<<xPos<<
", extp: "<<
Amg::toString(lPos)<<
" ("
325 <<
sp->measuresPhi()<<
") cov:\n"<<xCov
326 <<
"\n-> inverse:\n"<<xCov.inverse()
327 <<
"\n "<<
Amg::toString(pullCalculatorChi2.residual())<<
", xAOD: "
329 retCode = StatusCode::FAILURE;
332 }
else if (targetSurf.type() == Acts::Surface::SurfaceType::Straw) {
333 const double dist = lPos[0];
334 const double extDist = (*extpPars).parameters()[Acts::eBoundLoc0];
335 const double extLocZ = (*extpPars).parameters()[Acts::eBoundLoc1];
336 const double cov = meas->covariance()[Acts::toUnderlying(AxisDefs::etaCov)];
338 <<
" straight: "<<dist<<
", extrapolated: "<<extDist
339 <<
"--> "<<(extDist - dist ) / std::sqrt(cov)
340 <<
", along the tube: "<<lPos[1]<<
", extrapolated: "<<extLocZ);
341 if (std::abs(dist - extDist) / std::sqrt(cov) > 0.05 ||
342 std::abs(lPos[1] - extLocZ) > 0.1_mm) {
343 ATH_MSG_ERROR(__func__<<
"() "<<__LINE__<<
" - Too large deviation on "<<(*meas)
344 <<
",\n"<<
Amg::toString(lPos)<<
" vs. ("<<extDist<<
", "<<extLocZ<<
")"
345 <<
", deviate R: "<<(std::abs(dist -extDist) / std::sqrt(cov))
346 <<
", deviate Z: "<<std::abs(lPos[1] - extLocZ));
347 retCode = StatusCode::FAILURE;
352 visualHelper.write(std::format(
"ExtTpTest_{:}_{:}_{:}.obj",
353 ctx.eventID().event_number(), segment->index(),