ATLAS Offline Software
MdtSegmentSeedGenerator.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #ifndef MUONR4_MUONPATTERNHELPERS_MDTSEGMENTSEEDGENERATOR_ICC
6 #define MUONR4_MUONPATTERNHELPERS_MDTSEGMENTSEEDGENERATOR_ICC
7 
8 #include <MuonPatternHelpers/MdtSegmentSeedGenerator.h>
9 
10 namespace MuonR4::SegmentFit{
11  template <Acts::Experimental::CompositeSpacePoint SpacePoint_t>
12  MdtSegmentSeedGenerator::SeedSolution
13  MdtSegmentSeedGenerator::estimateTangentLine(const SpacePoint_t& topHit, const SpacePoint_t& bottomHit,
14  const SignComboType& signs) const {
15 
16  using namespace Acts::UnitLiterals;
17  const auto&[signTop, signBot] = signs;
18 
19  SeedSolution solution{};
20  const Amg::Vector3D& bottomPos{bottomHit.localPosition()};
21  const Amg::Vector3D& topPos{topHit.localPosition()};
22 
23  const Amg::Vector3D D = topPos - bottomPos;
24  ATH_MSG_VERBOSE(__func__<<"() - "<<__LINE__<<": Bottom position: "<<Amg::toString(bottomPos)
25  <<", driftRadius: "<<(signBot*bottomHit.driftRadius())<<" - top position "<<Amg::toString(topPos)
26  <<", driftRadius: "<<(signTop * topHit.driftRadius()) <<", tube distance: "<<Amg::toString(D));
27 
28  const double thetaTubes = std::atan2(D.y(), D.z());
29  const double distTubes = Acts::fastHypot(D.y(), D.z());
30  constexpr auto covIdx = Acts::toUnderlying(AxisDefs::etaCov);
31  const double combDriftUncert{topHit.covariance()[covIdx] + bottomHit.covariance()[covIdx]};
32  const double R = signBot * bottomHit.driftRadius() - signTop * topHit.driftRadius();
33  solution.theta = thetaTubes - std::asin(std::clamp(R / distTubes, -1., 1.));
34  /// Outside the used allowed parameter range
35  if (solution.theta < m_cfg.thetaRange[0] || solution.theta > m_cfg.thetaRange[1]) {
36  solution.isValid = false;
37  return solution;
38  }
39  const double cosTheta = std::cos(solution.theta);
40  const double sinTheta = std::sin(solution.theta);
41  solution.y0 = bottomPos.y()*cosTheta - bottomPos.z()*sinTheta + signBot*bottomHit.driftRadius();
42  ATH_MSG_VERBOSE("Solution is theta: "<< (solution.theta / 1._degree)<<", y0: "<<solution.y0);
43  assert(Acts::abs(topPos.y()*cosTheta - topPos.z()*sinTheta + signTop*topHit.driftRadius() - solution.y0) <
44  std::numeric_limits<float>::epsilon());
45  solution.y0 /= cosTheta;
46  if (solution.y0 < m_cfg.interceptRange[0] || solution.y0 > m_cfg.interceptRange[1]) {
47  solution.isValid = false;
48  return solution;
49  }
50  const double denomSquare = 1. - Acts::pow(R / distTubes, 2);
51  if (denomSquare < std::numeric_limits<double>::epsilon()){
52  ATH_MSG_VERBOSE("Invalid seed, rejecting");
53  solution.isValid = false;
54  return solution;
55  }
56  solution.dTheta = combDriftUncert / std::sqrt(denomSquare) / distTubes;
57  solution.dY0 = std::hypot(bottomPos.y()*sinTheta + bottomPos.z()*cosTheta, 1.) * solution.dTheta;
58  return solution;
59  }
60 }
61 
62 #endif