8#include <framework/dataobjects/Helix.h>
10#include <Math/VectorUtil.h>
11#include <Math/Vector2D.h>
15#include <framework/utilities/TestHelpers.h>
17#include <gtest/gtest.h>
21using namespace HelixParameterIndex;
24std::ostream& operator<<(::std::ostream& output,
const TVector3& tVector3)
28 << tVector3.X() <<
", "
29 << tVector3.Y() <<
", "
30 << tVector3.Z() <<
")";
44 bool d0Near = fabs(expected.
getD0() - actual.
getD0()) < tolerance;
47 bool z0Near = fabs(expected.
getZ0() - actual.
getZ0()) < tolerance;
50 return d0Near and phi0Near and omegaNear and z0Near and tanLambdaNear;
55 Belle2::Helix helixFromCenter(
const ROOT::Math::XYZVector& center,
const float& radius,
const float& tanLambda)
57 double omega = 1 / radius;
58 double phi0 = center.Phi() + copysign(M_PI / 2.0, radius);
59 double d0 = copysign(center.Rho(), radius) - radius;
60 double z0 = center.Z();
66 vector<float> linspace(
const float& start,
const float& end,
const int n)
68 std::vector<float> result(n);
72 for (
int i = 1; i < n - 1; ++i) {
73 float start_weight = (float)(n - 1 - i) / (n - 1);
74 float end_weight = 1 - start_weight;
75 result[i] = start * start_weight + end * end_weight;
82 class HelixTest :
public ::testing::Test {
86 double absError = 1e-6;
87 double nominalBz = 1.5;
89 std::vector<float> omegas { -1, 0, 1};
91 std::vector<float> phi0s = linspace(-M_PI, M_PI, 11);
92 std::vector<float> d0s { -0.5, -0.2, 0, 0.2, 0.5};
94 std::vector<float> chis = linspace(-5 * M_PI / 6, 5 * M_PI / 6, 11);
96 std::vector<ROOT::Math::XYZVector> bys = {
97 ROOT::Math::XYZVector(-2.0, 0.5, 0.0),
98 ROOT::Math::XYZVector(-1.0, 0.5, 0.0),
99 ROOT::Math::XYZVector(0.0, 0.5, 0.0),
100 ROOT::Math::XYZVector(1.0, 0.5, 0.0),
101 ROOT::Math::XYZVector(2.0, 0.5, 0.0),
103 ROOT::Math::XYZVector(-2.0, 0.0, 0.0),
104 ROOT::Math::XYZVector(-1.0, 0.0, 0.0),
105 ROOT::Math::XYZVector(0.0, 0.0, 0.0),
106 ROOT::Math::XYZVector(1.0, 0.0, 0.0),
107 ROOT::Math::XYZVector(2.0, 0.0, 0.0),
109 ROOT::Math::XYZVector(-2.0, -1.0, 0.0),
110 ROOT::Math::XYZVector(-1.0, -1.0, 0.0),
111 ROOT::Math::XYZVector(0.0, -1.0, 0.0),
112 ROOT::Math::XYZVector(1.0, -1.0, 0.0),
113 ROOT::Math::XYZVector(2.0, -1.0, 0.0),
119 TEST_F(HelixTest, Getters)
122 unsigned int nCases = 1;
123 double bField = nominalBz;
125 for (
unsigned int i = 0; i < nCases; ++i) {
127 short int charge = generator.Uniform(-1, 1) > 0 ? 1 : -1;
130 ROOT::Math::XYVector d(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
131 ROOT::Math::XYVector pt(generator.Uniform(-1, 1), generator.Uniform(-1, 1));
132 d.SetCoordinates(d.X(), -d.X() * pt.X() / pt.Y());
135 ROOT::Math::XYZVector position(d.X(), d.Y(), generator.Uniform(-1, 1));
136 ROOT::Math::XYZVector momentum(pt.X(), pt.Y(), generator.Uniform(-1, 1));
139 Helix helix(position, momentum, charge, bField);
142 EXPECT_ALL_NEAR(position, helix.getPerigee(), absError);
143 EXPECT_ALL_NEAR(momentum, helix.getMomentum(bField), absError);
146 EXPECT_NEAR(momentum.Rho(), helix.getTransverseMomentum(bField), absError);
149 EXPECT_NEAR(charge / momentum.Rho(), helix.getKappa(bField), absError);
153 EXPECT_NEAR(position.Rho(), fabs(helix.getD0()), absError);
156 EXPECT_SAME_SIGN(position.Cross(momentum).Z(), helix.getD0());
159 EXPECT_NEAR(momentum.Phi(), helix.getPhi0(), absError);
162 EXPECT_NEAR(position.Z(), helix.getZ0(), absError);
165 EXPECT_NEAR(1 / tan(momentum.Theta()), helix.getTanLambda(), absError);
168 EXPECT_NEAR(1 / tan(momentum.Theta()), helix.getCotTheta(), absError);
171 EXPECT_EQ(charge, helix.getChargeSign());
176 TEST_F(HelixTest, SignOfD0)
180 const ROOT::Math::XYZVector position(1, 0, 0);
181 const ROOT::Math::XYZVector momentum(0, 1, 0);
182 const ROOT::Math::XYZVector oppositeMomentum(0, -1, 0);
184 const float bField = nominalBz;
186 Helix helix(position, momentum, charge, bField);
187 EXPECT_NEAR(1, helix.getD0(), absError);
190 Helix helix2(position, momentum, -charge, bField);
191 EXPECT_NEAR(1, helix2.getD0(), absError);
194 Helix oppositeMomentumHelix(position, oppositeMomentum, charge, bField);
195 EXPECT_NEAR(-1, oppositeMomentumHelix.getD0(), absError);
197 Helix oppositeMomentumHelix2(position, oppositeMomentum, -charge, bField);
198 EXPECT_NEAR(-1, oppositeMomentumHelix2.getD0(), absError);
202 TEST_F(HelixTest, Center)
210 ROOT::Math::XYZVector center(0.0, -2.0, 0.0);
215 Helix helix = helixFromCenter(center, radius, tanLambda);
218 EXPECT_NEAR(center.X(), actualCenter.X(), absError);
219 EXPECT_NEAR(center.Y(), actualCenter.Y(), absError);
222 TEST_F(HelixTest, Explicit)
230 ROOT::Math::XYZVector center(0.0, -2.0, 0.0);
235 Helix helix = helixFromCenter(center, radius, tanLambda);
236 EXPECT_NEAR(-1, helix.
getD0(), absError);
237 EXPECT_ANGLE_NEAR(-M_PI, helix.
getPhi0(), absError);
238 EXPECT_NEAR(-1, helix.
getOmega(), absError);
243 float arcLength2D = 0;
247 EXPECT_ALL_NEAR(ROOT::Math::XYZVector(0.0, -1.0, 0.0), position, absError);
248 EXPECT_ANGLE_NEAR(-M_PI, tangential.Phi(), absError);
252 float arcLength2D = M_PI / 2;
255 EXPECT_ALL_NEAR(ROOT::Math::XYZVector(-1.0, -2.0, 0.0), position, absError);
256 EXPECT_ANGLE_NEAR(-M_PI / 2, tangential.Phi(), absError);
260 float arcLength2D = M_PI;
263 EXPECT_ALL_NEAR(ROOT::Math::XYZVector(0.0, -3.0, 0.0), position, absError);
264 EXPECT_ANGLE_NEAR(0, tangential.Phi(), absError);
268 float arcLength2D = 3 * M_PI / 2 ;
271 EXPECT_ALL_NEAR(ROOT::Math::XYZVector(1.0, -2.0, 0.0), position, absError);
272 EXPECT_ANGLE_NEAR(M_PI / 2, tangential.Phi(), absError);
276 TEST_F(HelixTest, Tangential)
281 for (
const float d0 : d0s) {
282 for (
const float phi0 : phi0s) {
283 for (
const float omega : omegas) {
285 Helix helix(d0, phi0, omega, z0, tanLambda);
286 TEST_CONTEXT(
"Failed for " << helix);
290 EXPECT_ANGLE_NEAR(phi0, tangentialAtPerigee.Phi(), absError);
291 EXPECT_FLOAT_EQ(1.0, tangentialAtPerigee.R());
292 EXPECT_FLOAT_EQ(tanLambda, 1 / tan(tangentialAtPerigee.Theta()));
294 for (
const float chi : chis) {
298 float arcLength2D = chi;
302 EXPECT_ALL_NEAR(tangentialAtPerigee, tangential, absError);
305 float arcLength2D = -chi / omega;
308 float actualChi = ROOT::Math::VectorUtil::DeltaPhi(tangentialAtPerigee, tangential);
309 EXPECT_ANGLE_NEAR(chi, actualChi, absError);
310 EXPECT_FLOAT_EQ(tangentialAtPerigee.Theta(), tangential.Theta());
311 EXPECT_FLOAT_EQ(1, tangential.R());
322 TEST_F(HelixTest, MomentumExtrapolation)
325 float tanLambda = -2;
327 for (
const float d0 : d0s) {
328 for (
const float phi0 : phi0s) {
329 for (
const float omega : omegas) {
332 Helix helix(d0, phi0, omega, z0, tanLambda);
333 ROOT::Math::XYZVector momentumAtPerigee = helix.
getMomentum(nominalBz);
334 for (
const float chi : chis) {
336 float arcLength2D = -chi / omega;
339 float actualChi = ROOT::Math::VectorUtil::DeltaPhi(momentumAtPerigee, extrapolatedMomentum);
340 EXPECT_ANGLE_NEAR(chi, actualChi, absError);
341 EXPECT_FLOAT_EQ(momentumAtPerigee.Theta(), extrapolatedMomentum.Theta());
342 EXPECT_FLOAT_EQ(momentumAtPerigee.R(), extrapolatedMomentum.R());
352 TEST_F(HelixTest, Extrapolation)
359 for (
const float d0 : d0s) {
360 for (
const float phi0 : phi0s) {
361 for (
const float omega : omegas) {
363 Helix helix(d0, phi0, omega, z0, tanLambda);
364 ROOT::Math::XYZVector perigee = helix.
getPerigee();
367 TEST_CONTEXT(
"Failed for " << helix);
371 for (
const float chi : chis) {
372 TEST_CONTEXT(
"Failed for chi = " << chi);
376 float expectedArcLength2D = omega != 0 ? -chi / omega : chi;
379 float cylindricalR = pointOnHelix.Rho();
383 EXPECT_NEAR(fabs(expectedArcLength2D), arcLength2D, absError);
386 ROOT::Math::XYZVector secantVector = pointOnHelix - perigee;
388 if (expectedArcLength2D == 0) {
389 EXPECT_NEAR(0, secantVector.R(), absError);
391 ROOT::Math::XYVector secantVectorXY(secantVector.X(), secantVector.Y());
393 ROOT::Math::XYVector tangentialXY(tangentialAtPerigee.X(), tangentialAtPerigee.Y());
394 float coalignment = secantVectorXY.Dot(tangentialXY);
396 bool extrapolationIsForward = coalignment > 0;
397 bool expectedIsForward = expectedArcLength2D > 0;
398 EXPECT_EQ(expectedIsForward, extrapolationIsForward);
407 TEST_F(HelixTest, ExtrapolationToNormalPlane)
410 ROOT::Math::XYZVector center(0.0, 2.0, 0.0);
414 Helix helix = helixFromCenter(center, radius, tanLambda);
422 EXPECT_NEAR(-M_PI / 2, arcLength2D, absError);
426 ROOT::Math::XYZVector center(0.0, 2.0, 0.0);
430 Helix helix = helixFromCenter(center, radius, tanLambda);
438 EXPECT_NEAR(M_PI / 2, arcLength2D, absError);
442 ROOT::Math::XYZVector center(0.0, 2.0, 0.0);
446 Helix helix = helixFromCenter(center, radius, tanLambda);
454 EXPECT_NEAR(M_PI / 2, arcLength2D, absError);
458 ROOT::Math::XYZVector center(0.0, 2.0, 0.0);
462 Helix helix = helixFromCenter(center, radius, tanLambda);
470 EXPECT_NEAR(-M_PI / 2, arcLength2D, absError);
477 TEST_F(HelixTest, PerigeeExtrapolateRoundTrip)
480 float tanLambda = -2;
482 for (
const float d0 : d0s) {
483 for (
const float phi0 : phi0s) {
484 for (
const float omega : omegas) {
488 Helix expectedHelix(d0, phi0, omega, z0, tanLambda);
490 for (
const float chi : chis) {
491 float arcLength2D = -chi / omega;
492 ROOT::Math::XYZVector position = expectedHelix.getPositionAtArcLength2D(arcLength2D);
493 ROOT::Math::XYZVector momentum = expectedHelix.getMomentumAtArcLength2D(arcLength2D, nominalBz);
494 int chargeSign = expectedHelix.getChargeSign();
496 EXPECT_NEAR(tanLambda, 1 / tan(momentum.Theta()), absError);
497 EXPECT_ANGLE_NEAR(phi0 + chi, momentum.Phi(), absError);
498 EXPECT_NEAR(z0 + tanLambda * arcLength2D, position.Z(), absError);
501 Helix helix(position, momentum, chargeSign, nominalBz);
503 EXPECT_NEAR(expectedHelix.getOmega(), helix.
getOmega(), absError);
504 EXPECT_ANGLE_NEAR(expectedHelix.getPhi0(), helix.
getPhi0(), absError);
505 EXPECT_NEAR(expectedHelix.getD0(), helix.
getD0(), absError);
506 EXPECT_NEAR(expectedHelix.getTanLambda(), helix.
getTanLambda(), absError);
507 EXPECT_NEAR(expectedHelix.getZ0(), helix.
getZ0(), absError);
601 TEST_F(HelixTest, PassiveMoveExplicit)
603 ROOT::Math::XYZVector center(0.0, 1.0, 0.0);
607 Helix helix = helixFromCenter(center, radius, tanLambda);
609 ASSERT_NEAR(0, helix.
getD0(), absError);
610 ASSERT_ANGLE_NEAR(0, helix.
getPhi0(), absError);
611 ASSERT_NEAR(-1, helix.
getOmega(), absError);
614 Helix expectedHelix(helix);
618 ROOT::Math::XYZVector by(1.0, 1.0, 0.0);
624 ASSERT_NEAR(M_PI / 2, arcLength2D, absError);
626 ASSERT_NEAR(0, helix.
getD0(), absError);
627 ASSERT_ANGLE_NEAR(M_PI / 2, helix.
getPhi0(), absError);
628 ASSERT_NEAR(-1, helix.
getOmega(), absError);
630 ASSERT_NEAR(3 * M_PI / 2, helix.
getZ0(), absError);
636 ASSERT_NEAR(arcLength2D, -arcLength2DBackward, absError);
637 ASSERT_ALL_NEAR(expectedHelix, helix, absError);
641 TEST_F(HelixTest, PassiveMove)
646 for (
const float phi0 : phi0s) {
647 for (
const float omega : omegas) {
648 for (
const float d0 : d0s) {
649 for (
const float chi : chis) {
650 for (
const float newD0 : d0s) {
651 Helix helix(d0, phi0, omega, z0, tanLambda);
652 TEST_CONTEXT(
"Failed for " << helix);
656 float expectedArcLength2D = omega == 0 ? chi : -chi / omega;
660 ROOT::Math::XYZVector perpendicularToHelix = tangentialToHelix;
661 perpendicularToHelix = ROOT::Math::VectorUtil::RotateZ(perpendicularToHelix, M_PI / 2.0);
663 perpendicularToHelix *= 1 / perpendicularToHelix.Rho();
665 ROOT::Math::XYZVector displacementFromHelix = -perpendicularToHelix * newD0;
666 ROOT::Math::XYZVector testPosition = positionOnHelix + displacementFromHelix;
668 ROOT::Math::XYZVector expectedPerigee = -displacementFromHelix;
670 TEST_CONTEXT(
"Failed for chi " << chi);
671 TEST_CONTEXT(
"Failed for position on helix " << positionOnHelix);
672 TEST_CONTEXT(
"Failed for tangential to helix " << tangentialToHelix);
673 TEST_CONTEXT(
"Failed for perpendicular to helix " << perpendicularToHelix);
674 TEST_CONTEXT(
"Failed for test position " << testPosition);
678 ASSERT_NEAR(expectedArcLength2D, arcLength2D, absError);
680 ASSERT_ALL_NEAR(expectedPerigee, helix.
getPerigee(), absError);
689 TEST_F(HelixTest, calcPassiveMoveByJacobian_identity)
691 ROOT::Math::XYZVector center(0.0, 1.0, 0.0);
695 Helix helix = helixFromCenter(center, radius, tanLambda);
699 EXPECT_NEAR(1.0, noMoveJacobian(0, 0), 1e-7);
700 EXPECT_NEAR(0.0, noMoveJacobian(0, 1), 1e-7);
701 EXPECT_NEAR(0.0, noMoveJacobian(0, 2), 1e-7);
703 EXPECT_NEAR(0.0, noMoveJacobian(1, 0), 1e-7);
704 EXPECT_NEAR(1.0, noMoveJacobian(1, 1), 1e-7);
705 EXPECT_NEAR(0.0, noMoveJacobian(1, 2), 1e-7);
707 EXPECT_NEAR(0.0, noMoveJacobian(2, 0), 1e-7);
708 EXPECT_NEAR(0.0, noMoveJacobian(2, 1), 1e-7);
709 EXPECT_NEAR(1.0, noMoveJacobian(2, 2), 1e-7);
712 TEST_F(HelixTest, calcPassiveMoveByJacobian_orthogonalToPhi0)
714 ROOT::Math::XYZVector center(0.0, 1.0, 0.0);
718 Helix helix = helixFromCenter(center, radius, tanLambda);
722 EXPECT_NEAR(1.0, moveByOneJacobian(iD0, iD0), 1e-7);
723 EXPECT_NEAR(0.0, moveByOneJacobian(iD0, iPhi0), 1e-7);
724 EXPECT_NEAR(0.0, moveByOneJacobian(iD0, iOmega), 1e-7);
726 EXPECT_NEAR(0.0, moveByOneJacobian(iPhi0, iD0), 1e-7);
727 EXPECT_NEAR(1.0 / 2.0, moveByOneJacobian(iPhi0, iPhi0), 1e-7);
728 EXPECT_NEAR(0.0, moveByOneJacobian(iPhi0, iOmega), 1e-7);
730 EXPECT_NEAR(0.0, moveByOneJacobian(iOmega, iD0), 1e-7);
731 EXPECT_NEAR(0.0, moveByOneJacobian(iOmega, iPhi0), 1e-7);
732 EXPECT_NEAR(1.0, moveByOneJacobian(iOmega, iOmega), 1e-7);
736 TEST_F(HelixTest, calcPassiveMoveByJacobian_parallelToPhi0_compare_opposite_transformation)
738 ROOT::Math::XYZVector center(0.0, 1.0, 0.0);
742 Helix helix = helixFromCenter(center, radius, tanLambda);
747 EXPECT_NEAR(1.0, moveByPlusTwoXJacobian(iOmega, iOmega), 1e-7);
748 EXPECT_NEAR(0.0, moveByPlusTwoXJacobian(iOmega, iPhi0), 1e-7);
749 EXPECT_NEAR(0.0, moveByPlusTwoXJacobian(iOmega, iD0), 1e-7);
751 EXPECT_NEAR(1.0, moveByMinusTwoXJacobian(iOmega, iOmega), 1e-7);
752 EXPECT_NEAR(0.0, moveByMinusTwoXJacobian(iOmega, iPhi0), 1e-7);
753 EXPECT_NEAR(0.0, moveByMinusTwoXJacobian(iOmega, iD0), 1e-7);
756 EXPECT_NEAR(moveByMinusTwoXJacobian(iD0, iOmega), moveByPlusTwoXJacobian(iD0, iOmega), 1e-7);
757 EXPECT_NEAR(moveByMinusTwoXJacobian(iPhi0, iPhi0), moveByPlusTwoXJacobian(iPhi0, iPhi0), 1e-7);
758 EXPECT_NEAR(moveByMinusTwoXJacobian(iD0, iD0), moveByPlusTwoXJacobian(iD0, iD0), 1e-7);
761 EXPECT_NEAR(moveByMinusTwoXJacobian(iD0, iPhi0), -moveByPlusTwoXJacobian(iD0, iPhi0), 1e-7);
762 EXPECT_NEAR(moveByMinusTwoXJacobian(iPhi0, iD0), -moveByPlusTwoXJacobian(iPhi0, iD0), 1e-7);
763 EXPECT_NEAR(moveByMinusTwoXJacobian(iPhi0, iOmega), -moveByPlusTwoXJacobian(iPhi0, iOmega), 1e-7);
766 EXPECT_NEGATIVE(moveByPlusTwoXJacobian(iD0, iPhi0));
767 EXPECT_POSITIVE(moveByPlusTwoXJacobian(iD0, iOmega));
768 EXPECT_POSITIVE(moveByPlusTwoXJacobian(iPhi0, iD0));
769 EXPECT_NEGATIVE(moveByPlusTwoXJacobian(iPhi0, iOmega));
771 EXPECT_NEGATIVE(moveByPlusTwoXJacobian(iD0, iD0) - 1);
772 EXPECT_NEGATIVE(moveByPlusTwoXJacobian(iPhi0, iPhi0) - 1);
775 TEST_F(HelixTest, calcPassiveMoveByJacobian_roundtrip)
777 for (
const auto& by : bys) {
778 ROOT::Math::XYZVector center(0.0, 1.0, 0.0);
782 Helix helix = helixFromCenter(center, radius, tanLambda);
789 TMatrixD unitMatrix = reverseJacobian * jacobian;
791 for (
int i = 0; i < 5; ++i) {
792 for (
int j = 0; j < 5; ++j) {
795 EXPECT_NEAR(1, unitMatrix(i, j), 1e-7);
798 EXPECT_NEAR(0, unitMatrix(i, j), 1e-7);
807 TEST_F(HelixTest, calcPassiveMoveByJacobian_parallelToPhi0)
809 ROOT::Math::XYZVector center(1.0, 0.0, 0.0);
813 Helix helix = helixFromCenter(center, radius, tanLambda);
818 double deltaParallel = 2;
824 double lambda = 1.0 / (5.0 + 3.0 * sqrt(5.0));
825 double mu = sqrt(5.0) / 10.0;
828 EXPECT_NEAR(1.0, moveByTwoYJacobian(iOmega, iOmega), 1e-7);
829 EXPECT_NEAR(0.0, moveByTwoYJacobian(iOmega, iPhi0), 1e-7);
830 EXPECT_NEAR(0.0, moveByTwoYJacobian(iOmega, iD0), 1e-7);
832 EXPECT_NEAR(2.0 / 5.0, moveByTwoYJacobian(iPhi0, iOmega), 1e-7);
833 EXPECT_NEAR(1.0 / 5.0, moveByTwoYJacobian(iPhi0, iPhi0), 1e-7);
834 EXPECT_NEAR(-2.0 / 5.0, moveByTwoYJacobian(iPhi0, iD0), 1e-7);
836 EXPECT_NEAR(mu * zeta - A * lambda, moveByTwoYJacobian(iD0, iOmega), 1e-7);
837 EXPECT_NEAR(2.0 * mu * u * deltaParallel, moveByTwoYJacobian(iD0, iPhi0), 1e-7);
838 EXPECT_NEAR(2.0 * mu * nu, moveByTwoYJacobian(iD0, iD0), 1e-7);
843 TEST_F(HelixTest, calcPassiveMoveByJacobian_consistency_of_expansion)
845 ROOT::Math::XYZVector center(0.0, 1.0, 0.0);
849 Helix helix = helixFromCenter(center, radius, tanLambda);
851 for (
const auto& by : bys) {
855 EXPECT_NEAR(1.0, jacobian(iOmega, iOmega), 1e-7);
856 EXPECT_NEAR(0.0, jacobian(iOmega, iPhi0), 1e-7);
857 EXPECT_NEAR(0.0, jacobian(iOmega, iD0), 1e-7);
859 EXPECT_NEAR(1.0, jacobianWithExpansion(iOmega, iOmega), 1e-7);
860 EXPECT_NEAR(0.0, jacobianWithExpansion(iOmega, iPhi0), 1e-7);
861 EXPECT_NEAR(0.0, jacobianWithExpansion(iOmega, iD0), 1e-7);
863 EXPECT_NEAR(jacobianWithExpansion(iD0, iD0), jacobian(iD0, iD0), 1e-7);
864 EXPECT_NEAR(jacobianWithExpansion(iD0, iPhi0), jacobian(iD0, iPhi0), 1e-7);
865 EXPECT_NEAR(jacobianWithExpansion(iD0, iOmega), jacobian(iD0, iOmega), 1e-7);
867 EXPECT_NEAR(jacobianWithExpansion(iPhi0, iD0), jacobian(iPhi0, iD0), 1e-7);
868 EXPECT_NEAR(jacobianWithExpansion(iPhi0, iPhi0), jacobian(iPhi0, iPhi0), 1e-7);
869 EXPECT_NEAR(jacobianWithExpansion(iPhi0, iOmega), jacobian(iPhi0, iOmega), 1e-7);
873 TEST_F(HelixTest, realExample)
876 std::vector<double> helixParams(5);
877 helixParams[0] = 3.82384;
878 helixParams[1] = std::remainder(3.575595, 2 * M_PI);
879 helixParams[2] = 0.00530726;
880 helixParams[3] = -0.000317335;
881 helixParams[4] = 1.34536;
883 ROOT::Math::XYZVector momentum(-0.768755, -0.356297, 1.13994);
884 ROOT::Math::XYZVector position(-1.60794, 3.46933, -0.000317335);
890 const double bZ = 1.5;
893 EXPECT_NEAR(0.0, momentum.X() * position.X() + momentum.Y() * position.Y(), 1e-6);
895 Helix helix(helixParams[0], helixParams[1], helixParams[2], helixParams[3], helixParams[4]);
897 EXPECT_ALL_NEAR(momentum, helix.
getMomentum(bZ), 1e-5);
898 EXPECT_ALL_NEAR(position, helix.
getPerigee(), 1e-5);
902 TEST_F(HelixTest, omegaForUnitMomentum)
904 ROOT::Math::XYZVector expectedMomentum(1.0, 0.0, 0.0);
905 ROOT::Math::XYZVector expectedPosition(0.0, 1.0, 0.0);
906 const double expectedCharge = 1;
907 const double bZ = 1.5;
909 Helix helix(expectedPosition, expectedMomentum, expectedCharge, bZ);
911 double expectedOmega = 0.0044968868700000003;
912 EXPECT_ALL_NEAR(expectedOmega, helix.
getOmega(), 1e-7);
This class represents an ideal helix in perigee parameterization.
double getArcLength2DAtCylindricalR(const double &cylindricalR) const
Calculates the transverse travel distance at the point the helix first reaches the given cylindrical ...
double getOmega() const
Getter for omega, which is a signed curvature measure of the track.
ROOT::Math::XYZVector getPositionAtArcLength2D(const double &arcLength2D) const
Calculates the position on the helix at the given two dimensional arc length.
ROOT::Math::XYZVector getUnitTangentialAtArcLength2D(const double &arcLength2D) const
Calculates the unit tangential vector to the helix curve at the given two dimensional arc length.
double getD0() const
Getter for d0, which is the signed distance to the perigee in the r-phi plane.
ROOT::Math::XYZVector getMomentum(const double bZ) const
Getter for vector of momentum at the perigee position.
double passiveMoveBy(const ROOT::Math::XYZVector &by)
Moves origin of the coordinate system (passive transformation) by the given vector.
double getArcLength2DAtNormalPlane(const double &x, const double &y, const double &nX, const double &nY) const
Calculates the arc length to reach a plane parallel to the z axes.
double getTanLambda() const
Getter for tan lambda, which is the z over two dimensional arc length slope of the track.
TMatrixD calcPassiveMoveByJacobian(const ROOT::Math::XYZVector &by, const double expandBelowChi=M_PI/8) const
Calculate the 5x5 jacobian matrix for the transport of the helix parameters, when moving the origin o...
double getZ0() const
Getter for z0, which is the z coordinate of the perigee.
ROOT::Math::XYZVector getMomentumAtArcLength2D(const double &arcLength2D, const double &bz) const
Calculates the momentum vector at the given two dimensional arc length.
ROOT::Math::XYZVector getPerigee() const
Getter for the perigee position.
double getPhi0() const
Getter for phi0, which is the azimuth angle of the transverse momentum at the perigee.
double charge(int pdgCode)
Returns electric charge of a particle with given pdg code.
Some utilities to help with writing unit tests.
bool angleNear(double expected, double actual, double tolerance)
Predicate checking that two angular values are close to each other modulus a 2 * PI difference.
bool allNear< Belle2::Helix >(const Belle2::Helix &expected, const Belle2::Helix &actual, double tolerance)
Predicate checking that all five components of the Helix are close by a maximal error of absError.
Abstract base class for different kinds of events.