9#include <framework/dataobjects/UncertainHelix.h>
11#include <framework/utilities/TestHelpers.h>
12#include <gtest/gtest.h>
19 TEST(UncertainHelixTest, CartesianCovarianceRoundtripWithPerigeeOnOrigin)
21 ROOT::Math::XYZVector expectedMomentum(1.0, 0.0, 0.0);
22 ROOT::Math::XYZVector expectedPosition(0.0, 0.0, 0.0);
23 const double expectedCharge = -1;
25 const double pValue = 0.5;
27 TMatrixDSym expectedCov6(6);
29 expectedCov6(0, 0) = 0;
30 expectedCov6(1, 1) = 2;
31 expectedCov6(2, 2) = 3;
32 expectedCov6(3, 3) = 4;
33 expectedCov6(4, 4) = 5;
34 expectedCov6(5, 5) = 6;
43 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
44 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
45 const double charge = uncertainHelix.getChargeSign();
46 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
48 EXPECT_NEAR(expectedPosition.X(), position.X(), 1e-7);
49 EXPECT_NEAR(expectedPosition.Y(), position.Y(), 1e-7);
50 EXPECT_NEAR(expectedPosition.Z(), position.Z(), 1e-7);
52 EXPECT_NEAR(expectedMomentum.X(), momentum.X(), 1e-7);
53 EXPECT_NEAR(expectedMomentum.Y(), momentum.Y(), 1e-7);
54 EXPECT_NEAR(expectedMomentum.Z(), momentum.Z(), 1e-7);
56 EXPECT_EQ(expectedCharge, charge);
58 for (
int i = 0; i < 6; ++i) {
59 for (
int j = 0; j < 6; ++j) {
60 EXPECT_NEAR(expectedCov6(i, j), cov6(i, j), 1e-7);
66 TEST(UncertainHelixTest, CartesianCovarianceRoundtripAtPerigeeBesidesOrigin)
68 ROOT::Math::XYZVector expectedMomentum(1.0, 0.0, 0.0);
69 ROOT::Math::XYZVector expectedPosition(0.0, 1.0, 0.0);
70 const double expectedCharge = -1;
72 const double pValue = 0.5;
74 TMatrixDSym expectedCov6(6);
76 expectedCov6(0, 0) = 0;
77 for (
int i = 1; i < 6; ++i) {
78 for (
int j = 1; j < 6; ++j) {
80 expectedCov6(i, j) = 1;
84 expectedCov6(1, 1) = 2;
85 expectedCov6(2, 2) = 3;
86 expectedCov6(3, 3) = 4;
87 expectedCov6(4, 4) = 5;
88 expectedCov6(5, 5) = 6;
97 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
98 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
99 const double charge = uncertainHelix.getChargeSign();
100 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
102 EXPECT_NEAR(expectedPosition.X(), position.X(), 1e-7);
103 EXPECT_NEAR(expectedPosition.Y(), position.Y(), 1e-7);
104 EXPECT_NEAR(expectedPosition.Z(), position.Z(), 1e-7);
106 EXPECT_NEAR(expectedMomentum.X(), momentum.X(), 1e-7);
107 EXPECT_NEAR(expectedMomentum.Y(), momentum.Y(), 1e-7);
108 EXPECT_NEAR(expectedMomentum.Z(), momentum.Z(), 1e-7);
110 EXPECT_EQ(expectedCharge, charge);
113 TVectorD nullSpace(6);
114 const double factor =
115 (expectedPosition.X() * expectedMomentum.Y() - expectedPosition.Y() * expectedMomentum.X()) / expectedMomentum.Perp2();
116 nullSpace[0] = expectedMomentum.X();
117 nullSpace[1] = expectedMomentum.Y();
119 nullSpace[3] = factor * expectedMomentum.Y();
120 nullSpace[4] = - factor * expectedMomentum.X();
123 TVectorD nullVector = cov6 * nullSpace;
124 for (
int j = 0; j < 6; ++j) {
125 EXPECT_NEAR(0, nullVector(j), 1e-7);
137 const TMatrixDSym cov6_2 = uncertainHelix2.getCartesianCovariance(bZ);
138 for (
int i = 0; i < 6; ++i) {
139 for (
int j = 0; j < 6; ++j) {
140 EXPECT_NEAR(cov6(i, j), cov6_2(i, j), 1e-7);
145 TEST(UncertainHelixTest, CartesianCovarianceRoundtripAtPerigeeBesidesOriginIndividualCoordinates)
147 ROOT::Math::XYZVector expectedMomentum(1.0, 0.0, 0.0);
148 ROOT::Math::XYZVector expectedPosition(0.0, 1.0, 0.0);
149 const double expectedCharge = -1;
151 const double pValue = 0.5;
153 for (
int i = 1; i < 6; ++i) {
155 TMatrixDSym expectedCov6(6);
157 expectedCov6(0, 0) = 0;
159 expectedCov6(i, i) = 1;
168 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
169 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
170 const double charge = uncertainHelix.getChargeSign();
171 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
173 EXPECT_NEAR(expectedPosition.X(), position.X(), 1e-7);
174 EXPECT_NEAR(expectedPosition.Y(), position.Y(), 1e-7);
175 EXPECT_NEAR(expectedPosition.Z(), position.Z(), 1e-7);
177 EXPECT_NEAR(expectedMomentum.X(), momentum.X(), 1e-7);
178 EXPECT_NEAR(expectedMomentum.Y(), momentum.Y(), 1e-7);
179 EXPECT_NEAR(expectedMomentum.Z(), momentum.Z(), 1e-7);
181 EXPECT_EQ(expectedCharge, charge);
184 TVectorD nullSpace(6);
185 const double factor =
186 (expectedPosition.X() * expectedMomentum.Y() - expectedPosition.Y() * expectedMomentum.X()) / expectedMomentum.Perp2();
187 nullSpace[0] = expectedMomentum.X();
188 nullSpace[1] = expectedMomentum.Y();
190 nullSpace[3] = factor * expectedMomentum.Y();
191 nullSpace[4] = - factor * expectedMomentum.X();
194 TVectorD nullVector = cov6 * nullSpace;
195 for (
int j = 0; j < 6; ++j) {
196 EXPECT_NEAR(0, nullVector(j), 1e-7);
208 const TMatrixDSym cov6_2 = uncertainHelix2.getCartesianCovariance(bZ);
209 for (
int j = 0; j < 6; ++j) {
210 for (
int k = 0; k < 6; ++k) {
211 EXPECT_NEAR(cov6(j, k), cov6_2(j, k), 1e-7);
217 TEST(UncertainHelixTest, PerigeeCovarianceRoundtripAtPerigeeBesidesOriginIndividualCoordinates)
221 double omega = -0.005;
222 double tanLambda = 1;
226 const double pValue = 0.5;
228 for (
int i = 0; i < 5; ++i) {
230 TMatrixDSym expectedCov5(5);
232 expectedCov5(i, i) = 1;
234 UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, expectedCov5, pValue);
236 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
237 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
238 const double charge = uncertainHelix.getChargeSign();
239 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
248 EXPECT_NEAR(d0, uncertainHelix2.getD0(), 1e-7);
249 EXPECT_NEAR(phi0, uncertainHelix2.getPhi0(), 1e-7);
250 EXPECT_NEAR(omega, uncertainHelix2.getOmega(), 1e-7);
252 EXPECT_NEAR(z0, uncertainHelix2.getZ0(), 1e-7);
253 EXPECT_NEAR(tanLambda, uncertainHelix2.getTanLambda(), 1e-7);
255 const TMatrixDSym& cov5 = uncertainHelix2.getCovariance();
256 EXPECT_EQ(-1, charge);
258 for (
int j = 0; j < 5; ++j) {
259 for (
int k = 0; k < 5; ++k) {
260 EXPECT_NEAR(expectedCov5(j, k), cov5(j, k), 1e-7);
266 TEST(UncertainHelixTest, RealPerigeeCovarianceRoundTrip)
268 const double bZ = 1.5;
269 const double pValue = 0.5;
271 std::vector<float> helixParams(5);
272 std::vector<float> helixCovariance(15);
274 helixParams[0] = 3.82384;
275 helixParams[1] = std::remainder(3.57559, 2 * M_PI);
276 helixParams[2] = 0.00530726;
277 helixParams[3] = -0.000317335;
278 helixParams[4] = 1.34536;
280 helixCovariance[0] = 0.000648818;
281 helixCovariance[1] = 6.357e-05;
282 helixCovariance[2] = 2.04344e-07;
283 helixCovariance[3] = -0.00101879;
284 helixCovariance[4] = 2.29407e-05;
286 helixCovariance[5] = 1.02934e-05;
287 helixCovariance[6] = 1.39609e-08;
288 helixCovariance[7] = 9.57685e-07;
289 helixCovariance[8] = 1.19863e-06;
291 helixCovariance[9] = 4.96093e-10;
292 helixCovariance[10] = -8.41612e-07;
293 helixCovariance[11] = 6.50684e-08;
295 helixCovariance[12] = 0.0317385;
296 helixCovariance[13] = -0.00065476;
298 helixCovariance[14] = 3.6521e-05;
300 TMatrixDSym expectedCov5(5);
301 unsigned int counter = 0;
302 for (
unsigned int i = 0; i < 5; ++i) {
303 for (
unsigned int j = i; j < 5; ++j) {
304 expectedCov5(i, j) = expectedCov5(j, i) = helixCovariance[counter];
317 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
318 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
319 const double charge = uncertainHelix.getChargeSign();
320 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
329 EXPECT_NEAR(helixParams[0], uncertainHelix2.getD0(), 1e-7);
330 EXPECT_NEAR(helixParams[1], uncertainHelix2.getPhi0(), 1e-7);
331 EXPECT_NEAR(helixParams[2], uncertainHelix2.getOmega(), 1e-7);
333 EXPECT_NEAR(helixParams[3], uncertainHelix2.getZ0(), 1e-7);
334 EXPECT_NEAR(helixParams[4], uncertainHelix2.getTanLambda(), 1e-7);
336 const TMatrixDSym& cov5 = uncertainHelix2.getCovariance();
337 EXPECT_EQ(1, charge);
339 for (
int i = 0; i < 5; ++i) {
340 for (
int j = 0; j < 5; ++j) {
341 EXPECT_NEAR(expectedCov5(i, j), cov5(i, j), 1e-7);
347 TEST(UncertainHelixTest, Explicit_D0)
351 double omega = -0.005;
352 double tanLambda = 1;
356 const double pValue = 0.5;
358 TMatrixDSym expectedCov5(5);
360 expectedCov5(0, 0) = 1;
362 TMatrixDSym expectedCov6(6);
364 expectedCov6(1, 1) = 1;
366 UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, expectedCov5, pValue);
368 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
370 for (
int i = 0; i < 6; ++i) {
371 for (
int j = 0; j < 6; ++j) {
372 TEST_CONTEXT(
"Failed for index (" << i <<
", " << j <<
")");
373 EXPECT_NEAR(expectedCov6(i, j), cov6(i, j), 1e-7);
378 TEST(UncertainHelixTest, Explicit_Phi0)
382 double omega = -0.006;
383 double tanLambda = 0;
386 const double bZ = 1.5;
387 const double pValue = 0.5;
389 TMatrixDSym expectedCov5(5);
391 expectedCov5(1, 1) = 1;
393 UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, expectedCov5, pValue);
395 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
396 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
397 const double charge = uncertainHelix.getChargeSign();
398 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
400 double absMom2D = uncertainHelix.getTransverseMomentum(1.5);
402 TMatrixDSym expectedCov6(6);
404 expectedCov6(4, 4) = absMom2D * absMom2D;
406 for (
int i = 0; i < 6; ++i) {
407 for (
int j = 0; j < 6; ++j) {
408 TEST_CONTEXT(
"Failed for index (" << i <<
", " << j <<
")");
409 EXPECT_NEAR(expectedCov6(i, j), cov6(i, j), 1e-7);
420 EXPECT_NEAR(d0, uncertainHelix2.getD0(), 1e-7);
421 EXPECT_NEAR(phi0, uncertainHelix2.getPhi0(), 1e-7);
422 EXPECT_NEAR(omega, uncertainHelix2.getOmega(), 1e-7);
424 EXPECT_NEAR(z0, uncertainHelix2.getZ0(), 1e-7);
425 EXPECT_NEAR(tanLambda, uncertainHelix2.getTanLambda(), 1e-7);
427 const TMatrixDSym& cov5 = uncertainHelix2.getCovariance();
428 EXPECT_EQ(-1, charge);
430 for (
int i = 0; i < 5; ++i) {
431 for (
int j = 0; j < 5; ++j) {
432 TEST_CONTEXT(
"Failed for index (" << i <<
", " << j <<
")");
433 EXPECT_NEAR(expectedCov5(i, j), cov5(i, j), 1e-7);
438 TEST(UncertainHelixTest, MoveInCartesianVersusMoveInPerigeeCoordinates)
441 ROOT::Math::XYZVector moveBy(0.5, -1, 0.5);
445 double omega = -0.005;
446 double tanLambda = 1;
450 const double pValue = 0.5;
452 TMatrixDSym initialCov5(5);
454 for (
int i = 0; i < 5; ++i) {
455 for (
int j = 0; j < 5; ++j) {
456 initialCov5(i, j) = i + j;
460 UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, initialCov5, pValue);
462 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
463 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
464 const double charge = uncertainHelix.getChargeSign();
465 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
468 const ROOT::Math::XYZVector movedPosition = position - moveBy;
476 const TMatrixDSym& cov5 = movedUncertainHelix.getCovariance();
481 const TMatrixDSym expectedCov5 = expectedMovedUncertainHelix.
getCovariance();
484 EXPECT_NEAR(expectedMovedUncertainHelix.
getD0(), movedUncertainHelix.getD0(), 1e-7);
485 EXPECT_NEAR(expectedMovedUncertainHelix.
getPhi0(), movedUncertainHelix.getPhi0(), 1e-7);
486 EXPECT_NEAR(expectedMovedUncertainHelix.
getOmega(), movedUncertainHelix.getOmega(), 1e-7);
487 EXPECT_NEAR(expectedMovedUncertainHelix.
getZ0(), movedUncertainHelix.getZ0(), 1e-7);
488 EXPECT_NEAR(expectedMovedUncertainHelix.
getTanLambda(), movedUncertainHelix.getTanLambda(), 1e-7);
490 for (
int i = 0; i < 5; ++i) {
491 for (
int j = 0; j < 5; ++j) {
492 TEST_CONTEXT(
"Failed for index (" << i <<
", " << j <<
")");
493 EXPECT_NEAR(expectedCov5(i, j), cov5(i, j), 1e-7);
double getOmega() const
Getter for omega, which is a signed curvature measure of the track.
double getD0() const
Getter for d0, which is the signed distance to the perigee in the r-phi plane.
double getTanLambda() const
Getter for tan lambda, which is the z over two dimensional arc length slope of the track.
double getZ0() const
Getter for z0, which is the z coordinate of the perigee.
double getPhi0() const
Getter for phi0, which is the azimuth angle of the transverse momentum at the perigee.
This class represents an ideal helix in perigee parameterization including the covariance matrix of t...
double passiveMoveBy(const ROOT::Math::XYZVector &by)
Moves origin of the coordinate system (passive transformation) by the given vector.
const TMatrixDSym & getCovariance() const
Getter for covariance matrix of perigee parameters in matrix form.
double charge(int pdgCode)
Returns electric charge of a particle with given pdg code.
Abstract base class for different kinds of events.