15 typename propagator_options_t>
21 auto res = getDistanceAndMomentum<3>(
gctx, trkParams, vtxPos,
state);
28 return res.value().first.norm();
32 typename propagator_options_t>
39 auto res = getDistanceAndMomentum<3>(
gctx, trkParams, vtxPos,
state);
52 Vector3 momDir = res.value().second;
59 Vector3 orthogonalDeltaR = deltaR - (deltaR.dot(momDir)) * momDir;
62 Vector3 perpDir = momDir.cross(orthogonalDeltaR);
74 coordinateSystem.matrix().block<3, 1>(0, 0) = orthogonalDeltaR;
75 coordinateSystem.matrix().block<3, 1>(0, 1) = perpDir;
76 coordinateSystem.matrix().block<3, 1>(0, 2) = momDir;
78 coordinateSystem.matrix().block<3, 1>(0, 3) = vtxPos;
81 std::shared_ptr<PlaneSurface> planeSurface =
82 Surface::makeShared<PlaneSurface>(coordinateSystem);
84 auto intersection = planeSurface
85 ->intersect(gctx, trkParams.position(gctx),
86 trkParams.direction(),
false)
90 propagator_options_t pOptions(gctx, mctx);
92 Direction::fromScalarZeroAsPositive(intersection.pathLength());
96 auto result =
m_cfg.propagator->propagate(trkParams, *planeSurface, pOptions);
98 return *result->endParameters;
100 return result.error();
104 template <
typename input_track_t,
typename propagator_t,
105 typename propagator_options_t>
106 template <
unsigned int nDim>
112 static_assert(nDim == 3 or nDim == 4,
113 "The number of dimensions nDim must be either 3 or 4.");
115 if (trkParams ==
nullptr) {
116 return VertexingError::EmptyInput;
121 if (not trkParams->
covariance().has_value()) {
122 return VertexingError::NoCovariance;
125 if constexpr (nDim == 3) {
141 Vector3 xAxis = surfaceAxes.col(0);
142 Vector3 yAxis = surfaceAxes.col(1);
149 Vector3 originToVertex = vertexPos.template head<3>() - surfaceOrigin;
154 localVertexCoords.template head<2>() =
155 Vector2(originToVertex.dot(xAxis), originToVertex.dot(yAxis));
158 localTrackCoords.template head<2>() =
162 if constexpr (nDim == 4) {
163 localVertexCoords(2) = vertexPos(3);
168 ActsVector<nDim - 1> residual = localTrackCoords - localVertexCoords;
171 return residual.dot(weight * residual);
174 template <
typename input_track_t,
typename propagator_t,
175 typename propagator_options_t>
178 propagator_options_t>::performNewtonOptimization(
const Vector3& helixCenter,
182 double sinPhi = std::sin(phi);
183 double cosPhi = std::cos(phi);
186 bool hasConverged =
false;
188 double cotTheta = 1. / std::tan(theta);
190 double xO = helixCenter.x();
191 double yO = helixCenter.y();
192 double zO = helixCenter.z();
194 double xVtx = vtxPos.x();
195 double yVtx = vtxPos.y();
196 double zVtx = vtxPos.z();
200 while (!hasConverged && nIter <
m_cfg.maxIterations) {
201 double derivative = rho * ((xVtx - xO) * cosPhi + (yVtx - yO) * sinPhi +
202 (zVtx - zO + rho * phi * cotTheta) * cotTheta);
203 double secDerivative = rho * (-(xVtx - xO) * sinPhi + (yVtx - yO) * cosPhi +
204 rho * cotTheta * cotTheta);
206 if (secDerivative < 0.) {
207 return VertexingError::NumericFailure;
210 double deltaPhi = -derivative / secDerivative;
213 sinPhi = std::sin(phi);
214 cosPhi = std::cos(phi);
218 if (std::abs(deltaPhi) <
m_cfg.precision) {
225 return VertexingError::NotConverged;
230 template <
typename input_track_t,
typename propagator_t,
231 typename propagator_options_t>
232 template <
unsigned int nDim>
238 static_assert(nDim == 3 or nDim == 4,
239 "The number of dimensions nDim must be either 3 or 4.");
251 if (!fieldRes.ok()) {
252 return fieldRes.error();
254 double bZ = (*fieldRes)[
eZ];
259 if (absoluteCharge == 0. or bZ == 0.) {
268 (vtxPos.template head<3>() - positionOnTrack).dot(momDirStraightTrack);
272 pcaStraightTrack.template head<3>() =
273 positionOnTrack + distanceToPca * momDirStraightTrack;
274 if constexpr (nDim == 4) {
284 pcaStraightTrack[3] = timeOnTrack + distanceToPca / beta;
290 return std::make_pair(deltaRStraightTrack, momDirStraightTrack);
304 double sinTheta = std::sin(theta);
305 double cotTheta = 1. / std::tan(theta);
312 double rho = sinTheta * (1. / qOvP) / bZ;
319 refPoint +
Vector3(-(d0 - rho) * std::sin(phi),
320 (d0 - rho) * std::cos(phi), z0 + rho * phi * cotTheta);
324 auto res = performNewtonOptimization(helixCenter, vtxPos.template head<3>(),
332 double cosPhi = std::cos(phi);
333 double sinPhi = std::sin(phi);
339 Vector3(cosPhi * sinTheta, sinPhi * sinTheta, std::cos(theta));
345 pca.template head<3>() =
346 helixCenter + rho *
Vector3(-sinPhi, cosPhi, -cotTheta * phi);
348 if constexpr (nDim == 4) {
358 pca[3] = tP - rho / (beta * sinTheta) * (phi - phiP);
363 return std::make_pair(deltaR, momDir);
366 template <
typename input_track_t,
typename propagator_t,
367 typename propagator_options_t>
374 bool calculateTimeIP)
const {
375 const std::shared_ptr<PerigeeSurface> perigeeSurface =
376 Surface::makeShared<PerigeeSurface>(vtx.
position());
379 propagator_options_t pOptions(gctx, mctx);
385 Direction::fromScalarZeroAsPositive(intersection.pathLength());
388 auto result =
m_cfg.propagator->propagate(track, *perigeeSurface, pOptions);
391 return result.error();
394 const auto& propRes = *result;
397 if (not propRes.endParameters->covariance().has_value()) {
398 return VertexingError::NoCovariance;
402 auto impactParams = propRes.endParameters->impactParameters();
403 auto impactParamCovariance =
404 propRes.endParameters->impactParameterCovariance().value();
416 ipAndSigma.
d0 = impactParams[0];
418 double vtxVar2DExtent = std::max(vtxVarX, vtxVarY);
422 if (vtxVar2DExtent > 0) {
424 std::sqrt(vtxVar2DExtent + impactParamCovariance(0, 0));
426 ipAndSigma.
sigmaD0 = std::sqrt(impactParamCovariance(0, 0));
429 ipAndSigma.
z0 = impactParams[1];
431 ipAndSigma.
sigmaZ0 = std::sqrt(vtxVarZ + impactParamCovariance(1, 1));
433 ipAndSigma.
sigmaZ0 = std::sqrt(impactParamCovariance(1, 1));
436 if (calculateTimeIP) {
437 ipAndSigma.
deltaT = std::abs(vtx.
time() - impactParams[2]);
440 ipAndSigma.
sigmaDeltaT = std::sqrt(vtxVarT + impactParamCovariance(2, 2));
442 ipAndSigma.
sigmaDeltaT = std::sqrt(impactParamCovariance(2, 2));
449 template <
typename input_track_t,
typename propagator_t,
450 typename propagator_options_t>
458 const std::shared_ptr<PerigeeSurface> perigeeSurface =
459 Surface::makeShared<PerigeeSurface>(vtx.
position());
462 propagator_options_t pOptions(gctx, mctx);
463 pOptions.direction = Direction::Backward;
466 auto result =
m_cfg.propagator->propagate(track, *perigeeSurface, pOptions);
469 return result.error();
472 const auto& propRes = *result;
473 const auto& params = propRes.endParameters->parameters();
479 double vs = std::sin(std::atan2(direction[1], direction[0]) - phi) * d0;
480 double eta = -std::log(std::tan(theta / 2.));
483 double zs = (dir_eta -
eta) * z0;
485 std::pair<double, double> vszs;
487 vszs.first = vs >= 0. ? 1. : -1.;
488 vszs.second = zs >= 0. ? 1. : -1.;
493 template <
typename input_track_t,
typename propagator_t,
494 typename propagator_options_t>
502 const std::shared_ptr<PerigeeSurface> perigeeSurface =
503 Surface::makeShared<PerigeeSurface>(vtx.
position());
506 propagator_options_t pOptions(gctx, mctx);
507 pOptions.direction = Direction::Backward;
510 auto result =
m_cfg.propagator->propagate(track, *perigeeSurface, pOptions);
513 return result.error();
516 const auto& propRes = *result;
517 const auto& params = propRes.endParameters;
518 const Vector3 trkpos = params->position(gctx);
519 const Vector3 trkmom = params->momentum();
522 (direction.cross(trkmom)).dot(trkmom.cross(vtx.
position() - trkpos));
524 return sign >= 0. ? 1. : -1.;