31void clampNegligibleCovarianceNoise(SurfaceTrackState&
state)
noexcept
33 constexpr float kNoiseFloor = 1.e-3f;
34 for (uint8_t
i = 0;
i < 5; ++
i) {
43void congruenceTransform(
const float (&inCov)[15],
const float (&jacobian)[5][5],
float (&outCov)[15])
noexcept
55 for (uint8_t k = 0; k < 5; ++k) {
64 for (uint8_t k = 0; k < 5; ++k) {
67 outCov[packedCovarianceIndex(
row,
col)] =
sum;
74bool barrelToForward(SurfaceTrackState&
state,
float bz)
noexcept
78 if (!(std::abs(snp) < 1.f) || tanl == 0.f) {
83 const float csp = std::sqrt((1.f - snp) * (1.f + snp));
87 const float xGlo = bX * csA - bY * snA;
88 const float yGlo = bX * snA + bY * csA;
90 float phi = std::remainder(
state.
alpha + std::asin(snp), o2::constants::math::TwoPI);
92 if (phi <= -o2::constants::math::PI) {
93 phi += o2::constants::math::TwoPI;
99 const float jacobian[5][5] = {
100 {-snA, -(csA * csp - snA * snp) / tanl, 0.f, 0.f, 0.f},
101 {csA, -(snA * csp + csA * snp) / tanl, 0.f, 0.f, 0.f},
102 {0.f, -curvature / tanl, 1.f / csp, 0.f, 0.f},
103 {0.f, 0.f, 0.f, 1.f, 0.f},
104 {0.f, 0.f, 0.f, 0.f, 1.f}};
109 for (uint8_t
i = 0;
i < 5; ++
i) {
112 for (uint8_t
i = 0;
i < 15; ++
i) {
124bool forwardToBarrel(SurfaceTrackState&
state,
float bz)
noexcept
128 const float r = std::sqrt(
x *
x +
y *
y);
132 const float alpha = std::atan2(
y,
x);
133 const float csA = std::cos(
alpha);
134 const float snA = std::sin(
alpha);
136 const float csp = std::cos(phi -
alpha);
137 const float snp = std::sin(phi -
alpha);
140 if (!(csp > 0.f && std::abs(snp) < 1.f)) {
144 const float bX =
x * csA +
y * snA;
145 const float bY = -
x * snA +
y * csA;
152 const float jacobian[5][5] = {
153 {-snA - snp * csA / csp, csA - snp * snA / csp, 0.f, 0.f, 0.f},
154 {-tanlOverCsp * csA, -tanlOverCsp * snA, 0.f, 0.f, 0.f},
155 {-curvature * csA, -curvature * snA, csp, 0.f, 0.f},
156 {0.f, 0.f, 0.f, 1.f, 0.f},
157 {0.f, 0.f, 0.f, 0.f, 1.f}};
162 for (uint8_t
i = 0;
i < 5; ++
i) {
165 for (uint8_t
i = 0;
i < 15; ++
i) {
176struct AttachmentTransaction {
180 void commit(SurfaceTrackState& destination,
float& destinationChi2)
const noexcept
183 destinationChi2 =
chi2;
187bool acceptsAttachmentChi2(
float predictedChi2,
bool gateEnabled,
float maxChi2)
noexcept
189 if (predictedChi2 < 0.f || (gateEnabled && predictedChi2 > maxChi2)) {
195bool covarianceDiagonalsNonNegative(
const SurfaceTrackState&
state)
noexcept
197 for (uint8_t
i = 0;
i < 5; ++
i) {
212using DenseMatrix5 =
float[5][5];
214bool validateBarrelSource(
const SurfaceTrackState&
state)
noexcept
222void unpackCovariance(
const SurfaceTrackState&
state, DenseMatrix5& covariance)
noexcept
225 for (uint8_t column = 0; column < 5; ++column) {
231void packCovariance(
const DenseMatrix5& covariance, SurfaceTrackState&
state)
noexcept
234 for (uint8_t column = 0; column <=
row; ++column) {
240void identity(DenseMatrix5& matrix)
noexcept
242 for (uint8_t
i = 0;
i < 5; ++
i) {
247void transportCovariance(SurfaceTrackState&
state,
const DenseMatrix5& jacobian)
noexcept
249 DenseMatrix5 covariance{};
250 DenseMatrix5 product{};
251 DenseMatrix5 transported{};
252 unpackCovariance(
state, covariance);
254 for (uint8_t column = 0; column < 5; ++column) {
255 for (uint8_t inner = 0; inner < 5; ++inner) {
256 product[
row][column] += jacobian[
row][inner] * covariance[inner][column];
261 for (uint8_t column = 0; column < 5; ++column) {
262 for (uint8_t inner = 0; inner < 5; ++inner) {
263 transported[
row][column] += product[
row][inner] * jacobian[column][inner];
267 packCovariance(transported,
state);
272bool commitBarrelPropagation(SurfaceTrackState& destination, SurfaceTrackState& scratch)
noexcept
274 sanitizeCovariance(scratch, kBarrelMaxDiagonal);
275 destination = scratch;
279bool residualInverse(
const SurfaceTrackState&
state,
const SurfaceMeasurement& measurement,
280 float& inverse00,
float& inverse01,
float& inverse11)
noexcept
282 if (!(measurement.covariance.uu >= 0.f) || !(measurement.covariance.vv >= 0.f)) {
285 const float s00 =
state.
covariance[packedCovarianceIndex(0, 0)] + measurement.covariance.uu;
286 const float s01 =
state.
covariance[packedCovarianceIndex(1, 0)] + measurement.covariance.uv;
287 const float s11 =
state.
covariance[packedCovarianceIndex(1, 1)] + measurement.covariance.vv;
288 const float determinant = s00 * s11 - s01 * s01;
289 if (determinant == 0.f) {
292 const float inverseDeterminant = 1.f / determinant;
293 inverse00 = s11 * inverseDeterminant;
294 inverse01 = -s01 * inverseDeterminant;
295 inverse11 = s00 * inverseDeterminant;
301bool propagateReferenceParams(SurfaceTrackParameters&
ref,
float targetX,
float bz)
noexcept
303 const float dx = targetX -
ref.referenceCoordinate;
305 ref.referenceCoordinate = targetX;
308 const float snp =
ref.parameters[2];
309 const float curvature =
ref.parameters[4] *
bz * o2::constants::math::B2C;
310 const float propagatedSnp = snp + curvature * dx;
311 if (std::abs(snp) >= 1.f || std::abs(propagatedSnp) >= 1.f) {
314 const float csp = std::sqrt((1.f - snp) * (1.f + snp));
315 const float propagatedCsp = std::sqrt((1.f - propagatedSnp) * (1.f + propagatedSnp));
316 if (csp == 0.f || propagatedCsp == 0.f) {
319 const float reciprocalCosines = 1.f / (csp + propagatedCsp);
320 const float dyOverDx = (snp + propagatedSnp) * reciprocalCosines;
321 const float x2r = curvature * dx;
322 const bool arcZ = std::abs(x2r) > 0.05f;
325 const float argument = csp * propagatedSnp - propagatedCsp * snp;
326 if (std::abs(argument) > 1.f || curvature == 0.f) {
329 float angle = std::asin(argument);
330 if (snp * snp + propagatedSnp * propagatedSnp > 1.f && snp * propagatedSnp < 0.f) {
331 angle = propagatedSnp > 0.f ? o2::constants::math::PI -
angle : -o2::constants::math::PI -
angle;
333 dz =
ref.parameters[3] / curvature *
angle;
335 dz = dx * (propagatedCsp + propagatedSnp * dyOverDx) *
ref.parameters[3];
337 ref.referenceCoordinate = targetX;
338 ref.parameters[0] += dx * dyOverDx;
339 ref.parameters[1] += dz;
340 ref.parameters[2] = propagatedSnp;
346constexpr float kForwardNoRangeLimit = std::numeric_limits<float>::max();
347constexpr float kForwardMaxDiagonal[5] = {kForwardNoRangeLimit, kForwardNoRangeLimit, kForwardNoRangeLimit,
348 kForwardNoRangeLimit, kForwardNoRangeLimit};
350bool validateForwardSource(
const SurfaceTrackState&
state)
noexcept
359bool commitPropagation(SurfaceTrackState& destination, SurfaceTrackState& scratch)
noexcept
361 sanitizeCovariance(scratch, kForwardMaxDiagonal);
362 destination = scratch;
366bool propagateLinear(SurfaceTrackState&
state,
float targetZ)
noexcept
370 if (tanl == 0.f && dz != 0.f) {
376 const float inverseTanl = 1.f / tanl;
377 const float n = dz * inverseTanl;
378 const float m =
n * inverseTanl;
385 DenseMatrix5 jacobian{};
387 jacobian[0][2] = -
n * sinPhi;
388 jacobian[0][3] = -
m * cosPhi;
389 jacobian[1][2] =
n * cosPhi;
390 jacobian[1][3] = -
m * sinPhi;
391 transportCovariance(
state, jacobian);
398template <
typename State>
399bool propagateHelixWithJacobian(State&
state,
float targetZ,
float bz, DenseMatrix5& jacobian)
noexcept
408 if (tanl == 0.f || bz == 0.f || inverseQPt == 0.f) {
411 const float n = dz / tanl;
412 const float curvatureScale = -std::abs(o2::constants::math::B2C) *
bz;
413 const float halfAnglePerQPt = 0.5f * curvatureScale *
n;
414 const float halfAngle = inverseQPt * halfAnglePerQPt;
415 float sinc, sincDerivative;
416 if (std::abs(halfAngle) < 0.25f) {
420 const float h2 = halfAngle * halfAngle;
421 sinc = std::fma(h2, std::fma(h2, std::fma(h2, -1.f / 5040.f, 1.f / 120.f), -1.f / 6.f), 1.f);
422 sincDerivative = halfAngle * std::fma(h2, std::fma(h2, -1.f / 840.f, 1.f / 30.f), -1.f / 3.f);
424 sinc = std::sin(halfAngle) / halfAngle;
425 sincDerivative = (std::cos(halfAngle) - sinc) / halfAngle;
428 const float sinMid = std::sin(phi + halfAngle);
429 const float cosMid = std::cos(phi + halfAngle);
430 const float endPhi =
phi + 2.f * halfAngle;
431 const float dx =
n * sinc * cosMid;
432 const float dy =
n * sinc * sinMid;
434 jacobian[0][2] = -dy;
436 jacobian[0][3] = -
n / tanl * std::cos(endPhi);
437 jacobian[1][3] = -
n / tanl * std::sin(endPhi);
438 jacobian[0][4] =
n * halfAnglePerQPt * std::fma(sincDerivative, cosMid, -sinc * sinMid);
439 jacobian[1][4] =
n * halfAnglePerQPt * std::fma(sincDerivative, sinMid, sinc * cosMid);
440 jacobian[2][3] = -2.f * halfAngle / tanl;
441 jacobian[2][4] = 2.f * halfAnglePerQPt;
450bool propagateHelix(SurfaceTrackState&
state,
float targetZ,
float bz)
noexcept
455 DenseMatrix5 jacobian{};
456 if (!propagateHelixWithJacobian(
state, targetZ, bz, jacobian)) {
459 transportCovariance(
state, jacobian);
463bool propagateAccepted(SurfaceTrackState& destination,
float targetZ,
float bz)
noexcept
465 if (!validateForwardSource(destination)) {
468 SurfaceTrackState scratch = destination;
469 const bool success = std::abs(bz) > 0.01f ? propagateHelix(scratch, targetZ, bz)
470 : propagateLinear(scratch, targetZ);
471 return success && commitPropagation(destination, scratch);
475bool referencePropagateLinear(SurfaceTrackParameters&
ref,
float targetZ, DenseMatrix5& jacobian)
noexcept
478 const float dz = targetZ -
ref.referenceCoordinate;
479 const float tanl =
ref.parameters[3];
480 if (tanl == 0.f && dz != 0.f) {
486 const float inverseTanl = 1.f / tanl;
487 const float n = dz * inverseTanl;
488 const float m =
n * inverseTanl;
489 const float sinPhi = std::sin(
ref.parameters[2]);
490 const float cosPhi = std::cos(
ref.parameters[2]);
491 ref.parameters[0] +=
n * cosPhi;
492 ref.parameters[1] +=
n * sinPhi;
493 ref.referenceCoordinate = targetZ;
495 jacobian[0][2] = -
n * sinPhi;
496 jacobian[0][3] = -
m * cosPhi;
497 jacobian[1][2] =
n * cosPhi;
498 jacobian[1][3] = -
m * sinPhi;
502bool referencePropagateHelix(SurfaceTrackParameters&
ref,
float targetZ,
float bz, DenseMatrix5& jacobian)
noexcept
504 return propagateHelixWithJacobian(
ref, targetZ, bz, jacobian);
507bool propagateAccepted(SurfaceTrackState&
state, SurfaceTrackParameters& linRef,
float targetZ,
float bz)
noexcept
509 if (!validateForwardSource(
state)) {
521 SurfaceTrackParameters scratchRef = linRef;
522 DenseMatrix5 jacobian{};
523 const bool ok = std::abs(bz) > 0.01f ? referencePropagateHelix(scratchRef, targetZ, bz, jacobian)
524 : referencePropagateLinear(scratchRef, targetZ, jacobian);
530 for (uint8_t
i = 0;
i < 5; ++
i) {
534 SurfaceTrackState scratchState =
state;
537 float value = scratchRef.parameters[
row];
538 for (uint8_t column = 0; column < 5; ++column) {
539 value += jacobian[
row][column] * diff[column];
541 scratchState.parameters[
row] =
value;
543 transportCovariance(scratchState, jacobian);
548 sanitizeCovariance(scratchState, kForwardMaxDiagonal);
549 state = scratchState;
558bool Propagator::correctForMaterial(SurfaceTrackState&
state, SurfaceTrackParameters& incidenceReference,
559 material::IntegratedMaterialBudget materialBudget,
562 if (
state.
parameters[4] == 0.f || incidenceReference.parameters[4] == 0.f) {
566 if (!(std::abs(
state.
parameters[2]) < 1.f) || !(std::abs(incidenceReference.parameters[2]) < 1.f)) {
569 }
else if (
state.
parameters[3] == 0.f || incidenceReference.parameters[3] == 0.f) {
572 if (
state.
pid.getID() >= o2::track::PID::NIDsTot) {
578 if (!covarianceDiagonalsNonNegative(
state)) {
582 float momentumBeforeGeV =
state.getP();
583 SurfaceTrackState scratchState =
state;
584 SurfaceTrackParameters scratchReference = incidenceReference;
587 const float tgl = scratchReference.
parameters[3];
588 float incidenceScale;
590 const float snp = scratchReference.parameters[2];
591 const float cosPhi2 = (1.f - snp) * (1.f + snp);
592 const float inverseCosLambda2 = 1.f + tgl * tgl;
593 incidenceScale = std::sqrt(inverseCosLambda2 / cosPhi2);
595 incidenceScale = std::sqrt(1.f + tgl * tgl) / std::abs(tgl);
597 materialBudget.xOverX0 *= incidenceScale;
598 materialBudget.arealDensityGPerCm2 *= incidenceScale;
599 float momentumAfterGeV = 0.f;
600 float highlandTheta2Rad2 = 0.f;
601 float relativeInverseMomentumVariance = 0.f;
603 momentumAfterGeV, highlandTheta2Rad2, relativeInverseMomentumVariance)) {
608 const bool isNoopMaterial = (materialBudget.xOverX0 == 0.f && materialBudget.arealDensityGPerCm2 == 0.f);
609 if (isNoopMaterial) {
613 const float tBefore = scratchState.parameters[3];
614 const float kBefore = scratchState.parameters[4];
615 const float A = 1.f + tBefore * tBefore;
616 const float h = highlandTheta2Rad2;
617 const float R = relativeInverseMomentumVariance;
620 const float snp = scratchState.parameters[2];
621 const float c2 = 1.f - snp * snp;
622 scratchState.covariance[packedCovarianceIndex(2, 2)] +=
h *
A * c2;
624 scratchState.covariance[packedCovarianceIndex(2, 2)] +=
h *
A;
626 scratchState.covariance[packedCovarianceIndex(3, 3)] +=
h *
A *
A;
627 scratchState.covariance[packedCovarianceIndex(4, 3)] +=
h *
A * tBefore * kBefore;
628 scratchState.covariance[packedCovarianceIndex(4, 4)] +=
h * (tBefore * kBefore) * (tBefore * kBefore) + kBefore * kBefore *
R;
630 sanitizeCovariance(scratchState, kBarrelMaxDiagonal);
640 const float kAfter = (momentumBeforeGeV == momentumAfterGeV)
642 : (kBefore * momentumBeforeGeV) / momentumAfterGeV;
643 scratchState.parameters[4] = kAfter;
647 if (scratchState.parameters[4] == 0.f) {
650 float momentumAfterDerived = scratchState.getP();
651 if (!covarianceDiagonalsNonNegative(scratchState)) {
658 const float referenceKBefore = scratchReference.parameters[4];
659 scratchReference.parameters[4] = (momentumBeforeGeV == momentumAfterGeV)
661 : (referenceKBefore * momentumBeforeGeV) / momentumAfterGeV;
662 if (scratchReference.parameters[4] == 0.f || !std::isfinite(scratchReference.parameters[4])) {
666 state = scratchState;
667 incidenceReference = scratchReference;
674 bool chi2GateEnabled,
float maxChi2,
float&
chi2)
noexcept
676 if (!acceptsAttachmentChi2(0.f, chi2GateEnabled, maxChi2)) {
680 AttachmentTransaction transaction{
state,
chi2};
681 auto& scratch = transaction.state;
682 if (!convertKind(scratch, targetSurface.kind, bz)) {
685 const auto materialBudget = targetSurface.material;
686 float predictedChi2 = 0.f;
687 float updateChi2 = 0.f;
690 if (!rotateBarrel(scratch, measurement.frame.frameAngle) ||
691 !propagateBarrel(scratch, measurement.frame.q, bz)) {
695 const auto materialResult = correctForMaterial(scratch, incidenceReference, integratedMaterial, direction);
696 if (!materialResult) {
699 if (!predictedChi2Barrel(scratch, measurement, predictedChi2)) {
702 if (!acceptsAttachmentChi2(predictedChi2, chi2GateEnabled, maxChi2)) {
705 if (!updateBarrel(scratch, measurement, updateChi2)) {
709 if (!propagateToReference(scratch, measurement.frame.q, bz)) {
713 const auto materialResult = correctForMaterial(scratch, incidenceReference, integratedMaterial, direction);
714 if (!materialResult) {
717 if (!predictedChi2Forward(scratch, measurement, predictedChi2)) {
720 if (!acceptsAttachmentChi2(predictedChi2, chi2GateEnabled, maxChi2)) {
723 if (!updateForward(scratch, measurement, updateChi2)) {
729 transaction.chi2 += updateChi2;
737 return propagateBarrel(
state, targetReferenceCoordinate, bz);
740 return propagateForward(
state, targetReferenceCoordinate, bz);
747 float targetReferenceCoordinate,
float bz)
noexcept
753 return propagateBarrel(
state, linRef, targetReferenceCoordinate, bz);
756 return propagateForward(
state, linRef, targetReferenceCoordinate, bz);
774 if (!std::isfinite(
value.referenceCoordinate) || !std::isfinite(
value.alpha)) {
777 for (
float parameter :
value.parameters) {
778 if (!std::isfinite(parameter)) {
782 for (
float covariance :
value.covariance) {
783 if (!std::isfinite(covariance)) {
789 if (!std::isfinite(bz) || !finiteState(
state)) {
793 const bool converted = targetKind ==
SurfaceKind::Disk ? barrelToForward(scratch, bz)
794 : forwardToBarrel(scratch, bz);
795 if (!converted || !finiteState(scratch)) {
805 bool chi2GateEnabled,
float maxChi2,
float&
chi2,
806 bool shiftReferenceToMeasurement)
noexcept
811 if (!acceptsAttachmentChi2(0.f, chi2GateEnabled, maxChi2)) {
820 AttachmentTransaction transaction{
state,
chi2};
821 auto& scratchState = transaction.state;
824 if (scratchState.kind != targetKind) {
825 if (!convertKind(scratchState, targetKind, bz)) {
835 auto& scratchChi2 = transaction.chi2;
836 float predChi2 = 0.f;
837 float updateChi2 = 0.f;
840 if (!rotateBarrel(scratchState, scratchRef, targetMeasurement.frame.frameAngle, bz)) {
843 if (!propagateBarrel(scratchState, scratchRef, targetMeasurement.frame.q, bz)) {
846 clampNegligibleCovarianceNoise(scratchState);
847 const auto materialResult = correctForMaterial(scratchState, scratchRef, materialBudget, direction);
848 if (!materialResult) {
851 if (!predictedChi2Barrel(scratchState, targetMeasurement, predChi2)) {
855 if (!Propagator::propagateToReference(scratchState, scratchRef, targetMeasurement.frame.q, bz)) {
858 clampNegligibleCovarianceNoise(scratchState);
859 const auto materialResult = correctForMaterial(scratchState, scratchRef, materialBudget, direction);
860 if (!materialResult) {
863 if (!predictedChi2Forward(scratchState, targetMeasurement, predChi2)) {
868 if (!acceptsAttachmentChi2(predChi2, chi2GateEnabled, maxChi2)) {
873 if (!updateBarrel(scratchState, targetMeasurement, updateChi2)) {
877 if (!updateForward(scratchState, targetMeasurement, updateChi2)) {
881 scratchChi2 += updateChi2;
882 if (scratchChi2 < 0.f) {
886 if (shiftReferenceToMeasurement) {
888 if (!shiftReferenceToMeasurementBarrel(scratchRef, targetMeasurement)) {
892 if (!shiftReferenceToMeasurementForward(scratchRef, targetMeasurement)) {
905 if (!validateBarrelSource(
state)) {
909 const float canonicalTargetAlpha = std::remainder(targetAlpha, 2.f * o2::constants::math::PI);
910 const float delta = std::remainder(canonicalTargetAlpha - scratch.
alpha, 2.f * o2::constants::math::PI);
911 const float sine = std::sin(delta);
912 const float cosine = std::cos(delta);
914 if (std::abs(snp) >= 1.f) {
917 const float csp = std::sqrt((1.f - snp) * (1.f + snp));
918 const float rotatedCosine = csp * cosine + snp * sine;
919 const float rotatedSnp = snp * cosine - csp * sine;
920 if (rotatedCosine < 0.f || std::abs(rotatedSnp) >= 1.f || csp == 0.f) {
928 scratch.
alpha = canonicalTargetAlpha;
929 const float ratio = cosine + snp / csp * sine;
930 scratch.
covariance[packedCovarianceIndex(0, 0)] *= cosine * cosine;
931 scratch.
covariance[packedCovarianceIndex(1, 0)] *= cosine;
932 scratch.
covariance[packedCovarianceIndex(2, 0)] *= cosine * ratio;
933 scratch.
covariance[packedCovarianceIndex(2, 1)] *= ratio;
934 scratch.
covariance[packedCovarianceIndex(2, 2)] *= ratio * ratio;
935 scratch.
covariance[packedCovarianceIndex(3, 0)] *= cosine;
936 scratch.
covariance[packedCovarianceIndex(3, 2)] *= ratio;
937 scratch.
covariance[packedCovarianceIndex(4, 0)] *= cosine;
938 scratch.
covariance[packedCovarianceIndex(4, 2)] *= ratio;
939 return commitBarrelPropagation(
state, scratch);
944 if (!validateBarrelSource(
state)) {
951 return commitBarrelPropagation(
state, scratch);
954 const float curvature = scratch.
parameters[4] * bz * o2::constants::math::B2C;
955 const float propagatedSnp = snp + curvature * dx;
956 if (std::abs(snp) >= 1.f || std::abs(propagatedSnp) >= 1.f) {
959 const float csp = std::sqrt((1.f - snp) * (1.f + snp));
960 const float propagatedCsp = std::sqrt((1.f - propagatedSnp) * (1.f + propagatedSnp));
961 if (csp == 0.f || propagatedCsp == 0.f) {
964 const float reciprocalCosines = 1.f / (csp + propagatedCsp);
965 const float dyOverDx = (snp + propagatedSnp) * reciprocalCosines;
966 const float x2r = curvature * dx;
967 const bool arcZ = std::abs(x2r) > 0.05f;
970 const float argument = csp * propagatedSnp - propagatedCsp * snp;
971 if (std::abs(argument) > 1.f || curvature == 0.f) {
974 float angle = std::asin(argument);
975 if (snp * snp + propagatedSnp * propagatedSnp > 1.f && snp * propagatedSnp < 0.f) {
976 angle = propagatedSnp > 0.f ? o2::constants::math::PI -
angle : -o2::constants::math::PI -
angle;
980 dz = dx * (propagatedCsp + propagatedSnp * dyOverDx) * scratch.
parameters[3];
987 const float propagatedCspInverse = 1.f / propagatedCsp;
988 const float dxOverCosines = dx * reciprocalCosines;
989 const float hh = dxOverCosines * propagatedCspInverse * (1.f + csp * propagatedCsp + snp * propagatedSnp);
990 const float jj = dx * (dyOverDx - propagatedSnp * propagatedCspInverse);
991 DenseMatrix5 jacobian{};
993 jacobian[0][2] = hh / csp;
994 jacobian[0][4] = hh * dxOverCosines * bz * o2::constants::math::B2C;
995 jacobian[1][2] = scratch.
parameters[3] * (jacobian[0][2] * propagatedSnp + jj);
996 jacobian[1][3] = dx * (propagatedCsp + propagatedSnp * dyOverDx);
997 jacobian[1][4] = scratch.
parameters[3] * (jacobian[0][4] * propagatedSnp + jj * dx * bz * o2::constants::math::B2C);
998 jacobian[2][4] = dx * bz * o2::constants::math::B2C;
999 transportCovariance(scratch, jacobian);
1000 return commitBarrelPropagation(
state, scratch);
1005 if (!validateBarrelSource(
state)) {
1008 float inverse00 = 0.f;
1009 float inverse01 = 0.f;
1010 float inverse11 = 0.f;
1011 if (!residualInverse(
state, measurement, inverse00, inverse01, inverse11)) {
1016 const float scratchChi2 = residualY * (inverse00 * residualY + inverse01 * residualZ) +
1017 residualZ * (inverse01 * residualY + inverse11 * residualZ);
1024 if (!validateBarrelSource(
state)) {
1027 float inverse00 = 0.f;
1028 float inverse01 = 0.f;
1029 float inverse11 = 0.f;
1030 if (!residualInverse(
state, measurement, inverse00, inverse01, inverse11)) {
1033 DenseMatrix5 covariance{};
1034 DenseMatrix5 josephTransform{};
1035 DenseMatrix5 transformedCovariance{};
1036 DenseMatrix5 updatedCovariance{};
1038 unpackCovariance(
state, covariance);
1042 gain[
row][0] = covariance[
row][0] * inverse00 + covariance[
row][1] * inverse01;
1043 gain[
row][1] = covariance[
row][0] * inverse01 + covariance[
row][1] * inverse11;
1049 identity(josephTransform);
1051 josephTransform[
row][0] -= gain[
row][0];
1052 josephTransform[
row][1] -= gain[
row][1];
1055 for (uint8_t column = 0; column < 5; ++column) {
1056 for (uint8_t inner = 0; inner < 5; ++inner) {
1057 transformedCovariance[
row][column] += josephTransform[
row][inner] * covariance[inner][column];
1062 for (uint8_t column = 0; column < 5; ++column) {
1063 for (uint8_t inner = 0; inner < 5; ++inner) {
1064 updatedCovariance[
row][column] += transformedCovariance[
row][inner] * josephTransform[column][inner];
1066 updatedCovariance[
row][column] +=
1067 gain[
row][0] * (measurement.covariance.uu * gain[column][0] + measurement.covariance.uv * gain[column][1]) +
1068 gain[
row][1] * (measurement.covariance.uv * gain[column][0] + measurement.covariance.vv * gain[column][1]);
1072 for (uint8_t column = 0; column <
row; ++column) {
1073 const float symmetric = 0.5f * (updatedCovariance[
row][column] + updatedCovariance[column][
row]);
1074 updatedCovariance[
row][column] = symmetric;
1075 updatedCovariance[column][
row] = symmetric;
1078 packCovariance(updatedCovariance, scratch);
1079 const float scratchChi2 = residual[0] * (inverse00 * residual[0] + inverse01 * residual[1]) +
1080 residual[1] * (inverse01 * residual[0] + inverse11 * residual[1]);
1082 sanitizeCovariance(scratch, kBarrelMaxDiagonal);
1090 if (!validateBarrelSource(
state)) {
1105 if (std::abs(stateSnp) >= 1.f) {
1112 const float canonicalAlpha = std::remainder(targetAlpha, 2.f * o2::constants::math::PI);
1115 const float refSnpBefore = scratchRef.
parameters[2];
1116 if (std::abs(refSnpBefore) >= 1.f) {
1119 const float delta = std::remainder(canonicalAlpha - scratchRef.
alpha, 2.f * o2::constants::math::PI);
1120 const float sa = std::sin(delta);
1121 const float ca = std::cos(delta);
1122 const float refCsp0 = std::sqrt((1.f - refSnpBefore) * (1.f + refSnpBefore));
1123 if (refCsp0 * ca + refSnpBefore * sa < 0.f) {
1126 const float refSnpRotated = refSnpBefore * ca - refCsp0 * sa;
1127 if (std::abs(refSnpRotated) >= 1.f) {
1131 const float refYOld = scratchRef.
parameters[0];
1132 scratchRef.
alpha = canonicalAlpha;
1134 scratchRef.
parameters[0] = -refXOld * sa + refYOld * ca;
1140 if (!propagateReferenceParams(scratchRef, trackX, bz)) {
1145 const float csp = std::sqrt((1.f - stateSnp) * (1.f + stateSnp));
1146 if (csp * ca + stateSnp * sa < 0.f) {
1149 const float updatedSnp = stateSnp * ca - csp * sa;
1150 if (std::abs(updatedSnp) >= 1.f) {
1154 const float stateYOld = scratchState.
parameters[0];
1155 scratchState.
parameters[0] = -stateXOld * sa + stateYOld * ca;
1158 scratchState.
alpha = canonicalAlpha;
1162 const float cspRef1 = ca * refCsp0 + sa * refSnpBefore;
1163 if (cspRef1 == 0.f) {
1166 const float rr = cspRef1 / refCsp0;
1170 const float cXSigY = scratchState.
covariance[packedCovarianceIndex(0, 0)] * ca * sa;
1171 const float cXSigZ = scratchState.
covariance[packedCovarianceIndex(1, 0)] * sa;
1172 const float cXSigSnp = scratchState.
covariance[packedCovarianceIndex(2, 0)] * rr * sa;
1173 const float cXSigTgl = scratchState.
covariance[packedCovarianceIndex(3, 0)] * sa;
1174 const float cXSigQ2Pt = scratchState.
covariance[packedCovarianceIndex(4, 0)] * sa;
1175 const float cSigX2 = scratchState.
covariance[packedCovarianceIndex(0, 0)] * sa * sa;
1177 scratchState.
covariance[packedCovarianceIndex(0, 0)] *= ca * ca;
1178 scratchState.
covariance[packedCovarianceIndex(1, 0)] *= ca;
1179 scratchState.
covariance[packedCovarianceIndex(2, 0)] *= ca * rr;
1180 scratchState.
covariance[packedCovarianceIndex(2, 1)] *= rr;
1181 scratchState.
covariance[packedCovarianceIndex(2, 2)] *= rr * rr;
1182 scratchState.
covariance[packedCovarianceIndex(3, 0)] *= ca;
1183 scratchState.
covariance[packedCovarianceIndex(3, 2)] *= rr;
1184 scratchState.
covariance[packedCovarianceIndex(4, 0)] *= ca;
1185 scratchState.
covariance[packedCovarianceIndex(4, 2)] *= rr;
1187 const float cspRef1Inv = 1.f / cspRef1;
1188 const float j3 = -refSnpRotated * cspRef1Inv;
1189 const float j4 = -scratchRef.
parameters[3] * cspRef1Inv;
1190 const float j5 = scratchRef.
parameters[4] * bz * o2::constants::math::B2C;
1192 const float hXSigY = cXSigY + cSigX2 * j3;
1193 const float hXSigZ = cXSigZ + cSigX2 * j4;
1194 const float hXSigSnp = cXSigSnp + cSigX2 * j5;
1196 scratchState.
covariance[packedCovarianceIndex(0, 0)] += j3 * (cXSigY + hXSigY);
1197 scratchState.
covariance[packedCovarianceIndex(1, 1)] += j4 * (cXSigZ + hXSigZ);
1198 scratchState.
covariance[packedCovarianceIndex(2, 0)] += cXSigSnp * j3 + hXSigY * j5;
1199 scratchState.
covariance[packedCovarianceIndex(2, 2)] += j5 * (cXSigSnp + hXSigSnp);
1200 scratchState.
covariance[packedCovarianceIndex(3, 1)] += cXSigTgl * j4;
1201 scratchState.
covariance[packedCovarianceIndex(4, 0)] += cXSigQ2Pt * j3;
1202 scratchState.
covariance[packedCovarianceIndex(4, 2)] += cXSigQ2Pt * j5;
1204 scratchState.
covariance[packedCovarianceIndex(1, 0)] += cXSigZ * j3 + hXSigY * j4;
1205 scratchState.
covariance[packedCovarianceIndex(2, 1)] += cXSigSnp * j4 + hXSigZ * j5;
1206 scratchState.
covariance[packedCovarianceIndex(3, 0)] += cXSigTgl * j3;
1207 scratchState.
covariance[packedCovarianceIndex(3, 2)] += cXSigTgl * j5;
1208 scratchState.
covariance[packedCovarianceIndex(4, 1)] += cXSigQ2Pt * j4;
1210 sanitizeCovariance(scratchState, kBarrelMaxDiagonal);
1211 state = scratchState;
1212 linRef = scratchRef;
1218 if (!validateBarrelSource(
state)) {
1234 if (std::abs(dx) < o2::constants::math::Almost0) {
1239 state = scratchState;
1240 linRef = scratchRef;
1245 const float snpRef0 = scratchRef.
parameters[2];
1246 const float cspRef0 = std::sqrt((1.f - snpRef0) * (1.f + snpRef0));
1247 const float tglRef0 = scratchRef.
parameters[3];
1249 if (!propagateReferenceParams(scratchRef, targetX, bz)) {
1252 const float snpRef1 = scratchRef.
parameters[2];
1253 const float cspRef1 = std::sqrt((1.f - snpRef1) * (1.f + snpRef1));
1254 if (cspRef0 == 0.f || cspRef1 == 0.f) {
1258 const float kb = bz * o2::constants::math::B2C;
1259 const float cspRef0Inv = 1.f / cspRef0;
1260 const float cspRef1Inv = 1.f / cspRef1;
1261 const float cc = cspRef0 + cspRef1;
1262 const float ccInv = 1.f /
cc;
1263 const float dy2dx = (snpRef0 + snpRef1) * ccInv;
1264 const float dxccInv = dx * ccInv;
1265 const float hh = dxccInv * cspRef1Inv * (1.f + cspRef0 * cspRef1 + snpRef0 * snpRef1);
1266 const float jj = dx * (dy2dx - snpRef1 * cspRef1Inv);
1268 const float f02 = hh * cspRef0Inv;
1269 const float f04 = hh * dxccInv * kb;
1270 const float f24 = dx * kb;
1271 const float f12 = tglRef0 * (f02 * snpRef1 + jj);
1272 const float f13 = dx * (cspRef1 + snpRef1 * dy2dx);
1273 const float f14 = tglRef0 * (f04 * snpRef1 + jj * f24);
1276 for (uint8_t
i = 0;
i < 5; ++
i) {
1279 const float snpUpd = snpRef1 + diff[2] + f24 * diff[4];
1280 if (std::abs(snpUpd) >= 1.f) {
1286 scratchState.
parameters[0] = scratchRef.
parameters[0] + diff[0] + f02 * diff[2] + f04 * diff[4];
1287 scratchState.
parameters[1] = scratchRef.
parameters[1] + diff[1] + f13 * diff[3] + f14 * diff[4];
1308 const float b00 = f02 * c20 + f04 * c40;
1309 const float b01 = f12 * c20 + f14 * c40 + f13 * c30;
1310 const float b02 = f24 * c40;
1311 const float b10 = f02 * c21 + f04 * c41;
1312 const float b11 = f12 * c21 + f14 * c41 + f13 * c31;
1313 const float b12 = f24 * c41;
1314 const float b20 = f02 * c22 + f04 * c42;
1315 const float b21 = f12 * c22 + f14 * c42 + f13 * c32;
1316 const float b22 = f24 * c42;
1317 const float b40 = f02 * c42 + f04 * c44;
1318 const float b41 = f12 * c42 + f14 * c44 + f13 * c43;
1319 const float b42 = f24 * c44;
1320 const float b30 = f02 * c32 + f04 * c43;
1321 const float b31 = f12 * c32 + f14 * c43 + f13 * c33;
1322 const float b32 = f24 * c43;
1324 const float a00 = f02 * b20 + f04 * b40;
1325 const float a01 = f02 * b21 + f04 * b41;
1326 const float a02 = f02 * b22 + f04 * b42;
1327 const float a11 = f12 * b21 + f14 * b41 + f13 * b31;
1328 const float a12 = f12 * b22 + f14 * b42 + f13 * b32;
1329 const float a22 = f24 * b42;
1331 scratchState.
covariance[packedCovarianceIndex(0, 0)] = c00 + b00 + b00 + a00;
1332 scratchState.
covariance[packedCovarianceIndex(1, 0)] = c10 + b10 + b01 + a01;
1333 scratchState.
covariance[packedCovarianceIndex(2, 0)] = c20 + b20 + b02 + a02;
1334 scratchState.
covariance[packedCovarianceIndex(3, 0)] = c30 + b30;
1335 scratchState.
covariance[packedCovarianceIndex(4, 0)] = c40 + b40;
1336 scratchState.
covariance[packedCovarianceIndex(1, 1)] = c11 + b11 + b11 + a11;
1337 scratchState.
covariance[packedCovarianceIndex(2, 1)] = c21 + b21 + b12 + a12;
1338 scratchState.
covariance[packedCovarianceIndex(3, 1)] = c31 + b31;
1339 scratchState.
covariance[packedCovarianceIndex(4, 1)] = c41 + b41;
1340 scratchState.
covariance[packedCovarianceIndex(2, 2)] = c22 + b22 + b22 + a22;
1341 scratchState.
covariance[packedCovarianceIndex(3, 2)] = c32 + b32;
1342 scratchState.
covariance[packedCovarianceIndex(4, 2)] = c42 + b42;
1343 scratchState.
covariance[packedCovarianceIndex(3, 3)] = c33;
1344 scratchState.
covariance[packedCovarianceIndex(4, 3)] = c43;
1345 scratchState.
covariance[packedCovarianceIndex(4, 4)] = c44;
1349 sanitizeCovariance(scratchState, kBarrelMaxDiagonal);
1350 state = scratchState;
1351 linRef = scratchRef;
1369 if (!validateForwardSource(
state)) {
1372 float inverse00 = 0.f;
1373 float inverse01 = 0.f;
1374 float inverse11 = 0.f;
1375 if (!residualInverse(
state, measurement, inverse00, inverse01, inverse11)) {
1380 const float scratchChi2 = residualX * (inverse00 * residualX + inverse01 * residualY) +
1381 residualY * (inverse01 * residualX + inverse11 * residualY);
1388 if (!validateForwardSource(
state)) {
1391 float inverse00 = 0.f;
1392 float inverse01 = 0.f;
1393 float inverse11 = 0.f;
1394 if (!residualInverse(
state, measurement, inverse00, inverse01, inverse11)) {
1398 DenseMatrix5 covariance{};
1399 DenseMatrix5 josephTransform{};
1400 DenseMatrix5 transformedCovariance{};
1401 DenseMatrix5 updatedCovariance{};
1403 unpackCovariance(
state, covariance);
1407 gain[
row][0] = covariance[
row][0] * inverse00 + covariance[
row][1] * inverse01;
1408 gain[
row][1] = covariance[
row][0] * inverse01 + covariance[
row][1] * inverse11;
1414 identity(josephTransform);
1416 josephTransform[
row][0] -= gain[
row][0];
1417 josephTransform[
row][1] -= gain[
row][1];
1420 for (uint8_t column = 0; column < 5; ++column) {
1421 for (uint8_t inner = 0; inner < 5; ++inner) {
1422 transformedCovariance[
row][column] += josephTransform[
row][inner] * covariance[inner][column];
1427 for (uint8_t column = 0; column < 5; ++column) {
1428 for (uint8_t inner = 0; inner < 5; ++inner) {
1429 updatedCovariance[
row][column] += transformedCovariance[
row][inner] * josephTransform[column][inner];
1431 updatedCovariance[
row][column] +=
1432 gain[
row][0] * (measurement.covariance.uu * gain[column][0] + measurement.covariance.uv * gain[column][1]) +
1433 gain[
row][1] * (measurement.covariance.uv * gain[column][0] + measurement.covariance.vv * gain[column][1]);
1437 for (uint8_t column = 0; column <
row; ++column) {
1438 const float symmetric = 0.5f * (updatedCovariance[
row][column] + updatedCovariance[column][
row]);
1439 updatedCovariance[
row][column] = symmetric;
1440 updatedCovariance[column][
row] = symmetric;
1443 packCovariance(updatedCovariance, scratch);
1444 const float scratchChi2 = residual[0] * (inverse00 * residual[0] + inverse01 * residual[1]) +
1445 residual[1] * (inverse01 * residual[0] + inverse11 * residual[1]);
1447 sanitizeCovariance(scratch, kForwardMaxDiagonal);
1467 return propagateAccepted(
state, targetZ, bz);
1471 float targetZ,
float bz)
noexcept
1473 return propagateAccepted(
state, linRef, targetZ, bz);
std::vector< double > sum
Class for time synchronization of RawReader instances.
GLfloat GLfloat GLfloat alpha
GLintptr GLsizeiptr GLboolean commit
GLsizei const GLfloat * value
uint8_t itsSharedClusterMap uint8_t
const TrackingFrameInfo *const const Cluster *const const float const float bz
bool calculateMaterialPhysics(float momentumGeV, o2::track::PID pid, uint8_t absCharge, MaterialTraversalDirection direction, IntegratedMaterialBudget material, float &momentumAfterGeV, float &highlandTheta2Rad2, float &relativeInverseMomentumVariance) noexcept
MaterialTraversalDirection
float referenceCoordinate
float referenceCoordinate
float xOverX0
thickness in units of radiation length
std::vector< o2::mch::ChannelCode > cc