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