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);
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.