Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:28

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp"
0010 
0011 #include "Acts/Definitions/TrackParametrization.hpp"
0012 #include "Acts/Utilities/MathHelpers.hpp"
0013 
0014 #include <numbers>
0015 
0016 Acts::FreeVector Acts::estimateTrackParamsFromSeed(const Vector3& sp0,
0017                                                    const Vector3& sp1,
0018                                                    const Vector3& sp2,
0019                                                    const Vector3& bField) {
0020   // Define a new coordinate frame with its origin at the bottom space point, z
0021   // axis long the magnetic field direction and y axis perpendicular to vector
0022   // from the bottom to middle space point. Hence, the projection of the middle
0023   // space point on the transverse plane will be located at the x axis of the
0024   // new frame.
0025   Vector3 relVec = sp1 - sp0;
0026   Vector3 newZAxis = bField.normalized();
0027   Vector3 newYAxis = newZAxis.cross(relVec).normalized();
0028   Vector3 newXAxis = newYAxis.cross(newZAxis);
0029   RotationMatrix3 rotation;
0030   rotation.col(0) = newXAxis;
0031   rotation.col(1) = newYAxis;
0032   rotation.col(2) = newZAxis;
0033   // The center of the new frame is at the bottom space point
0034   Translation3 trans(sp0);
0035   // The transform which constructs the new frame
0036   Transform3 transform(trans * rotation);
0037 
0038   // The coordinate of the middle and top space point in the new frame
0039   Vector3 local1 = transform.inverse() * sp1;
0040   Vector3 local2 = transform.inverse() * sp2;
0041 
0042   // In the new frame the bottom sp is at the origin, while the middle
0043   // sp in along the x axis. As such, the x-coordinate of the circle is
0044   // at: x-middle / 2.
0045   // The y coordinate can be found by using the straight line passing
0046   // between the mid point between the middle and top sp and perpendicular to
0047   // the line connecting them
0048   Vector2 circleCenter;
0049   circleCenter(0) = 0.5 * local1(0);
0050 
0051   double deltaX21 = local2(0) - local1(0);
0052   double sumX21 = local2(0) + local1(0);
0053   // straight line connecting the two points
0054   // y = a * x + c (we don't care about c right now)
0055   // we simply need the slope
0056   // we compute 1./a since this is what we need for the following computation
0057   double ia = deltaX21 / local2(1);
0058   // Perpendicular line is then y = -1/a *x + b
0059   // we can evaluate b given we know a already by imposing
0060   // the line passes through P = (0.5 * (x2 + x1), 0.5 * y2)
0061   double b = 0.5 * (local2(1) + ia * sumX21);
0062   circleCenter(1) = -ia * circleCenter(0) + b;
0063   // Radius is a signed distance between circleCenter and first sp, which is at
0064   // (0, 0) in the new frame. Sign depends on the slope a (positive vs negative)
0065   int sign = ia > 0 ? -1 : 1;
0066   const double R = circleCenter.norm();
0067   double invTanTheta =
0068       local2.z() / (2 * R * std::asin(local2.head<2>().norm() / (2 * R)));
0069   // The momentum direction in the new frame (the center of the circle has the
0070   // coordinate (-1.*A/(2*B), 1./(2*B)))
0071   double A = -circleCenter(0) / circleCenter(1);
0072   Vector3 transDirection(1., A, fastHypot(1, A) * invTanTheta);
0073   // Transform it back to the original frame
0074   Vector3 direction = rotation * transDirection.normalized();
0075 
0076   // Initialize the free parameters vector
0077   FreeVector params = FreeVector::Zero();
0078 
0079   // The bottom space point position
0080   params.segment<3>(eFreePos0) = sp0;
0081 
0082   // The estimated direction
0083   params.segment<3>(eFreeDir0) = direction;
0084 
0085   // The estimated q/pt in [GeV/c]^-1 (note that the pt is the projection of
0086   // momentum on the transverse plane of the new frame)
0087   double qOverPt = sign / (bField.norm() * R);
0088   // The estimated q/p in [GeV/c]^-1
0089   params[eFreeQOverP] = qOverPt / fastHypot(1., invTanTheta);
0090 
0091   return params;
0092 }
0093 
0094 Acts::BoundMatrix Acts::estimateTrackParamCovariance(
0095     const EstimateTrackParamCovarianceConfig& config, const BoundVector& params,
0096     bool hasTime) {
0097   assert((params[eBoundTheta] > 0 && params[eBoundTheta] < std::numbers::pi) &&
0098          "Theta must be in the range (0, pi)");
0099 
0100   BoundSquareMatrix result = BoundSquareMatrix::Zero();
0101 
0102   for (std::size_t i = eBoundLoc0; i < eBoundSize; ++i) {
0103     double sigma = config.initialSigmas[i];
0104     double variance = sigma * sigma;
0105 
0106     if (i == eBoundQOverP) {
0107       // note that we rely on the fact that sigma theta is already computed
0108       double varianceTheta = result(eBoundTheta, eBoundTheta);
0109 
0110       // transverse momentum contribution
0111       variance += std::pow(config.initialSigmaPtRel * params[eBoundQOverP], 2);
0112 
0113       // theta contribution
0114       variance +=
0115           varianceTheta *
0116           std::pow(params[eBoundQOverP] / std::tan(params[eBoundTheta]), 2);
0117     }
0118 
0119     if (i == eBoundTime && !hasTime) {
0120       // Inflate the time uncertainty if no time measurement is available
0121       variance *= config.noTimeVarInflation;
0122     }
0123 
0124     // Inflate the initial covariance
0125     variance *= config.initialVarInflation[i];
0126 
0127     result(i, i) = variance;
0128   }
0129 
0130   return result;
0131 }