9#include <framework/dataobjects/UncertainHelix.h>
11#include <boost/range/irange.hpp>
12#include <framework/utilities/TestHelpers.h>
13#include <gtest/gtest.h>
22 TEST(UncertainHelixTest, CartesianCovarianceRoundtripWithPerigeeOnOrigin)
24 ROOT::Math::XYZVector expectedMomentum(1.0, 0.0, 0.0);
25 ROOT::Math::XYZVector expectedPosition(0.0, 0.0, 0.0);
26 const double expectedCharge = -1;
28 const double pValue = 0.5;
30 TMatrixDSym expectedCov6(6);
32 expectedCov6(0, 0) = 0;
33 expectedCov6(1, 1) = 2;
34 expectedCov6(2, 2) = 3;
35 expectedCov6(3, 3) = 4;
36 expectedCov6(4, 4) = 5;
37 expectedCov6(5, 5) = 6;
46 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
47 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
48 const double charge = uncertainHelix.getChargeSign();
49 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
51 EXPECT_NEAR(expectedPosition.X(), position.X(), 1e-7);
52 EXPECT_NEAR(expectedPosition.Y(), position.Y(), 1e-7);
53 EXPECT_NEAR(expectedPosition.Z(), position.Z(), 1e-7);
55 EXPECT_NEAR(expectedMomentum.X(), momentum.X(), 1e-7);
56 EXPECT_NEAR(expectedMomentum.Y(), momentum.Y(), 1e-7);
57 EXPECT_NEAR(expectedMomentum.Z(), momentum.Z(), 1e-7);
59 EXPECT_EQ(expectedCharge, charge);
61 for (
int i : irange(0, 6)) {
62 for (
int j : irange(0, 6)) {
63 EXPECT_NEAR(expectedCov6(i, j), cov6(i, j), 1e-7);
69 TEST(UncertainHelixTest, CartesianCovarianceRoundtripAtPerigeeBesidesOrigin)
71 ROOT::Math::XYZVector expectedMomentum(1.0, 0.0, 0.0);
72 ROOT::Math::XYZVector expectedPosition(0.0, 1.0, 0.0);
73 const double expectedCharge = -1;
75 const double pValue = 0.5;
77 TMatrixDSym expectedCov6(6);
79 expectedCov6(0, 0) = 0;
80 for (
int i : irange(1, 6)) {
81 for (
int j : irange(1, 6)) {
83 expectedCov6(i, j) = 1;
87 expectedCov6(1, 1) = 2;
88 expectedCov6(2, 2) = 3;
89 expectedCov6(3, 3) = 4;
90 expectedCov6(4, 4) = 5;
91 expectedCov6(5, 5) = 6;
100 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
101 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
102 const double charge = uncertainHelix.getChargeSign();
103 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
105 EXPECT_NEAR(expectedPosition.X(), position.X(), 1e-7);
106 EXPECT_NEAR(expectedPosition.Y(), position.Y(), 1e-7);
107 EXPECT_NEAR(expectedPosition.Z(), position.Z(), 1e-7);
109 EXPECT_NEAR(expectedMomentum.X(), momentum.X(), 1e-7);
110 EXPECT_NEAR(expectedMomentum.Y(), momentum.Y(), 1e-7);
111 EXPECT_NEAR(expectedMomentum.Z(), momentum.Z(), 1e-7);
113 EXPECT_EQ(expectedCharge, charge);
116 TVectorD nullSpace(6);
117 const double factor =
118 (expectedPosition.X() * expectedMomentum.Y() - expectedPosition.Y() * expectedMomentum.X()) / expectedMomentum.Perp2();
119 nullSpace[0] = expectedMomentum.X();
120 nullSpace[1] = expectedMomentum.Y();
122 nullSpace[3] = factor * expectedMomentum.Y();
123 nullSpace[4] = - factor * expectedMomentum.X();
126 TVectorD nullVector = cov6 * nullSpace;
127 for (
int j : irange(0, 6)) {
128 EXPECT_NEAR(0, nullVector(j), 1e-7);
140 const TMatrixDSym cov6_2 = uncertainHelix2.getCartesianCovariance(bZ);
141 for (
int i : irange(0, 6)) {
142 for (
int j : irange(0, 6)) {
143 EXPECT_NEAR(cov6(i, j), cov6_2(i, j), 1e-7);
148 TEST(UncertainHelixTest, CartesianCovarianceRoundtripAtPerigeeBesidesOriginIndividualCoordinates)
150 ROOT::Math::XYZVector expectedMomentum(1.0, 0.0, 0.0);
151 ROOT::Math::XYZVector expectedPosition(0.0, 1.0, 0.0);
152 const double expectedCharge = -1;
154 const double pValue = 0.5;
156 for (
int i : irange(1, 6)) {
158 TMatrixDSym expectedCov6(6);
160 expectedCov6(0, 0) = 0;
162 expectedCov6(i, i) = 1;
171 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
172 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
173 const double charge = uncertainHelix.getChargeSign();
174 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
176 EXPECT_NEAR(expectedPosition.X(), position.X(), 1e-7);
177 EXPECT_NEAR(expectedPosition.Y(), position.Y(), 1e-7);
178 EXPECT_NEAR(expectedPosition.Z(), position.Z(), 1e-7);
180 EXPECT_NEAR(expectedMomentum.X(), momentum.X(), 1e-7);
181 EXPECT_NEAR(expectedMomentum.Y(), momentum.Y(), 1e-7);
182 EXPECT_NEAR(expectedMomentum.Z(), momentum.Z(), 1e-7);
184 EXPECT_EQ(expectedCharge, charge);
187 TVectorD nullSpace(6);
188 const double factor =
189 (expectedPosition.X() * expectedMomentum.Y() - expectedPosition.Y() * expectedMomentum.X()) / expectedMomentum.Perp2();
190 nullSpace[0] = expectedMomentum.X();
191 nullSpace[1] = expectedMomentum.Y();
193 nullSpace[3] = factor * expectedMomentum.Y();
194 nullSpace[4] = - factor * expectedMomentum.X();
197 TVectorD nullVector = cov6 * nullSpace;
198 for (
int j : irange(0, 6)) {
199 EXPECT_NEAR(0, nullVector(j), 1e-7);
211 const TMatrixDSym cov6_2 = uncertainHelix2.getCartesianCovariance(bZ);
212 for (
int j : irange(0, 6)) {
213 for (
int k : irange(0, 6)) {
214 EXPECT_NEAR(cov6(j, k), cov6_2(j, k), 1e-7);
220 TEST(UncertainHelixTest, PerigeeCovarianceRoundtripAtPerigeeBesidesOriginIndividualCoordinates)
224 double omega = -0.005;
225 double tanLambda = 1;
229 const double pValue = 0.5;
231 for (
int i : irange(0, 5)) {
233 TMatrixDSym expectedCov5(5);
235 expectedCov5(i, i) = 1;
237 UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, expectedCov5, pValue);
239 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
240 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
241 const double charge = uncertainHelix.getChargeSign();
242 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
251 EXPECT_NEAR(d0, uncertainHelix2.getD0(), 1e-7);
252 EXPECT_NEAR(phi0, uncertainHelix2.getPhi0(), 1e-7);
253 EXPECT_NEAR(omega, uncertainHelix2.getOmega(), 1e-7);
255 EXPECT_NEAR(z0, uncertainHelix2.getZ0(), 1e-7);
256 EXPECT_NEAR(tanLambda, uncertainHelix2.getTanLambda(), 1e-7);
258 const TMatrixDSym& cov5 = uncertainHelix2.getCovariance();
259 EXPECT_EQ(-1, charge);
261 for (
int j : irange(0, 5)) {
262 for (
int k : irange(0, 5)) {
263 EXPECT_NEAR(expectedCov5(j, k), cov5(j, k), 1e-7);
269 TEST(UncertainHelixTest, RealPerigeeCovarianceRoundTrip)
271 const double bZ = 1.5;
272 const double pValue = 0.5;
274 std::vector<float> helixParams(5);
275 std::vector<float> helixCovariance(15);
277 helixParams[0] = 3.82384;
278 helixParams[1] = std::remainder(3.57559, 2 * M_PI);
279 helixParams[2] = 0.00530726;
280 helixParams[3] = -0.000317335;
281 helixParams[4] = 1.34536;
283 helixCovariance[0] = 0.000648818;
284 helixCovariance[1] = 6.357e-05;
285 helixCovariance[2] = 2.04344e-07;
286 helixCovariance[3] = -0.00101879;
287 helixCovariance[4] = 2.29407e-05;
289 helixCovariance[5] = 1.02934e-05;
290 helixCovariance[6] = 1.39609e-08;
291 helixCovariance[7] = 9.57685e-07;
292 helixCovariance[8] = 1.19863e-06;
294 helixCovariance[9] = 4.96093e-10;
295 helixCovariance[10] = -8.41612e-07;
296 helixCovariance[11] = 6.50684e-08;
298 helixCovariance[12] = 0.0317385;
299 helixCovariance[13] = -0.00065476;
301 helixCovariance[14] = 3.6521e-05;
303 TMatrixDSym expectedCov5(5);
304 unsigned int counter = 0;
305 for (
unsigned int i = 0; i < 5; ++i) {
306 for (
unsigned int j = i; j < 5; ++j) {
307 expectedCov5(i, j) = expectedCov5(j, i) = helixCovariance[counter];
320 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
321 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
322 const double charge = uncertainHelix.getChargeSign();
323 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
332 EXPECT_NEAR(helixParams[0], uncertainHelix2.getD0(), 1e-7);
333 EXPECT_NEAR(helixParams[1], uncertainHelix2.getPhi0(), 1e-7);
334 EXPECT_NEAR(helixParams[2], uncertainHelix2.getOmega(), 1e-7);
336 EXPECT_NEAR(helixParams[3], uncertainHelix2.getZ0(), 1e-7);
337 EXPECT_NEAR(helixParams[4], uncertainHelix2.getTanLambda(), 1e-7);
339 const TMatrixDSym& cov5 = uncertainHelix2.getCovariance();
340 EXPECT_EQ(1, charge);
342 for (
int i : boost::irange(0, 5)) {
343 for (
int j : boost::irange(0, 5)) {
344 EXPECT_NEAR(expectedCov5(i, j), cov5(i, j), 1e-7);
350 TEST(UncertainHelixTest, Explicit_D0)
354 double omega = -0.005;
355 double tanLambda = 1;
359 const double pValue = 0.5;
361 TMatrixDSym expectedCov5(5);
363 expectedCov5(0, 0) = 1;
365 TMatrixDSym expectedCov6(6);
367 expectedCov6(1, 1) = 1;
369 UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, expectedCov5, pValue);
371 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
373 for (
int i : irange(0, 6)) {
374 for (
int j : irange(0, 6)) {
375 TEST_CONTEXT(
"Failed for index (" << i <<
", " << j <<
")");
376 EXPECT_NEAR(expectedCov6(i, j), cov6(i, j), 1e-7);
381 TEST(UncertainHelixTest, Explicit_Phi0)
385 double omega = -0.006;
386 double tanLambda = 0;
389 const double bZ = 1.5;
390 const double pValue = 0.5;
392 TMatrixDSym expectedCov5(5);
394 expectedCov5(1, 1) = 1;
396 UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, expectedCov5, pValue);
398 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
399 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
400 const double charge = uncertainHelix.getChargeSign();
401 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
403 double absMom2D = uncertainHelix.getTransverseMomentum(1.5);
405 TMatrixDSym expectedCov6(6);
407 expectedCov6(4, 4) = absMom2D * absMom2D;
409 for (
int i : irange(0, 6)) {
410 for (
int j : irange(0, 6)) {
411 TEST_CONTEXT(
"Failed for index (" << i <<
", " << j <<
")");
412 EXPECT_NEAR(expectedCov6(i, j), cov6(i, j), 1e-7);
423 EXPECT_NEAR(d0, uncertainHelix2.getD0(), 1e-7);
424 EXPECT_NEAR(phi0, uncertainHelix2.getPhi0(), 1e-7);
425 EXPECT_NEAR(omega, uncertainHelix2.getOmega(), 1e-7);
427 EXPECT_NEAR(z0, uncertainHelix2.getZ0(), 1e-7);
428 EXPECT_NEAR(tanLambda, uncertainHelix2.getTanLambda(), 1e-7);
430 const TMatrixDSym& cov5 = uncertainHelix2.getCovariance();
431 EXPECT_EQ(-1, charge);
433 for (
int i : irange(0, 5)) {
434 for (
int j : irange(0, 5)) {
435 TEST_CONTEXT(
"Failed for index (" << i <<
", " << j <<
")");
436 EXPECT_NEAR(expectedCov5(i, j), cov5(i, j), 1e-7);
441 TEST(UncertainHelixTest, MoveInCartesianVersusMoveInPerigeeCoordinates)
444 ROOT::Math::XYZVector moveBy(0.5, -1, 0.5);
448 double omega = -0.005;
449 double tanLambda = 1;
453 const double pValue = 0.5;
455 TMatrixDSym initialCov5(5);
457 for (
int i : irange(0, 5)) {
458 for (
int j : irange(0, 5)) {
459 initialCov5(i, j) = i + j;
463 UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, initialCov5, pValue);
465 const ROOT::Math::XYZVector position = uncertainHelix.getPerigee();
466 const ROOT::Math::XYZVector momentum = uncertainHelix.getMomentum(bZ);
467 const double charge = uncertainHelix.getChargeSign();
468 const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
471 const ROOT::Math::XYZVector movedPosition = position - moveBy;
479 const TMatrixDSym& cov5 = movedUncertainHelix.getCovariance();
484 const TMatrixDSym expectedCov5 = expectedMovedUncertainHelix.
getCovariance();
487 EXPECT_NEAR(expectedMovedUncertainHelix.
getD0(), movedUncertainHelix.getD0(), 1e-7);
488 EXPECT_NEAR(expectedMovedUncertainHelix.
getPhi0(), movedUncertainHelix.getPhi0(), 1e-7);
489 EXPECT_NEAR(expectedMovedUncertainHelix.
getOmega(), movedUncertainHelix.getOmega(), 1e-7);
490 EXPECT_NEAR(expectedMovedUncertainHelix.
getZ0(), movedUncertainHelix.getZ0(), 1e-7);
491 EXPECT_NEAR(expectedMovedUncertainHelix.
getTanLambda(), movedUncertainHelix.getTanLambda(), 1e-7);
493 for (
int i : irange(0, 5)) {
494 for (
int j : irange(0, 5)) {
495 TEST_CONTEXT(
"Failed for index (" << i <<
", " << j <<
")");
496 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.