File indexing completed on 2025-11-03 08:57:40
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 #include "Acts/Vertexing/HelicalTrackLinearizer.hpp"
0010 
0011 #include "Acts/Propagator/PropagatorOptions.hpp"
0012 #include "Acts/Utilities/Intersection.hpp"
0013 #include "Acts/Utilities/MathHelpers.hpp"
0014 #include "Acts/Vertexing/LinearizerTrackParameters.hpp"
0015 
0016 Acts::Result<Acts::LinearizedTrack>
0017 Acts::HelicalTrackLinearizer::linearizeTrack(
0018     const BoundTrackParameters& params, double linPointTime,
0019     const Surface& perigeeSurface, const Acts::GeometryContext& gctx,
0020     const Acts::MagneticFieldContext& mctx,
0021     MagneticFieldProvider::Cache& fieldCache) const {
0022   
0023   PropagatorPlainOptions pOptions(gctx, mctx);
0024 
0025   
0026   
0027   pOptions.surfaceTolerance = m_cfg.targetTolerance;
0028 
0029   
0030   
0031   
0032   
0033   Intersection3D intersection =
0034       perigeeSurface
0035           .intersect(gctx, params.position(gctx), params.direction(),
0036                      BoundaryTolerance::Infinite())
0037           .closest();
0038 
0039   
0040   
0041   
0042   
0043   pOptions.direction =
0044       Direction::fromScalarZeroAsPositive(intersection.pathLength());
0045 
0046   
0047   const auto res =
0048       m_cfg.propagator->propagateToSurface(params, perigeeSurface, pOptions);
0049   if (!res.ok()) {
0050     return res.error();
0051   }
0052   const auto& endParams = *res;
0053 
0054   
0055   
0056   BoundVector paramsAtPCA = endParams.parameters();
0057 
0058   
0059   Vector4 pca = Vector4::Zero();
0060   {
0061     auto pos = endParams.position(gctx);
0062     pca[ePos0] = pos[ePos0];
0063     pca[ePos1] = pos[ePos1];
0064     pca[ePos2] = pos[ePos2];
0065     pca[eTime] = endParams.time();
0066   }
0067   BoundSquareMatrix parCovarianceAtPCA = endParams.covariance().value();
0068 
0069   
0070   
0071   double d0 = paramsAtPCA(BoundIndices::eBoundLoc0);
0072 
0073   double phi = paramsAtPCA(BoundIndices::eBoundPhi);
0074   double sinPhi = std::sin(phi);
0075   double cosPhi = std::cos(phi);
0076 
0077   double theta = paramsAtPCA(BoundIndices::eBoundTheta);
0078   double sinTheta = std::sin(theta);
0079   double tanTheta = std::tan(theta);
0080 
0081   
0082   double qOvP = paramsAtPCA(BoundIndices::eBoundQOverP);
0083   
0084   double m0 = params.particleHypothesis().mass();
0085   
0086   double p = params.particleHypothesis().extractMomentum(qOvP);
0087 
0088   
0089   double beta = p / fastHypot(p, m0);
0090   
0091   double betaT = beta * sinTheta;
0092 
0093   
0094   Vector3 momentumAtPCA(phi, theta, qOvP);
0095 
0096   
0097   double absoluteCharge = params.particleHypothesis().absoluteCharge();
0098 
0099   
0100   auto field = m_cfg.bField->getField(VectorHelpers::position(pca), fieldCache);
0101   if (!field.ok()) {
0102     return field.error();
0103   }
0104   double Bz = (*field)[eZ];
0105 
0106   
0107   ActsMatrix<eBoundSize, eLinSize> completeJacobian =
0108       ActsMatrix<eBoundSize, eLinSize>::Zero(eBoundSize, eLinSize);
0109 
0110   
0111   
0112   
0113   if (absoluteCharge == 0. || Bz == 0.) {
0114     
0115     
0116     
0117     
0118 
0119     
0120     completeJacobian(eBoundLoc0, eLinPos0) = -sinPhi;
0121     completeJacobian(eBoundLoc0, eLinPos1) = cosPhi;
0122 
0123     
0124     completeJacobian(eBoundLoc1, eLinPos0) = -cosPhi / tanTheta;
0125     completeJacobian(eBoundLoc1, eLinPos1) = -sinPhi / tanTheta;
0126     completeJacobian(eBoundLoc1, eLinPos2) = 1.;
0127     completeJacobian(eBoundLoc1, eLinPhi) = -d0 / tanTheta;
0128 
0129     
0130     completeJacobian(eBoundPhi, eLinPhi) = 1.;
0131 
0132     
0133     completeJacobian(eBoundTheta, eLinTheta) = 1.;
0134 
0135     
0136     completeJacobian(eBoundQOverP, eLinQOverP) = 1.;
0137 
0138     
0139     completeJacobian(eBoundTime, eLinPos0) = -cosPhi / betaT;
0140     completeJacobian(eBoundTime, eLinPos1) = -sinPhi / betaT;
0141     completeJacobian(eBoundTime, eLinTime) = 1.;
0142     completeJacobian(eBoundTime, eLinPhi) = -d0 / betaT;
0143   } else {
0144     
0145     double rho = sinTheta * (1. / qOvP) / Bz;
0146     
0147     double h = (rho < 0.) ? -1 : 1;
0148 
0149     
0150     double X = pca(0) - perigeeSurface.center(gctx).x() + rho * sinPhi;
0151     double Y = pca(1) - perigeeSurface.center(gctx).y() - rho * cosPhi;
0152     double S2 = (X * X + Y * Y);
0153     
0154     
0155     double S = std::sqrt(S2);
0156 
0157     double XoverS2 = X / S2;
0158     double YoverS2 = Y / S2;
0159     double rhoCotTheta = rho / tanTheta;
0160     double rhoOverBetaT = rho / betaT;
0161     
0162     double absRhoOverS = h * rho / S;
0163 
0164     
0165     
0166     
0167     
0168     
0169 
0170     
0171     completeJacobian(eBoundLoc0, eLinPos0) = -h * X / S;
0172     completeJacobian(eBoundLoc0, eLinPos1) = -h * Y / S;
0173 
0174     
0175     completeJacobian(eBoundLoc1, eLinPos0) = rhoCotTheta * YoverS2;
0176     completeJacobian(eBoundLoc1, eLinPos1) = -rhoCotTheta * XoverS2;
0177     completeJacobian(eBoundLoc1, eLinPos2) = 1.;
0178     completeJacobian(eBoundLoc1, eLinPhi) = rhoCotTheta * (1. - absRhoOverS);
0179 
0180     
0181     completeJacobian(eBoundPhi, eLinPos0) = -YoverS2;
0182     completeJacobian(eBoundPhi, eLinPos1) = XoverS2;
0183     completeJacobian(eBoundPhi, eLinPhi) = absRhoOverS;
0184 
0185     
0186     completeJacobian(eBoundTheta, eLinTheta) = 1.;
0187 
0188     
0189     completeJacobian(eBoundQOverP, eLinQOverP) = 1.;
0190 
0191     
0192     completeJacobian(eBoundTime, eLinPos0) = rhoOverBetaT * YoverS2;
0193     completeJacobian(eBoundTime, eLinPos1) = -rhoOverBetaT * XoverS2;
0194     completeJacobian(eBoundTime, eLinTime) = 1.;
0195     completeJacobian(eBoundTime, eLinPhi) = rhoOverBetaT * (1. - absRhoOverS);
0196   }
0197 
0198   
0199   ActsMatrix<eBoundSize, eLinPosSize> positionJacobian =
0200       completeJacobian.block<eBoundSize, eLinPosSize>(0, 0);
0201   ActsMatrix<eBoundSize, eLinMomSize> momentumJacobian =
0202       completeJacobian.block<eBoundSize, eLinMomSize>(0, eLinPosSize);
0203 
0204   
0205   BoundVector constTerm =
0206       paramsAtPCA - positionJacobian * pca - momentumJacobian * momentumAtPCA;
0207 
0208   
0209   BoundSquareMatrix weightAtPCA = parCovarianceAtPCA.inverse();
0210 
0211   Vector4 linPoint;
0212   linPoint.head<3>() = perigeeSurface.center(gctx);
0213   linPoint[3] = linPointTime;
0214 
0215   return LinearizedTrack(paramsAtPCA, parCovarianceAtPCA, weightAtPCA, linPoint,
0216                          positionJacobian, momentumJacobian, pca, momentumAtPCA,
0217                          constTerm);
0218 }