ATLAS Offline Software
MdtSegmentFitter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
9 #include <GaudiKernel/PhysicalConstants.h>
11 #include <CxxUtils/sincos.h>
12 
13 #include <format>
14 /* * Residual strip hit: R= (P + <P-H|D>*D -H)
15  * dR
16  * --> -- dP = dP + <dP|D>*D
17  * dP
18  *
19  * dR
20  * -- dD = <P-H|D>dD + <P-H|dD>*D
21  * dD
22  *
23  * chi2 = <R|1./cov^{2} | R>
24  *
25  * dchi2 = <dR | 1./cov^{2} | R> + <R | 1./cov^{2} | dR>
26  */
27 namespace {
28  constexpr double c_inv = 1. / Gaudi::Units::c_light;
29  /* Cut off value for the determinant. Hessian matrices with a determinant smaller than this
30  are considered to be invalid */
31  constexpr double detCutOff = 1.e-8;
32 }
33 
34 namespace MuonR4{
35  using namespace SegmentFit;
38 
41  RangeArray rng{};
42  constexpr double spatRang = 10.*Gaudi::Units::m;
43  constexpr double timeTange = 25 * Gaudi::Units::ns;
44  rng[toInt(ParamDefs::y0)] = std::array{-spatRang, spatRang};
45  rng[toInt(ParamDefs::x0)] = std::array{-spatRang, spatRang};
48  rng[toInt(ParamDefs::time)] = std::array{-timeTange, timeTange};
49  return rng;
50  }
53  m_cfg{std::move(config)}{}
54 
55  inline void MdtSegmentFitter::updateDriftSigns(const Amg::Vector3D& segPos, const Amg::Vector3D& segDir,
56  SegmentFitResult& fitResult) const {
57  for (std::unique_ptr<CalibratedSpacePoint>& meas : fitResult.calibMeasurements) {
58  meas->setDriftRadius(SegmentFitHelpers::driftSign(segPos,segDir, *meas, msg())*meas->driftRadius());
59  }
60  }
61 
62  inline bool MdtSegmentFitter::recalibrate(const EventContext& ctx,
63  SegmentFitResult& fitResult) const{
64 
66  const auto [segPos, segDir] = makeLine(fitResult.segmentPars);
67 
68  fitResult.calibMeasurements = m_cfg.calibrator->calibrate(ctx, std::move(fitResult.calibMeasurements), segPos, segDir,
69  fitResult.segmentPars[toInt(ParamDefs::time)]);
70  if (!updateHitSummary(fitResult)){
71  return false;
72  }
73  updateDriftSigns(segPos, segDir, fitResult);
75  if (fitResult.timeFit && fitResult.nDoF <= 1) {
76  fitResult.timeFit = false;
77  ATH_MSG_DEBUG("Switch of the time fit because nDoF: "<<fitResult.nDoF);
78  fitResult.segmentPars[toInt(ParamDefs::time)] = 0.;
80  fitResult.calibMeasurements = m_cfg.calibrator->calibrate(ctx, std::move(fitResult.calibMeasurements), segPos, segDir,
81  fitResult.segmentPars[toInt(ParamDefs::time)]);
83  } else if (!fitResult.timeFit && m_cfg.doTimeFit) {
84  ATH_MSG_DEBUG("Somehow a measurement is on the narrow ridge of validity. Let's try if the time can be fitted now ");
85  fitResult.timeFit = true;
86  }
87 
88  return true;
89  }
90  inline bool MdtSegmentFitter::updateHitSummary(SegmentFitResult& fitResult) const {
93  fitResult.nPhiMeas = fitResult.nDoF = fitResult.nTimeMeas = 0;
94  for (const HitType& hit : fitResult.calibMeasurements) {
95  if (hit->fitState() != State::Valid){
96  continue;
97  }
98 
99  fitResult.nPhiMeas+= hit->measuresPhi();
100  fitResult.nDoF+= hit->measuresPhi();
101  fitResult.nDoF+= hit->measuresEta();
103  fitResult.nDoF += (m_cfg.doTimeFit && hit->type() != xAOD::UncalibMeasType::MdtDriftCircleType && hit->measuresTime());
104  fitResult.nTimeMeas+=hit->measuresTime();
105  }
106  if (!fitResult.nDoF) {
107  ATH_MSG_VERBOSE("Measurements rejected.");
108  return false;
109  }
110  if (!fitResult.nPhiMeas) {
111  ATH_MSG_VERBOSE("No phi measurements are left.");
112  fitResult.segmentPars[toInt(ParamDefs::phi)] = 90. * Gaudi::Units::deg;
113  fitResult.segmentPars[toInt(ParamDefs::x0)] = 0;
114  }
115 
116  fitResult.nDoF = fitResult.nDoF - 2 - (fitResult.nPhiMeas > 0 ? 2 : 0);
117 
118  return true;
119  }
121  const LineWithPartials& line,
122  const ParamDefs fitPar) {
123  const double normDot = normal.dot(line.dir);
124  switch (fitPar) {
125  case ParamDefs::phi:
126  case ParamDefs::theta:{
127  const double travelledDist = (offset - line.pos.dot(normal)) / normDot;
128  const double partialDist = - travelledDist / normDot * normal.dot(line.gradient[toInt(fitPar)]);
129  return travelledDist * line.gradient[toInt(fitPar)] + partialDist * line.dir;
130  break;
131  } case ParamDefs::y0:
132  case ParamDefs::x0:
133  return line.gradient[toInt(fitPar)] - line.gradient[toInt(fitPar)].dot(normal) / normDot * line.dir;
134  break;
135  default:
136  break;
137  }
138  return Amg::Vector3D::Zero();
139  }
140 
141 
144 
149  line.gradient[toInt(ParamDefs::x0)] = Amg::Vector3D::UnitX();
150  line.gradient[toInt(ParamDefs::y0)] = Amg::Vector3D::UnitY();
162  phi{params[toInt(ParamDefs::phi)]};
163  line.gradient[toInt(ParamDefs::theta)] = Amg::Vector3D{phi.cs*theta.cs, phi.sn*theta.cs, -theta.sn};
164  line.gradient[toInt(ParamDefs::phi)] = Amg::Vector3D{-theta.sn *phi.sn, theta.sn*phi.cs, 0};
165  /*********************************************************************************
166  * Non-vanishing second order derivatives
167  *
168  * d^{2} segDir d^{2} segDir cos phi
169  * ------------- = - segDir , ------------ = - sin(theta) sin phi
170  * d^{2} theta d^{2} phi 0
171  *
172  * d^{2} segDir -sin phi
173  * ------------- = cos(theta) cos phi
174  * d theta dPhi 0
175  ************************************************************************************/
176  constexpr unsigned nPars = LineWithPartials::nPars;
177  constexpr int idxThetaSq = vecIdxFromSymMat<nPars>(toInt(ParamDefs::theta), toInt(ParamDefs::theta));
178  constexpr int idxPhiSq = vecIdxFromSymMat<nPars>(toInt(ParamDefs::phi), toInt(ParamDefs::phi));
179  constexpr int idxPhiTheta = vecIdxFromSymMat<nPars>(toInt(ParamDefs::theta), toInt(ParamDefs::phi));
180  line.hessian[idxThetaSq] = - Amg::Vector3D{phi.cs*theta.sn,phi.sn*theta.sn, theta.cs};
181  line.hessian[idxPhiSq] = -theta.sn * Amg::Vector3D{phi.cs, phi.sn, 0.};
182  line.hessian[idxPhiTheta] = theta.cs * Amg::Vector3D{-phi.sn, phi.cs, 0.};
183  }
185  const CalibratedSpacePoint& hit,
186  ResidualWithPartials& measResidual) const {
188  const Amg::Vector3D& hitPos{hit.positionInChamber()};
189  const Amg::Vector3D& hitDir{hit.directionInChamber()};
191  const double planeProject = line.dir.dot(hitDir);
192  const double projDirLenSq = 1. - std::pow(planeProject, 2);
193  if (projDirLenSq < std::numeric_limits<float>::epsilon()) {
194  measResidual.residual.setZero();
195  for (Amg::Vector3D& grad : measResidual.gradient){
196  grad.setZero();
197  }
198  if (!m_cfg.useSecOrderDeriv) {
199  return;
200  }
201  for (Amg::Vector3D& hess : measResidual.hessian) {
202  hess.setZero();
203  }
204  ATH_MSG_WARNING("Segment is parallel along the wire");
205  return;
206  }
207  const double invProjLenSq = 1. / projDirLenSq;
208  const double invProjLen = std::sqrt(invProjLenSq);
210  const Amg::Vector3D projDir = (line.dir - planeProject*hitDir) * invProjLen;
212  const Amg::Vector3D hitMinSeg = hitPos - line.pos ;
214  const double lineDist = projDir.cross(hitDir).dot(hitMinSeg);
215  const double resVal = (lineDist - hit.driftRadius());
216  measResidual.residual = resVal * Amg::Vector3D::Unit(toInt(AxisDefs::eta));
217  ATH_MSG_VERBOSE("Mdt drift radius: "<<hit.driftRadius()<<" distance: "<<lineDist<<";"
218  <<Amg::signedDistance(hitPos, hitDir, line.pos, line.dir)<<", residual: "<<resVal);
221  if (hit.dimension() == 2) {
222  measResidual.residual[toInt(AxisDefs::phi)] = (hitMinSeg.dot(line.dir)*planeProject - hitMinSeg.dot(hitDir)) * invProjLenSq;
223  }
224  constexpr unsigned nLinePars = LineWithPartials::nPars;
226  auto partProjDir{make_array<Amg::Vector3D, nLinePars>(Amg::Vector3D::Zero())};
228  auto partPlaneProject{make_array<double, nLinePars>(0.)};
229 
231  for (const int param : {toInt(ParamDefs::y0), toInt(ParamDefs::x0),
233  if (!measResidual.evalPhiPars && (param == toInt(ParamDefs::x0) || param == toInt(ParamDefs::phi))){
234  continue;
235  }
236  switch (param) {
237  case toInt(ParamDefs::theta):
238  case toInt(ParamDefs::phi): {
239  partPlaneProject[param] = line.gradient[param].dot(hitDir);
240  partProjDir[param] = (line.gradient[param] - partPlaneProject[param]*hitDir) * invProjLen
241  + partPlaneProject[param]*planeProject* projDir * invProjLenSq;
242  const double partialDist = partProjDir[param].cross(hitDir).dot(hitMinSeg);
243 
244  measResidual.gradient[param] = partialDist * Amg::Vector3D::Unit(toInt(AxisDefs::eta));
245  if (hit.dimension() == 2) {
246  measResidual.gradient[param][toInt(AxisDefs::phi)] =
247  ( hitMinSeg.dot(line.gradient[param]) * planeProject +
248  hitMinSeg.dot(line.dir)*partPlaneProject[param]) * invProjLenSq
249  +2.* measResidual.residual[toInt(AxisDefs::phi)]*( planeProject * partPlaneProject[param]) * invProjLenSq;
250  }
251  break;
252  } case toInt(ParamDefs::y0):
253  case toInt(ParamDefs::x0): {
254  const double partialDist = - projDir.cross(hitDir).dot(line.gradient[param]);
255  measResidual.gradient[param] = partialDist * Amg::Vector3D::Unit(toInt(AxisDefs::eta));
256  if (hit.dimension() == 2) {
257  measResidual.gradient[param][toInt(AxisDefs::phi)] = -(line.gradient[param].dot(line.dir) * planeProject -
258  line.gradient[param].dot(hitDir)) * invProjLenSq;
259  }
260  break;
261  }
263  default:
264  break;
265  }
266  }
267  if (!m_cfg.useSecOrderDeriv) {
268  return;
269  }
271  for (int param = toInt(ParamDefs::phi); param >=0; --param){
272  if (!measResidual.evalPhiPars && (param == toInt(ParamDefs::x0) || param == toInt(ParamDefs::phi))){
273  continue;
274  }
275  for (int param1 = param; param1>=0; --param1) {
276  if (!measResidual.evalPhiPars && (param1 == toInt(ParamDefs::x0) || param1 == toInt(ParamDefs::phi))){
277  continue;
278  }
279  const int lineIdx = vecIdxFromSymMat<nLinePars>(param, param1);
280  const int resIdx = vecIdxFromSymMat<toInt(ParamDefs::nPars)>(param, param1);
282  if ( (param == toInt(ParamDefs::theta) || param == toInt(ParamDefs::phi)) &&
283  (param1 == toInt(ParamDefs::theta) || param1 == toInt(ParamDefs::phi))) {
284 
285  const double partSqLineProject = line.hessian[lineIdx].dot(hitDir);
286  const Amg::Vector3D projDirPartSq = (line.hessian[lineIdx] - partSqLineProject * hitDir) * invProjLen
287  + (partPlaneProject[param1] * planeProject) * invProjLenSq * partProjDir[param]
288  + (partPlaneProject[param] * planeProject) * invProjLenSq * partProjDir[param1]
289  + (partSqLineProject*planeProject) * invProjLenSq * projDir
290  + (partPlaneProject[param1] * partPlaneProject[param]) * std::pow(invProjLenSq, 2) * projDir;
291 
292  const double partialSqDist = projDirPartSq.cross(hitDir).dot(hitMinSeg);
293  measResidual.hessian[resIdx] = partialSqDist * Amg::Vector3D::Unit(toInt(AxisDefs::eta));
294  if (hit.dimension() == 2) {
295  const double partialSqAlongWire =2.*measResidual.residual[toInt(AxisDefs::phi)]*planeProject*partSqLineProject * invProjLenSq
296  +2.*measResidual.residual[toInt(AxisDefs::phi)]*partPlaneProject[param]*partPlaneProject[param1]*invProjLenSq
297  +2.*measResidual.gradient[param1][toInt(AxisDefs::phi)]*planeProject*partPlaneProject[param]*invProjLenSq
298  +2.*measResidual.gradient[param][toInt(AxisDefs::phi)]*planeProject*partPlaneProject[param1]*invProjLenSq
299  + hitMinSeg.dot(line.hessian[lineIdx]) *planeProject * invProjLenSq
300  + hitMinSeg.dot(line.dir)*partSqLineProject * invProjLenSq
301  + hitMinSeg.dot(line.gradient[param])*partPlaneProject[param1]*invProjLenSq
302  + hitMinSeg.dot(line.gradient[param1])*partPlaneProject[param]*invProjLenSq;
303  measResidual.hessian[resIdx][toInt(AxisDefs::phi)] = partialSqAlongWire;
304  }
305  }
307  else if (param == toInt(ParamDefs::theta) || param == toInt(ParamDefs::phi)){
308  const double partialSqDist = - partProjDir[param].cross(hitDir).dot(line.gradient[param1]);
309  measResidual.hessian[resIdx] = partialSqDist * Amg::Vector3D::Unit(toInt(AxisDefs::eta));
310  if (hit.dimension() == 2) {
311  const double partialSqAlongWire = -(line.gradient[param1].dot(line.gradient[param])*planeProject +
312  line.gradient[param1].dot(line.dir)*partPlaneProject[param]) * invProjLenSq
313  + 2.* measResidual.gradient[param1][toInt(AxisDefs::phi)]*( planeProject * partPlaneProject[param]) * invProjLenSq;
314  measResidual.hessian[resIdx][toInt(AxisDefs::phi)] = partialSqAlongWire;
315  }
316  }
317  }
318  }
319  }
321  const CalibratedSpacePoint& hit,
323 
324 
325  const Amg::Vector3D& hitPos{hit.positionInChamber()};
326  const Amg::Vector3D normal = hit.type() != xAOD::UncalibMeasType::Other
327  ? hit.spacePoint()->planeNormal() : Amg::Vector3D::UnitZ();
328  const double planeOffSet = normal.dot(hitPos);
329 
330  const double normDot = normal.dot(line.dir);
331  if (std::abs(normDot) < std::numeric_limits<double>::epsilon()){
332  residual.residual.setZero();
333  for (Amg::Vector3D& deriv: residual.gradient) {
334  deriv.setZero();
335  }
336  ATH_MSG_WARNING("The hit parallel with the segment line "<<Amg::toString(line.dir));
337  return;
338  }
339  const double travelledDist = (planeOffSet - line.pos.dot(normal)) / normDot;
340 
341  const Amg::Vector3D planeIsect = line.pos + travelledDist * line.dir;
343  residual.residual.block<2,1>(0,0) = (planeIsect - hitPos).block<2,1>(0,0);
344 
345  for (unsigned fitPar = 0; fitPar < line.gradient.size(); ++fitPar) {
346  switch (fitPar) {
347  case toInt(ParamDefs::phi):
348  case toInt(ParamDefs::theta):{
349  const double partialDist = - travelledDist / normDot * normal.dot(line.gradient[fitPar]);
350  residual.gradient[fitPar].block<2,1>(0,0) = (travelledDist * line.gradient[fitPar] + partialDist * line.dir).block<2,1>(0,0);
351  break;
352  } case toInt(ParamDefs::y0):
353  case toInt(ParamDefs::x0): {
354  residual.gradient[fitPar].block<2,1>(0,0) = (line.gradient[fitPar] - line.gradient[fitPar].dot(normal) / normDot * line.dir).block<2,1>(0,0);
355  break;
356  }
357  default: {
358  break;
359  }
360  }
361  }
362  if (!m_cfg.useSecOrderDeriv) {
363  return;
364  }
365  constexpr unsigned nLinePars = LineWithPartials::nPars;
366  for (int param = toInt(ParamDefs::phi); param >=0; --param){
367  for (int param1 = param; param1>=0; --param1) {
368  const int lineIdx = vecIdxFromSymMat<nLinePars>(param, param1);
369  const int resIdx = vecIdxFromSymMat<toInt(ParamDefs::nPars)>(param, param1);
370  if ( (param == toInt(ParamDefs::theta) || param == toInt(ParamDefs::phi)) &&
371  (param1 == toInt(ParamDefs::theta) || param1 == toInt(ParamDefs::phi))) {
372  residual.hessian[resIdx].block<2,1>(0,0) =(
373  travelledDist * line.hessian[lineIdx] - travelledDist *(normal.dot(line.hessian[lineIdx])) / normDot * line.dir
374  - normal.dot(line.gradient[param1]) / normDot * residual.gradient[param]
375  - normal.dot(line.gradient[param]) / normDot * residual.gradient[param1]).block<2,1>(0,0);
376  } else if (param == toInt(ParamDefs::theta) || param == toInt(ParamDefs::phi)) {
377  const double gradientDisplace = normal.dot(line.gradient[param1]);
378  if (gradientDisplace > std::numeric_limits<float>::epsilon()){
379  residual.hessian[resIdx].block<2,1>(0,0) = gradientDisplace*( normal.dot(line.gradient[param]) / std::pow(normDot,2)*line.dir
380  - line.gradient[param] / normDot ).block<2,1>(0,0);
381  } else {
382  residual.hessian[resIdx].setZero();
383  }
384  }
385  }
386  }
387  }
388 
390  HitVec&& calibHits,
391  const Parameters& startPars,
392  const Amg::Transform3D& localToGlobal) const {
393 
394  const Muon::IMuonIdHelperSvc* idHelperSvc{calibHits[0]->spacePoint()->msSector()->idHelperSvc()};
396 
397  if (msgLvl(MSG::VERBOSE)) {
398  std::stringstream hitStream{};
399  const auto [startPos, startDir] = makeLine(startPars);
400  for (const HitType& hit : calibHits) {
401  hitStream<<" **** "<<(hit->type() != xAOD::UncalibMeasType::Other ? idHelperSvc->toString(hit->spacePoint()->identify()): "beamspot" )
402  <<" position: "<<Amg::toString(hit->positionInChamber());
403  if (hit->type() == xAOD::UncalibMeasType::MdtDriftCircleType) {
404  hitStream<<", driftRadius: "<<SegmentFitHelpers::driftSign(startPos,startDir, *hit, msg())*hit->driftRadius() ;
405  }
406  hitStream<<", channel dir: "<<Amg::toString(hit->directionInChamber())<<std::endl;
407  }
408  ATH_MSG_VERBOSE("Start segment fit with parameters "<<toString(startPars)
409  <<", plane location: "<<Amg::toString(localToGlobal)<<std::endl<<hitStream.str());
410 
411  }
412 
413  SegmentFitResult fitResult{};
414  fitResult.segmentPars = startPars;
415  fitResult.timeFit = m_cfg.doTimeFit;
416  fitResult.calibMeasurements = std::move(calibHits);
417  if (!updateHitSummary(fitResult)) {
418  ATH_MSG_WARNING("No valid segment seed parsed from the beginning");
419  return fitResult;
420  }
421  if (!m_cfg.reCalibrate) {
422  const auto [segPos, segDir] = makeLine(startPars);
423  updateDriftSigns(segPos, segDir, fitResult);
424  }
425  Parameters gradient{AmgVector(5)::Zero()}, prevGrad{AmgVector(5)::Zero()}, prevPars{AmgVector(5)::Zero()};
426  AmgSymMatrix(5) hessian{AmgSymMatrix(5)::Zero()};
427 
429  LineWithPartials segmentLine{};
432 
433  unsigned int noChangeIter{0};
434  while (fitResult.nIter++ < m_cfg.nMaxCalls) {
435  ATH_MSG_VERBOSE("Iteration: "<<fitResult.nIter<<" parameters: "<<toString(fitResult.segmentPars)<<"chi2: "<<fitResult.chi2);
437  updateLinePartials(fitResult.segmentPars, segmentLine);
438 
440  if (m_cfg.reCalibrate && !recalibrate(ctx, fitResult)) {
441  break;
442  }
444  fitResult.chi2 = 0;
445  hessian.setZero();
446  gradient.setZero();
447 
449  for (const HitType& hit : fitResult.calibMeasurements) {
450  if (hit->fitState() != State::Valid) {
451  continue;
452  }
453  const Amg::Vector3D& hitPos{hit->positionInChamber()};
454  const Amg::Vector3D& hitDir{hit->directionInChamber()};
455  ATH_MSG_VERBOSE("Update chi2 from measurement "<<(hit->spacePoint() ? idHelperSvc->toString(hit->spacePoint()->identify())
456  : "pseudo meas")<<" position: "<<Amg::toString(hitPos)<<" + "<<Amg::toString(hitDir));
457 
459  const int start = toInt(fitResult.nPhiMeas ? ParamDefs::phi : ParamDefs::theta);
460  switch (hit->type()) {
462  calculateWireResiduals(segmentLine, *hit, residual);
463  break;
464  }
467  const Amg::Vector3D normal = hit->spacePoint()->planeNormal();
468  const double planeOffSet = normal.dot(hit->positionInChamber());
469  const Amg::Vector3D planeIsect = segmentLine.pos
470  + Amg::intersect<3>(segmentLine.pos, segmentLine.dir, normal, planeOffSet).value_or(0)* segmentLine.dir;
471 
473  residual.residual.block<2,1>(0,0) = (hitPos - planeIsect).block<2,1>(0,0);
474 
475  if (fitResult.timeFit && hit->measuresTime()) {
477  const double totFlightDist = (localToGlobal * planeIsect).mag();
478  residual.residual[toInt(AxisDefs::t0)] = hit->time() - totFlightDist * c_inv - fitResult.segmentPars[toInt(ParamDefs::time)];
479  }
480 
481  for (int p = start; p >= 0; --p) {
482  const ParamDefs par{static_cast<ParamDefs>(p)};
483  residual.gradient[toInt(par)].block<2,1>(0, 0) = - partialPlaneIntersect(normal, planeOffSet, segmentLine, par).block<2,1>(0,0);
484 
485  if (fitResult.timeFit && hit->measuresTime()) {
486  residual.gradient[toInt(par)][toInt(AxisDefs::t0)] = -residual.gradient[toInt(par)].perp() * c_inv;
487  }
488  ATH_MSG_VERBOSE("Partial derivative of "<<idHelperSvc->toString(hit->spacePoint()->identify())
489  <<" residual "<<Amg::toString(residual.residual)<<" "<<
490  Amg::toString(multiply(inverse(hit->covariance()), residual.residual))
491  <<" "<<std::endl<<toString(hit->covariance())<<std::endl<<" w.r.t "<<toString(par)<<"="
492  <<Amg::toString(residual.gradient[toInt(par)]));
493 
494  }
495  if (fitResult.timeFit && hit->measuresTime()) {
496  constexpr ParamDefs par = ParamDefs::time;
497  residual.gradient[toInt(par)] = -Amg::Vector3D::Unit(toInt(AxisDefs::t0));
498  ATH_MSG_VERBOSE("Partial derivative of "<<idHelperSvc->toString(hit->spacePoint()->identify())
499  <<" residual "<<Amg::toString(residual.residual)<<" w.r.t "<<toString(par)<<"="
500  <<Amg::toString(residual.gradient[toInt(par)]));
501  }
502  break;
504  static const Amg::Vector3D normal = Amg::Vector3D::UnitZ();
505  const double planeOffSet = normal.dot(hit->positionInChamber());
506  const Amg::Vector3D planeIsect = segmentLine.pos +
507  Amg::intersect<3>(segmentLine.pos, segmentLine.dir, normal, planeOffSet).value_or(0)* segmentLine.dir;
508 
509  residual.residual.block<2,1>(0,0) = (hitPos - planeIsect).block<2,1>(0,0);
510  residual.residual[toInt(AxisDefs::t0)] =0.;
511  for (int p = start; p >= 0; --p) {
512  const ParamDefs par{static_cast<ParamDefs>(p)};
513  residual.gradient[toInt(par)].block<2,1>(0, 0) = - partialPlaneIntersect(normal, planeOffSet, segmentLine, par).block<2,1>(0,0);
514 
515  residual.gradient[toInt(par)][toInt(AxisDefs::t0)] = 0;
516  ATH_MSG_VERBOSE("Partial derivative of "<<idHelperSvc->toString(hit->spacePoint()->identify())
517  <<" residual "<<Amg::toString(residual.residual)<<" w.r.t "<<toString(par)<<"="
518  <<Amg::toString(residual.gradient[toInt(par)]));
519 
520  }
521  break;
522  } default:
523  const auto &measurement = *hit->spacePoint()->primaryMeasurement();
524  ATH_MSG_WARNING("MdtSegmentFitter() - Unsupported measurment type" <<typeid(measurement).name());
525  }
526 
527  ATH_MSG_VERBOSE("Update derivatives for hit "<< (hit->spacePoint() ? idHelperSvc->toString(hit->spacePoint()->identify()) : "beamspot"));
528  updateDerivatives(residual, hit->covariance(), gradient, hessian, fitResult.chi2,
529  fitResult.timeFit && hit->measuresTime() ? toInt(ParamDefs::time) : start);
530  }
531 
533  for (int k =1; k < 5 - (!fitResult.timeFit); ++k){
534  for (int l = 0; l< k; ++l){
535  hessian(l,k) = hessian(k,l);
536  }
537  }
539  if (gradient.mag() < m_cfg.tolerance) {
540  fitResult.converged = true;
541  ATH_MSG_VERBOSE("Fit converged after "<<fitResult.nIter<<" iterations with "<<fitResult.chi2);
542  break;
543  }
544  ATH_MSG_VERBOSE("Chi2: "<<fitResult.chi2<<", gradient: "<<Amg::toString(gradient)<<"hessian: "<<std::endl<<hessian);
547  if (!fitResult.nPhiMeas && !fitResult.timeFit) {
548  paramUpdate = updateParameters<2>(fitResult.segmentPars, prevPars, gradient, prevGrad, hessian);
549  } else if (!fitResult.nPhiMeas && fitResult.timeFit) {
552  hessian.col(2).swap(hessian.col(toInt(ParamDefs::time)));
553  hessian.row(2).swap(hessian.row(toInt(ParamDefs::time)));
554  std::swap(gradient[2], gradient[toInt(ParamDefs::time)]);
555  std::swap(fitResult.segmentPars[2], fitResult.segmentPars[toInt(ParamDefs::time)]);
556 
557  paramUpdate = updateParameters<3>(fitResult.segmentPars, prevPars, gradient, prevGrad, hessian);
558 
559  std::swap(fitResult.segmentPars[2], fitResult.segmentPars[toInt(ParamDefs::time)]);
560  hessian.col(2).swap(hessian.col(toInt(ParamDefs::time)));
561  hessian.row(2).swap(hessian.row(toInt(ParamDefs::time)));
562  std::swap(gradient[2], gradient[toInt(ParamDefs::time)]);
563  } else if (fitResult.nPhiMeas && !fitResult.timeFit) {
564  paramUpdate = updateParameters<4>(fitResult.segmentPars, prevPars, gradient, prevGrad, hessian);
565  } else if (fitResult.nPhiMeas && fitResult.timeFit) {
566  paramUpdate = updateParameters<5>(fitResult.segmentPars, prevPars, gradient, prevGrad, hessian);
567  }
568  if (paramUpdate == UpdateStatus::noChange) {
569  if ((++noChangeIter) >= m_cfg.noMoveIter){
570  fitResult.converged = true;
571  break;
572  }
573  } else if (paramUpdate == UpdateStatus::allOkay) {
574  noChangeIter = 0;
575  } else if (paramUpdate == UpdateStatus::outOfBounds){
576  return fitResult;
577  }
578  }
579 
581  fitResult.nDoF-=fitResult.timeFit;
582 
584  const auto [segPos, segDir] = fitResult.makeLine();
585  fitResult.chi2 =0.;
586 
587  std::optional<double> toF = fitResult.timeFit ? std::make_optional<double>((localToGlobal * segPos).mag() * c_inv) : std::nullopt;
589  std::ranges::stable_sort(fitResult.calibMeasurements, [](const HitType&a, const HitType& b){
590  return a->positionInChamber().z() < b->positionInChamber().z();
591  });
592 
593  /*** Remove the drift sign again */
594  fitResult.chi2 =0.;
595  for (const HitType& hit : fitResult.calibMeasurements) {
596  hit->setDriftRadius(std::abs(hit->driftRadius()));
597  fitResult.chi2 +=SegmentFitHelpers::chiSqTerm(segPos, segDir, fitResult.segmentPars[toInt(ParamDefs::time)], toF, *hit, msg());
598  }
600  if (!fitResult.nPhiMeas&& !fitResult.timeFit) {
601  blockCovariance<2>(std::move(hessian), /* std::move(gradient), std::move(prevGrad), */ fitResult.segmentParErrs);
602  }else if (!fitResult.nPhiMeas && fitResult.timeFit) {
603  hessian.col(2).swap(hessian.col(toInt(ParamDefs::time)));
604  hessian.row(2).swap(hessian.row(toInt(ParamDefs::time)));
605  blockCovariance<3>(std::move(hessian),/* std::move(gradient), std::move(prevGrad), */ fitResult.segmentParErrs);
606  fitResult.segmentParErrs.col(2).swap(fitResult.segmentParErrs.col(toInt(ParamDefs::time)));
607  fitResult.segmentParErrs.row(2).swap(fitResult.segmentParErrs.row(toInt(ParamDefs::time)));
608  } else if (fitResult.nPhiMeas) {
609  blockCovariance<4>(std::move(hessian), /* std::move(gradient), std::move(prevGrad), */ fitResult.segmentParErrs);
610  } else if (fitResult.nPhiMeas && fitResult.timeFit) {
611  blockCovariance<5>(std::move(hessian),/* std::move(gradient), std::move(prevGrad), */ fitResult.segmentParErrs);
612  }
613  return fitResult;
614  }
615 
617  const MeasCov_t& covariance,
618  AmgVector(5)& gradient, AmgSymMatrix(5)& hessian,
619  double& chi2, int startPar) const {
620  const MeasCov_t invCov{inverse(covariance)};
621  const Amg::Vector3D covRes = multiply(invCov, fitMeas.residual);
622  chi2 += covRes.dot(fitMeas.residual);
623  for (int p = startPar; p >=0 ; --p) {
624  gradient[p] +=2.*covRes.dot(fitMeas.gradient[p]);
625  for (int k=p; k>=0; --k) {
626  hessian(p,k)+= 2.*contract(invCov, fitMeas.gradient[p], fitMeas.gradient[k]);
627  if (m_cfg.useSecOrderDeriv) {
628  const int symMatIdx = vecIdxFromSymMat<ResidualWithPartials::nPars>(p,k);
629  hessian(p,k)+=contract(invCov, covRes, fitMeas.hessian[symMatIdx]);
630  }
631  }
632  }
633  ATH_MSG_VERBOSE("After derivative update --- chi2: "<<chi2<<"("<<covRes.dot(fitMeas.residual)<<"), gradient: "
634  <<toString(gradient)<<", Hessian:\n"<<hessian<<", measurement covariance\n"<<toString(invCov));
635  }
636 
637  template <unsigned int nDim>
639  SegmentFit::Covariance& covariance) const {
640 
641  covariance.setIdentity();
642  AmgSymMatrix(nDim) miniHessian = hessian.block<nDim, nDim>(0,0);
643  if (std::abs(miniHessian.determinant()) <= detCutOff) {
644  ATH_MSG_VERBOSE("Boeser mini hessian ("<<miniHessian.determinant()<<")\n"<<miniHessian<<"\n\n"<<hessian);
645  return;
646  }
647  ATH_MSG_VERBOSE("Hessian matrix: \n"<<hessian<<",\nblock Hessian:\n"<<miniHessian<<",\n determinant: "<<miniHessian.determinant());
648  covariance.block<nDim,nDim>(0,0) = miniHessian.inverse();
649  ATH_MSG_VERBOSE("covariance: \n"<<covariance);
650  }
651 
652  template <unsigned int nDim>
655  Parameters& currGrad, Parameters& prevGrad,
656  const AmgSymMatrix(5)& currentHessian) const {
657 
658  AmgSymMatrix(nDim) miniHessian = currentHessian.block<nDim, nDim>(0,0);
659  ATH_MSG_VERBOSE("Parameter update -- \ncurrenPars: "<<toString(currPars)<<", \ngradient: "<<toString(currGrad)
660  <<", hessian ("<<miniHessian.determinant()<<")"<<std::endl<<miniHessian);
661 
662  double changeMag{0.};
663  if (std::abs(miniHessian.determinant()) > detCutOff) {
664  prevPars.block<nDim,1>(0,0) = currPars.block<nDim,1>(0,0);
665  // Update the parameters accrodingly to the hessian
666  const AmgVector(nDim) updateMe = miniHessian.inverse()* currGrad.block<nDim, 1>(0,0);
667  changeMag = std::sqrt(updateMe.dot(updateMe));
668  currPars.block<nDim,1>(0,0) -= updateMe;
669  prevGrad.block<nDim,1>(0,0) = currGrad.block<nDim,1>(0,0);
670  ATH_MSG_VERBOSE("Hessian inverse:\n"<<miniHessian.inverse()<<"\n\nUpdate the parameters by -"
671  <<Amg::toString(updateMe));
672  } else {
673  const AmgVector(nDim) gradDiff = (currGrad - prevGrad).block<nDim,1>(0,0);
674  const double gradDiffMag = gradDiff.mag2();
675  double denom = (gradDiffMag > std::numeric_limits<float>::epsilon() ? gradDiffMag : 1.);
676  const double gamma = std::abs((currPars - prevPars).block<nDim,1>(0,0).dot(gradDiff))
677  / denom;
678  ATH_MSG_VERBOSE("Hessian determinant invalid. Try deepest descent - \nprev parameters: "
679  <<toString(prevPars)<<",\nprevious gradient: "<<toString(prevGrad)<<", gamma: "<<gamma);
680  prevPars.block<nDim, 1>(0,0) = currPars.block<nDim, 1>(0,0);
681  currPars.block<nDim, 1>(0,0) -= gamma* currGrad.block<nDim, 1>(0,0);
682  prevGrad.block<nDim, 1>(0,0) = currGrad.block<nDim,1>(0,0);
683  changeMag = std::abs(gamma) * currGrad.block<nDim, 1>(0,0).mag();
684  }
686  unsigned int nOutOfBound{0};
687  for (unsigned int p =0; p< nDim; ++p) {
688  if (m_cfg.ranges[p][0] > currPars[p] || m_cfg.ranges[p][1]< currPars[p]) {
689  ATH_MSG_VERBOSE("The "<<p<<"-th parameter "<<toString(static_cast<ParamDefs>(p))<<" is out of range "<<currPars[p]
690  <<"["<<m_cfg.ranges[p][0]<<"-"<<m_cfg.ranges[p][1]<<"]");
691  ++nOutOfBound;
692  }
693  currPars[p] = std::clamp(currPars[p], m_cfg.ranges[p][0], m_cfg.ranges[p][1]);
694  }
695  if (nOutOfBound > m_cfg.nParsOutOfBounds){
697  }
698  if (changeMag <= m_cfg.tolerance) {
699  return UpdateStatus::noChange;
700  }
701  return UpdateStatus::allOkay;
702  }
703 }
MuonR4::MdtSegmentFitter::ResidualWithPartials::residual
Amg::Vector3D residual
Vector carrying the residual.
Definition: MdtSegmentFitter.h:73
MuonR4::MdtSegmentFitter::updateDriftSigns
void updateDriftSigns(const Amg::Vector3D &segPos, const Amg::Vector3D &segDir, SegmentFitResult &fitRes) const
Update the signs of the measurement.
Definition: MdtSegmentFitter.cxx:55
MuonR4::SegmentFit::ParamDefs
ParamDefs
This file defines the parameter enums in the Trk namespace.
Definition: MuonHoughDefs.h:29
checkFileSG.line
line
Definition: checkFileSG.py:75
MuonR4::MdtSegmentFitter::blockCovariance
void blockCovariance(const AmgSymMatrix(5)&hessian, SegmentFit::Covariance &covariance) const
Definition: MdtSegmentFitter.cxx:638
MuonR4::MdtSegmentFitter::updateHitSummary
bool updateHitSummary(SegmentFitResult &fitResult) const
Brief updates the hit summary from the contributing hits.
Definition: MdtSegmentFitter.cxx:90
MuonR4::MdtSegmentFitter::calculateStripResiduals
void calculateStripResiduals(const LineWithPartials &line, const CalibratedSpacePoint &spacePoint, ResidualWithPartials &residual) const
Calculates the residual together with hte correspdonding derivatives for strip measurements.
Definition: MdtSegmentFitter.cxx:320
python.SystemOfUnits.m
int m
Definition: SystemOfUnits.py:91
MuonR4::MdtSegmentFitter::LineWithPartials::nPars
static constexpr unsigned nPars
Free parameters of the line (x0,y0,theta,phi)
Definition: MdtSegmentFitter.h:56
MuonR4::MdtSegmentFitter::ResidualWithPartials
Helper struct carrying the residual with its derivatives.
Definition: MdtSegmentFitter.h:67
MuonR4::MdtSegmentFitter::UpdateStatus
UpdateStatus
Definition: MdtSegmentFitter.h:163
ClusterSeg::residual
@ residual
Definition: ClusterNtuple.h:20
MuonR4::multiply
Amg::Vector3D multiply(const CalibratedSpacePoint::Covariance_t &mat, const Amg::Vector3D &v)
Multiplies a 3D vector with the covariance matrix which can be either 2x2 or 3x3 matrix.
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/UtilFunctions.cxx:40
MuonR4::MdtSegmentFitter::Parameters
SegmentFit::Parameters Parameters
Definition: MdtSegmentFitter.h:22
MuonR4::SegmentFitResult::calibMeasurements
HitVec calibMeasurements
Calibrated measurements used in the fit.
Definition: SegmentFitterEventData.h:64
mergePhysValFiles.start
start
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:14
MuonR4::MdtSegmentFitter::UpdateStatus::outOfBounds
@ outOfBounds
MuonR4::SpacePoint::planeNormal
Amg::Vector3D planeNormal() const
Returns the vector pointing out of the measurement plane.
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:128
Amg::y
@ y
Definition: GeoPrimitives.h:35
sincos.h
Helper to simultaneously calculate sin and cos of the same angle.
deg
#define deg
Definition: SbPolyhedron.cxx:17
MuonR4::HitVec
SpacePointPerLayerSorter::HitVec HitVec
Definition: SpacePointPerLayerSorter.cxx:9
ISpacePointCalibrator.h
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
MuonR4::ISpacePointCalibrator::calibrate
virtual CalibSpacePointPtr calibrate(const EventContext &ctx, const SpacePoint *spacePoint, const Amg::Vector3D &seedPosInChamb, const Amg::Vector3D &seedDirInChamb, const double timeDelay) const =0
Calibrates a single space point.
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
MuonR4::MdtSegmentFitter::Config::noMoveIter
unsigned int noMoveIter
How many iterations with changes below tolerance.
Definition: MdtSegmentFitter.h:42
D3PDTest::rng
uint32_t rng()
Definition: FillerAlg.cxx:40
MuonR4::SegmentFitHelpers::chiSqTerm
double chiSqTerm(const Amg::Vector3D &posInChamber, const Amg::Vector3D &dirInChamber, const SpacePoint &measurement, MsgStream &msg)
Calculates the chi2 contribuation to a linear segment line from an uncalibrated measurement.
Definition: SegmentFitHelperFunctions.cxx:28
MuonR4::SegmentFit::makeLine
std::pair< Amg::Vector3D, Amg::Vector3D > makeLine(const Parameters &pars)
Returns the parsed parameters into an Eigen line parametrization.
Definition: SegmentFitterEventData.cxx:26
ParamDefs.h
MuonR4::MdtSegmentFitter::Config::tolerance
double tolerance
Gradient cut off.
Definition: MdtSegmentFitter.h:30
MuonR4::toString
std::string toString(const CalibratedSpacePoint::Covariance_t &mat)
Returns the matrix in string.
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/UtilFunctions.cxx:75
MuonR4::MdtSegmentFitter::fitSegment
SegmentFitResult fitSegment(const EventContext &ctx, HitVec &&calibHits, const Parameters &startPars, const Amg::Transform3D &localToGlobal) const
Definition: MdtSegmentFitter.cxx:389
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
MuonR4::SegmentFitResult::HitVec
std::vector< HitType > HitVec
Definition: SegmentFitterEventData.h:53
MuonR4::SegmentFit::ParamDefs::phi
@ phi
xAOD::UncalibMeasType::TgcStripType
@ TgcStripType
MuonR4::MdtSegmentFitter::Config::calibrator
const ISpacePointCalibrator * calibrator
Pointer to the calibrator tool.
Definition: MdtSegmentFitter.h:40
MuonR4::MdtSegmentFitter::ResidualWithPartials::gradient
std::array< Amg::Vector3D, nPars > gradient
First order derivatives.
Definition: MdtSegmentFitter.h:75
MuonR4::SegmentFitResult::nDoF
int nDoF
degrees of freedom
Definition: SegmentFitterEventData.h:68
MuonR4::MdtSegmentFitter::Config::ranges
RangeArray ranges
Definition: MdtSegmentFitter.h:48
MuonR4::SegmentFit::AxisDefs::phi
@ phi
MuonR4::SegmentFitHelpers::driftSign
int driftSign(const Amg::Vector3D &posInChamber, const Amg::Vector3D &dirInChamber, const SpacePoint &uncalibHit, MsgStream &msg)
Calculates whether a segement line travereses the tube measurement on the left (-1) or right (1) side...
Definition: SegmentFitHelperFunctions.cxx:232
MuonR4::SegmentFit::AxisDefs::t0
@ t0
MuonR4::MdtSegmentFitter::ResidualWithPartials::evalPhiPars
bool evalPhiPars
Flag whether the the residuals w.r.t phi shall be evaluated.
Definition: MdtSegmentFitter.h:71
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
Amg::toString
std::string toString(const Translation3D &translation, int precision=4)
GeoPrimitvesToStringConverter.
Definition: GeoPrimitivesToStringConverter.h:40
MuonR4::MdtSegmentFitter::UpdateStatus::noChange
@ noChange
AthMessaging::msgLvl
bool msgLvl(const MSG::Level lvl) const
Test the output level.
Definition: AthMessaging.h:151
TrigVtx::gamma
@ gamma
Definition: TrigParticleTable.h:26
MuonR4::inverse
CalibratedSpacePoint::Covariance_t inverse(const CalibratedSpacePoint::Covariance_t &mat)
Inverts the parsed matrix.
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/UtilFunctions.cxx:65
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
UtilFunctions.h
MuonR4::MdtSegmentFitter::MeasCov_t
CalibratedSpacePoint::Covariance_t MeasCov_t
Updates the chi2, its Gradient & Hessian from the measurement residual.
Definition: MdtSegmentFitter.h:154
SegmentFitHelperFunctions.h
AmgVector
AmgVector(4) T2BSTrackFilterTool
Definition: T2BSTrackFilterTool.cxx:114
Amg::x
@ x
Definition: GeoPrimitives.h:34
MuonR4::MdtSegmentFitter::HitType
std::unique_ptr< CalibratedSpacePoint > HitType
Definition: MdtSegmentFitter.h:23
Amg::Transform3D
Eigen::Affine3d Transform3D
Definition: GeoPrimitives.h:46
MuonR4::SegmentFitResult::nTimeMeas
unsigned int nTimeMeas
How many measurements give time constaint.
Definition: SegmentFitterEventData.h:72
chi2
double chi2(TH1 *h0, TH1 *h1)
Definition: comparitor.cxx:523
MuonR4::MdtSegmentFitter::Config
Definition: MdtSegmentFitter.h:26
MuonR4::CalibratedSpacePoint::State
State
State flag to distinguish different space point states.
Definition: CalibratedSpacePoint.h:24
MuonR4::MdtSegmentFitter::Config::useSecOrderDeriv
bool useSecOrderDeriv
Switch toggling whether the second order derivative shall be included.
Definition: MdtSegmentFitter.h:36
AthMessaging
Class to provide easy MsgStream access and capabilities.
Definition: AthMessaging.h:55
MuonR4::MdtSegmentFitter::Config::nParsOutOfBounds
unsigned int nParsOutOfBounds
Abort the fit as soon as more than n parameters leave the fit range.
Definition: MdtSegmentFitter.h:38
xAOD::Other
@ Other
MuonR4::SegmentFitResult::segmentPars
Parameters segmentPars
Final segment parameters.
Definition: SegmentFitterEventData.h:60
MuonR4::CalibratedSpacePoint::type
xAOD::UncalibMeasType type() const
Returns the space point type.
Definition: CalibratedSpacePoint.cxx:36
MuonR4::SegmentFit::ParamDefs::x0
@ x0
MuonR4::MdtSegmentFitter::calculateWireResiduals
void calculateWireResiduals(const LineWithPartials &line, const CalibratedSpacePoint &spacePoint, ResidualWithPartials &residual) const
Calculates the residuals together with the corresponding derivatives for a drift-circle measurement.
Definition: MdtSegmentFitter.cxx:184
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
MuonR4::SegmentFit::AxisDefs::eta
@ eta
dot.dot
def dot(G, fn, nodesToHighlight=[])
Definition: dot.py:5
AthMessaging::msg
MsgStream & msg() const
The standard message stream.
Definition: AthMessaging.h:164
compute_lumi.denom
denom
Definition: compute_lumi.py:76
MuonR4::SegmentFit::ParamDefs::time
@ time
MuonR4::CalibratedSpacePoint::State::Valid
@ Valid
MuonR4::MdtSegmentFitter::updateDerivatives
void updateDerivatives(const ResidualWithPartials &fitMeas, const MeasCov_t &measCovariance, AmgVector(5)&gradient, AmgSymMatrix(5)&hessian, double &chi2, int startPar) const
Definition: MdtSegmentFitter.cxx:616
lumiFormat.array
array
Definition: lumiFormat.py:91
MuonR4::MdtSegmentFitter::m_cfg
Config m_cfg
Definition: MdtSegmentFitter.h:91
MuonR4::SegmentFit::ParamDefs::y0
@ y0
MuonR4::MdtSegmentFitter::MdtSegmentFitter
MdtSegmentFitter(const std::string &name, Config &&config)
Standard constructor.
Definition: MdtSegmentFitter.cxx:51
MuonR4::MdtSegmentFitter::Config::nMaxCalls
unsigned int nMaxCalls
How many calls shall be executed.
Definition: MdtSegmentFitter.h:28
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
createCoolChannelIdFile.par
par
Definition: createCoolChannelIdFile.py:29
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
MuonR4::SegmentFit::toInt
constexpr int toInt(const ParamDefs p)
Definition: MuonHoughDefs.h:42
MuonR4::CalibratedSpacePoint::positionInChamber
const Amg::Vector3D & positionInChamber() const
The position of the calibrated space point inside the chamber.
Definition: CalibratedSpacePoint.cxx:21
MuonR4::MdtSegmentFitter::Config::reCalibrate
bool reCalibrate
Switch toggling whether the calibrator shall be called at each iteration.
Definition: MdtSegmentFitter.h:34
MuonR4::MdtSegmentFitter::UpdateStatus::allOkay
@ allOkay
MuonR4::SegmentFitResult::HitType
std::unique_ptr< CalibratedSpacePoint > HitType
Definition: SegmentFitterEventData.h:52
python.PhysicalConstants.c_light
float c_light
Definition: PhysicalConstants.py:63
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
MuonR4::MdtSegmentFitter::LineWithPartials
Store the partial derivative of the line w.r.t.
Definition: MdtSegmentFitter.h:54
Amg::dirFromAngles
Amg::Vector3D dirFromAngles(const double phi, const double theta)
Constructs a direction vector from the azimuthal & polar angles.
Definition: GeoPrimitivesHelpers.h:299
MuonR4
This header ties the generic definitions in this package.
Definition: HoughEventData.h:16
EventPrimitivesCovarianceHelpers.h
MuonR4::MdtSegmentFitter::Config::RangeArray
std::array< std::array< double, 2 >, SegmentFit::toInt(ParamDefs::nPars)> RangeArray
Allowed parameter ranges.
Definition: MdtSegmentFitter.h:44
MuonR4::SegmentFit::Covariance
AmgSymMatrix(toInt(ParamDefs::nPars)) Covariance
Definition: MuonHoughDefs.h:49
a
TList * a
Definition: liststreamerinfos.cxx:10
MdtSegmentFitter.h
MuonR4::CalibratedSpacePoint::dimension
unsigned dimension() const
Returns the local dimension of the measurement.
Definition: CalibratedSpacePoint.cxx:61
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
MuonR4::MdtSegmentFitter::Config::doTimeFit
bool doTimeFit
Switch toggling whether the T0 shall be fitted or not.
Definition: MdtSegmentFitter.h:32
MuonR4::MdtSegmentFitter::HitVec
std::vector< HitType > HitVec
Definition: MdtSegmentFitter.h:24
MuonR4::SegmentFitResult::timeFit
bool timeFit
Was the time fitted.
Definition: SegmentFitterEventData.h:56
MuonR4::CalibratedSpacePoint
The calibrated Space point is created during the calibration process.
Definition: CalibratedSpacePoint.h:15
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
MuonR4::SegmentFitResult::nPhiMeas
unsigned int nPhiMeas
How many phi measurements.
Definition: SegmentFitterEventData.h:70
CxxUtils::sincos
Helper to simultaneously calculate sin and cos of the same angle.
Definition: sincos.h:76
Muon::IMuonIdHelperSvc
Interface for Helper service that creates muon Identifiers and can be used to print Identifiers.
Definition: IMuonIdHelperSvc.h:27
Amg::signedDistance
double signedDistance(const Amg::Vector3D &posA, const Amg::Vector3D &dirA, const Amg::Vector3D &posB, const Amg::Vector3D &dirB)
Calculates the signed distance between two lines in 3D space.
Definition: GeoPrimitivesHelpers.h:329
python.SystemOfUnits.ns
int ns
Definition: SystemOfUnits.py:130
MuonR4::SegmentFitResult
Definition: SegmentFitterEventData.h:46
MuonR4::MdtSegmentFitter::partialPlaneIntersect
static Amg::Vector3D partialPlaneIntersect(const Amg::Vector3D &normal, const double offset, const LineWithPartials &line, const ParamDefs fitPar)
Calculates the partial derivative of the intersection point between the segment line and the measurem...
Definition: MdtSegmentFitter.cxx:120
python.Constants.VERBOSE
int VERBOSE
Definition: Control/AthenaCommon/python/Constants.py:14
PowhegControl_ttFCNC_NLO.params
params
Definition: PowhegControl_ttFCNC_NLO.py:226
MuonR4::CalibratedSpacePoint::spacePoint
const SpacePoint * spacePoint() const
The pointer to the space point out of which this space point has been built.
Definition: CalibratedSpacePoint.cxx:18
MuonR4::MdtSegmentFitter::Config::defaultRanges
static RangeArray defaultRanges()
Function that returns a set of predefined ranges for testing.
Definition: MdtSegmentFitter.cxx:40
MuonR4::AmgSymMatrix
const AmgSymMatrix(2) &SpacePoint
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/SpacePoint.cxx:150
pow
constexpr int pow(int base, int exp) noexcept
Definition: ap_fixedTest.cxx:15
MuonR4::MdtSegmentFitter::recalibrate
bool recalibrate(const EventContext &ctx, SegmentFitResult &fitResult) const
Recalibrate the measurements participating in the fit & shift them into the centre-of gravity frame.
Definition: MdtSegmentFitter.cxx:62
MuonR4::MdtSegmentFitter::updateParameters
UpdateStatus updateParameters(Parameters &currentPars, Parameters &previousPars, Parameters &currGrad, Parameters &prevGrad, const AmgSymMatrix(5)&hessian) const
Update step of the segment parameters using the Hessian and the gradient.
Definition: MdtSegmentFitter.cxx:654
MuonR4::MdtSegmentFitter::ResidualWithPartials::hessian
std::array< Amg::Vector3D, sumUp(nPars)> hessian
Second order derivatives.
Definition: MdtSegmentFitter.h:77
MuonR4::CalibratedSpacePoint::directionInChamber
const Amg::Vector3D & directionInChamber() const
The direction of the calibrated space point inside the chamber.
Definition: CalibratedSpacePoint.cxx:24
MuonR4::SegmentFit::ParamDefs::nPars
@ nPars
xAOD::UncalibMeasType::RpcStripType
@ RpcStripType
MuonR4::HitType
SegmentFitResult::HitType HitType
Definition: MdtSegmentFitter.cxx:36
MuonR4::CalibratedSpacePoint::driftRadius
double driftRadius() const
The drift radius of the calibrated space point.
Definition: CalibratedSpacePoint.cxx:27
xAOD::UncalibMeasType::MdtDriftCircleType
@ MdtDriftCircleType
mag
Scalar mag() const
mag method
Definition: AmgMatrixBasePlugin.h:26
MuonR4::SegmentFit::ParamDefs::theta
@ theta
fitman.k
k
Definition: fitman.py:528
generate::Zero
void Zero(TH1D *hin)
Definition: generate.cxx:32
MuonR4::MdtSegmentFitter::updateLinePartials
static void updateLinePartials(const Parameters &fitPars, LineWithPartials &line)
Updates the line parameters together with its first & second order partial derivatives.
Definition: MdtSegmentFitter.cxx:142
MuonR4::contract
double contract(const CalibratedSpacePoint::Covariance_t &mat, const Amg::Vector3D &a, const Amg::Vector3D &b)
Definition: MuonSpectrometer/MuonPhaseII/Event/MuonSpacePoint/src/UtilFunctions.cxx:13