Belle II Software  release-05-01-25
UncertainHelix.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2014 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Oliver Frost <oliver.frost@desy.de> *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <framework/dataobjects/UncertainHelix.h>
12 #include <TVectorD.h>
13 #include <boost/range/irange.hpp>
14 #include <framework/utilities/TestHelpers.h>
15 #include <gtest/gtest.h>
16 
17 using boost::irange;
18 
19 using namespace std;
20 using namespace Belle2;
21 
22 namespace {
23 
24  TEST(UncertainHelixTest, CartesianCovarianceRoundtripWithPerigeeOnOrigin)
25  {
26  TVector3 expectedMomentum(1.0, 0.0, 0.0);
27  TVector3 expectedPosition(0.0, 0.0, 0.0);
28  const double expectedCharge = -1;
29  const double bZ = 2;
30  const double pValue = 0.5;
31 
32  TMatrixDSym expectedCov6(6);
33  expectedCov6.Zero();
34  expectedCov6(0, 0) = 0; // There cannot be a covariance in the x direction since the direction along the track has no constrained.
35  expectedCov6(1, 1) = 2;
36  expectedCov6(2, 2) = 3;
37  expectedCov6(3, 3) = 4;
38  expectedCov6(4, 4) = 5;
39  expectedCov6(5, 5) = 6;
40 
41  UncertainHelix uncertainHelix(expectedPosition,
42  expectedMomentum,
43  expectedCharge,
44  bZ,
45  expectedCov6,
46  pValue);
47 
48  const TVector3 position = uncertainHelix.getPerigee();
49  const TVector3 momentum = uncertainHelix.getMomentum(bZ);
50  const double charge = uncertainHelix.getChargeSign();
51  const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
52 
53  EXPECT_NEAR(expectedPosition.X(), position.X(), 1e-7);
54  EXPECT_NEAR(expectedPosition.Y(), position.Y(), 1e-7);
55  EXPECT_NEAR(expectedPosition.Z(), position.Z(), 1e-7);
56 
57  EXPECT_NEAR(expectedMomentum.X(), momentum.X(), 1e-7);
58  EXPECT_NEAR(expectedMomentum.Y(), momentum.Y(), 1e-7);
59  EXPECT_NEAR(expectedMomentum.Z(), momentum.Z(), 1e-7);
60 
61  EXPECT_EQ(expectedCharge, charge);
62 
63  for (int i : irange(0, 6)) {
64  for (int j : irange(0, 6)) {
65  EXPECT_NEAR(expectedCov6(i, j), cov6(i, j), 1e-7);
66  }
67  }
68  }
69 
70 
71  TEST(UncertainHelixTest, CartesianCovarianceRoundtripAtPerigeeBesidesOrigin)
72  {
73  TVector3 expectedMomentum(1.0, 0.0, 0.0);
74  TVector3 expectedPosition(0.0, 1.0, 0.0);
75  const double expectedCharge = -1;
76  const double bZ = 2;
77  const double pValue = 0.5;
78 
79  TMatrixDSym expectedCov6(6);
80  expectedCov6.Zero();
81  expectedCov6(0, 0) = 0; // There cannot be a covariance in the x direction since the direction along the track has no constraint.
82  for (int i : irange(1, 6)) {
83  for (int j : irange(1, 6)) {
84  // Assign some values to the covariances to check the correct propagation of signs.
85  expectedCov6(i, j) = 1;
86  }
87  }
88 
89  expectedCov6(1, 1) = 2;
90  expectedCov6(2, 2) = 3;
91  expectedCov6(3, 3) = 4;
92  expectedCov6(4, 4) = 5;
93  expectedCov6(5, 5) = 6;
94 
95  UncertainHelix uncertainHelix(expectedPosition,
96  expectedMomentum,
97  expectedCharge,
98  bZ,
99  expectedCov6,
100  pValue);
101 
102  const TVector3 position = uncertainHelix.getPerigee();
103  const TVector3 momentum = uncertainHelix.getMomentum(bZ);
104  const double charge = uncertainHelix.getChargeSign();
105  const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
106 
107  EXPECT_NEAR(expectedPosition.X(), position.X(), 1e-7);
108  EXPECT_NEAR(expectedPosition.Y(), position.Y(), 1e-7);
109  EXPECT_NEAR(expectedPosition.Z(), position.Z(), 1e-7);
110 
111  EXPECT_NEAR(expectedMomentum.X(), momentum.X(), 1e-7);
112  EXPECT_NEAR(expectedMomentum.Y(), momentum.Y(), 1e-7);
113  EXPECT_NEAR(expectedMomentum.Z(), momentum.Z(), 1e-7);
114 
115  EXPECT_EQ(expectedCharge, charge);
116 
117  // Test the covariance matrix for the right null space
118  TVectorD nullSpace(6);
119  const double factor =
120  (expectedPosition.X() * expectedMomentum.Y() - expectedPosition.Y() * expectedMomentum.X()) / expectedMomentum.Perp2();
121  nullSpace[0] = expectedMomentum.X();
122  nullSpace[1] = expectedMomentum.Y();
123  nullSpace[2] = 0;
124  nullSpace[3] = factor * expectedMomentum.Y();
125  nullSpace[4] = - factor * expectedMomentum.X();
126  nullSpace[5] = 0;
127 
128  TVectorD nullVector = cov6 * nullSpace;
129  for (int j : irange(0, 6)) {
130  EXPECT_NEAR(0, nullVector(j), 1e-7);
131  }
132 
133  // Make a second round trip to assert the covariance
134  // is stable after one adjustment of the null space
135  UncertainHelix uncertainHelix2(position,
136  momentum,
137  charge,
138  bZ,
139  cov6,
140  pValue);
141 
142  const TMatrixDSym cov6_2 = uncertainHelix2.getCartesianCovariance(bZ);
143  for (int i : irange(0, 6)) {
144  for (int j : irange(0, 6)) {
145  EXPECT_NEAR(cov6(i, j), cov6_2(i, j), 1e-7);
146  }
147  }
148  }
149 
150  TEST(UncertainHelixTest, CartesianCovarianceRoundtripAtPerigeeBesidesOriginIndividualCoordinates)
151  {
152  TVector3 expectedMomentum(1.0, 0.0, 0.0);
153  TVector3 expectedPosition(0.0, 1.0, 0.0);
154  const double expectedCharge = -1;
155  const double bZ = 2;
156  const double pValue = 0.5;
157 
158  for (int i : irange(1, 6)) {
159 
160  TMatrixDSym expectedCov6(6);
161  expectedCov6.Zero();
162  expectedCov6(0, 0) = 0; // There cannot be a covariance in the x direction since the direction along the track has no constraint.
163 
164  expectedCov6(i, i) = 1;
165 
166  UncertainHelix uncertainHelix(expectedPosition,
167  expectedMomentum,
168  expectedCharge,
169  bZ,
170  expectedCov6,
171  pValue);
172 
173  const TVector3 position = uncertainHelix.getPerigee();
174  const TVector3 momentum = uncertainHelix.getMomentum(bZ);
175  const double charge = uncertainHelix.getChargeSign();
176  const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
177 
178  EXPECT_NEAR(expectedPosition.X(), position.X(), 1e-7);
179  EXPECT_NEAR(expectedPosition.Y(), position.Y(), 1e-7);
180  EXPECT_NEAR(expectedPosition.Z(), position.Z(), 1e-7);
181 
182  EXPECT_NEAR(expectedMomentum.X(), momentum.X(), 1e-7);
183  EXPECT_NEAR(expectedMomentum.Y(), momentum.Y(), 1e-7);
184  EXPECT_NEAR(expectedMomentum.Z(), momentum.Z(), 1e-7);
185 
186  EXPECT_EQ(expectedCharge, charge);
187 
188  // Test the covariance matrix for the right null space
189  TVectorD nullSpace(6);
190  const double factor =
191  (expectedPosition.X() * expectedMomentum.Y() - expectedPosition.Y() * expectedMomentum.X()) / expectedMomentum.Perp2();
192  nullSpace[0] = expectedMomentum.X();
193  nullSpace[1] = expectedMomentum.Y();
194  nullSpace[2] = 0;
195  nullSpace[3] = factor * expectedMomentum.Y();
196  nullSpace[4] = - factor * expectedMomentum.X();
197  nullSpace[5] = 0;
198 
199  TVectorD nullVector = cov6 * nullSpace;
200  for (int j : irange(0, 6)) {
201  EXPECT_NEAR(0, nullVector(j), 1e-7);
202  }
203 
204  // Make a second round trip to assert the covariance
205  // is stable after one adjustment of the null space
206  UncertainHelix uncertainHelix2(position,
207  momentum,
208  charge,
209  bZ,
210  cov6,
211  pValue);
212 
213  const TMatrixDSym cov6_2 = uncertainHelix2.getCartesianCovariance(bZ);
214  for (int j : irange(0, 6)) {
215  for (int k : irange(0, 6)) {
216  EXPECT_NEAR(cov6(j, k), cov6_2(j, k), 1e-7);
217  }
218  }
219  }
220  }
221 
222  TEST(UncertainHelixTest, PerigeeCovarianceRoundtripAtPerigeeBesidesOriginIndividualCoordinates)
223  {
224  double d0 = 1;
225  double phi0 = 0;
226  double omega = -0.005;
227  double tanLambda = 1;
228  double z0 = 0;
229 
230  const double bZ = 2;
231  const double pValue = 0.5;
232 
233  for (int i : irange(0, 5)) {
234 
235  TMatrixDSym expectedCov5(5);
236  expectedCov5.Zero();
237  expectedCov5(i, i) = 1;
238 
239  UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, expectedCov5, pValue);
240 
241  const TVector3 position = uncertainHelix.getPerigee();
242  const TVector3 momentum = uncertainHelix.getMomentum(bZ);
243  const double charge = uncertainHelix.getChargeSign();
244  const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
245 
246  UncertainHelix uncertainHelix2(position,
247  momentum,
248  charge,
249  bZ,
250  cov6,
251  pValue);
252 
253  EXPECT_NEAR(d0, uncertainHelix2.getD0(), 1e-7);
254  EXPECT_NEAR(phi0, uncertainHelix2.getPhi0(), 1e-7);
255  EXPECT_NEAR(omega, uncertainHelix2.getOmega(), 1e-7);
256 
257  EXPECT_NEAR(z0, uncertainHelix2.getZ0(), 1e-7);
258  EXPECT_NEAR(tanLambda, uncertainHelix2.getTanLambda(), 1e-7);
259 
260  const TMatrixDSym& cov5 = uncertainHelix2.getCovariance();
261  EXPECT_EQ(-1, charge);
262 
263  for (int j : irange(0, 5)) {
264  for (int k : irange(0, 5)) {
265  EXPECT_NEAR(expectedCov5(j, k), cov5(j, k), 1e-7);
266  }
267  }
268  }
269  }
270 
271  TEST(UncertainHelixTest, RealPerigeeCovarianceRoundTrip)
272  {
273  const double bZ = 1.5;
274  const double pValue = 0.5;
275 
276  std::vector<float> helixParams(5);
277  std::vector<float> helixCovariance(15);
278 
279  helixParams[0] = 3.82384;
280  helixParams[1] = std::remainder(3.57559, 2 * M_PI);
281  helixParams[2] = 0.00530726;
282  helixParams[3] = -0.000317335;
283  helixParams[4] = 1.34536;
284 
285  helixCovariance[0] = 0.000648818;
286  helixCovariance[1] = 6.357e-05;
287  helixCovariance[2] = 2.04344e-07;
288  helixCovariance[3] = -0.00101879;
289  helixCovariance[4] = 2.29407e-05;
290 
291  helixCovariance[5] = 1.02934e-05;
292  helixCovariance[6] = 1.39609e-08;
293  helixCovariance[7] = 9.57685e-07;
294  helixCovariance[8] = 1.19863e-06;
295 
296  helixCovariance[9] = 4.96093e-10;
297  helixCovariance[10] = -8.41612e-07;
298  helixCovariance[11] = 6.50684e-08;
299 
300  helixCovariance[12] = 0.0317385;
301  helixCovariance[13] = -0.00065476;
302 
303  helixCovariance[14] = 3.6521e-05;
304 
305  TMatrixDSym expectedCov5(5);
306  unsigned int counter = 0;
307  for (unsigned int i = 0; i < 5; ++i) {
308  for (unsigned int j = i; j < 5; ++j) {
309  expectedCov5(i, j) = expectedCov5(j, i) = helixCovariance[counter];
310  ++counter;
311  }
312  }
313 
314  UncertainHelix uncertainHelix(helixParams[0],
315  helixParams[1],
316  helixParams[2],
317  helixParams[3],
318  helixParams[4],
319  expectedCov5,
320  pValue);
321 
322  const TVector3 position = uncertainHelix.getPerigee();
323  const TVector3 momentum = uncertainHelix.getMomentum(bZ);
324  const double charge = uncertainHelix.getChargeSign();
325  const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
326 
327  UncertainHelix uncertainHelix2(position,
328  momentum,
329  charge,
330  bZ,
331  cov6,
332  pValue);
333 
334  EXPECT_NEAR(helixParams[0], uncertainHelix2.getD0(), 1e-7);
335  EXPECT_NEAR(helixParams[1], uncertainHelix2.getPhi0(), 1e-7);
336  EXPECT_NEAR(helixParams[2], uncertainHelix2.getOmega(), 1e-7);
337 
338  EXPECT_NEAR(helixParams[3], uncertainHelix2.getZ0(), 1e-7);
339  EXPECT_NEAR(helixParams[4], uncertainHelix2.getTanLambda(), 1e-7);
340 
341  const TMatrixDSym& cov5 = uncertainHelix2.getCovariance();
342  EXPECT_EQ(1, charge);
343 
344  for (int i : boost::irange(0, 5)) {
345  for (int j : boost::irange(0, 5)) {
346  EXPECT_NEAR(expectedCov5(i, j), cov5(i, j), 1e-7);
347  }
348  }
349  }
350 
351 
352  TEST(UncertainHelixTest, Explicit_D0)
353  {
354  double d0 = 1;
355  double phi0 = 0;
356  double omega = -0.005;
357  double tanLambda = 1;
358  double z0 = 0;
359 
360  const double bZ = 2;
361  const double pValue = 0.5;
362 
363  TMatrixDSym expectedCov5(5);
364  expectedCov5.Zero();
365  expectedCov5(0, 0) = 1;
366 
367  TMatrixDSym expectedCov6(6);
368  expectedCov6.Zero();
369  expectedCov6(1, 1) = 1;
370 
371  UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, expectedCov5, pValue);
372 
373  const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
374 
375  for (int i : irange(0, 6)) {
376  for (int j : irange(0, 6)) {
377  TEST_CONTEXT("Failed for index (" << i << ", " << j << ")");
378  EXPECT_NEAR(expectedCov6(i, j), cov6(i, j), 1e-7);
379  }
380  }
381  }
382 
383  TEST(UncertainHelixTest, Explicit_Phi0)
384  {
385  double d0 = 0;
386  double phi0 = 0;
387  double omega = -0.006;
388  double tanLambda = 0;
389  double z0 = 0;
390 
391  const double bZ = 1.5;
392  const double pValue = 0.5;
393 
394  TMatrixDSym expectedCov5(5);
395  expectedCov5.Zero();
396  expectedCov5(1, 1) = 1;
397 
398  UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, expectedCov5, pValue);
399 
400  const TVector3 position = uncertainHelix.getPerigee();
401  const TVector3 momentum = uncertainHelix.getMomentum(bZ);
402  const double charge = uncertainHelix.getChargeSign();
403  const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
404 
405  double absMom2D = uncertainHelix.getTransverseMomentum(1.5);
406 
407  TMatrixDSym expectedCov6(6);
408  expectedCov6.Zero();
409  expectedCov6(4, 4) = absMom2D * absMom2D;
410 
411  for (int i : irange(0, 6)) {
412  for (int j : irange(0, 6)) {
413  TEST_CONTEXT("Failed for index (" << i << ", " << j << ")");
414  EXPECT_NEAR(expectedCov6(i, j), cov6(i, j), 1e-7);
415  }
416  }
417 
418  UncertainHelix uncertainHelix2(position,
419  momentum,
420  charge,
421  bZ,
422  cov6,
423  pValue);
424 
425  EXPECT_NEAR(d0, uncertainHelix2.getD0(), 1e-7);
426  EXPECT_NEAR(phi0, uncertainHelix2.getPhi0(), 1e-7);
427  EXPECT_NEAR(omega, uncertainHelix2.getOmega(), 1e-7);
428 
429  EXPECT_NEAR(z0, uncertainHelix2.getZ0(), 1e-7);
430  EXPECT_NEAR(tanLambda, uncertainHelix2.getTanLambda(), 1e-7);
431 
432  const TMatrixDSym& cov5 = uncertainHelix2.getCovariance();
433  EXPECT_EQ(-1, charge);
434 
435  for (int i : irange(0, 5)) {
436  for (int j : irange(0, 5)) {
437  TEST_CONTEXT("Failed for index (" << i << ", " << j << ")");
438  EXPECT_NEAR(expectedCov5(i, j), cov5(i, j), 1e-7);
439  }
440  }
441  }
442 
443  TEST(UncertainHelixTest, MoveInCartesianVersusMoveInPerigeeCoordinates)
444  {
445  // Move of the coordinate system
446  TVector3 moveBy(0.5, -1, 0.5);
447 
448  double d0 = 1;
449  double phi0 = 0;
450  double omega = -0.005;
451  double tanLambda = 1;
452  double z0 = 0;
453 
454  const double bZ = 2;
455  const double pValue = 0.5;
456 
457  TMatrixDSym initialCov5(5);
458  initialCov5.Zero();
459  for (int i : irange(0, 5)) {
460  for (int j : irange(0, 5)) {
461  initialCov5(i, j) = i + j;
462  }
463  }
464 
465  UncertainHelix uncertainHelix(d0, phi0, omega, z0, tanLambda, initialCov5, pValue);
466 
467  const TVector3 position = uncertainHelix.getPerigee();
468  const TVector3 momentum = uncertainHelix.getMomentum(bZ);
469  const double charge = uncertainHelix.getChargeSign();
470  const TMatrixDSym cov6 = uncertainHelix.getCartesianCovariance(bZ);
471 
472  // Execute the move in cartesian coordinates
473  const TVector3 movedPosition = position - moveBy;
474  UncertainHelix movedUncertainHelix(movedPosition,
475  momentum,
476  charge,
477  bZ,
478  cov6,
479  pValue);
480 
481  const TMatrixDSym& cov5 = movedUncertainHelix.getCovariance();
482 
483  // Execute the move in perigee coordinates
484  UncertainHelix expectedMovedUncertainHelix = uncertainHelix;
485  expectedMovedUncertainHelix.passiveMoveBy(moveBy);
486  const TMatrixDSym expectedCov5 = expectedMovedUncertainHelix.getCovariance();
487 
488  // Test equivalence of both transformation
489  EXPECT_NEAR(expectedMovedUncertainHelix.getD0(), movedUncertainHelix.getD0(), 1e-7);
490  EXPECT_NEAR(expectedMovedUncertainHelix.getPhi0(), movedUncertainHelix.getPhi0(), 1e-7);
491  EXPECT_NEAR(expectedMovedUncertainHelix.getOmega(), movedUncertainHelix.getOmega(), 1e-7);
492  EXPECT_NEAR(expectedMovedUncertainHelix.getZ0(), movedUncertainHelix.getZ0(), 1e-7);
493  EXPECT_NEAR(expectedMovedUncertainHelix.getTanLambda(), movedUncertainHelix.getTanLambda(), 1e-7);
494 
495  for (int i : irange(0, 5)) {
496  for (int j : irange(0, 5)) {
497  TEST_CONTEXT("Failed for index (" << i << ", " << j << ")");
498  EXPECT_NEAR(expectedCov5(i, j), cov5(i, j), 1e-7);
499  }
500  }
501  }
502 }
Belle2::EvtPDLUtil::charge
double charge(int pdgCode)
Returns electric charge of a particle with given pdg code.
Definition: EvtPDLUtil.cc:46
Belle2::UncertainHelix
This class represents an ideal helix in perigee parameterization including the covariance matrix of t...
Definition: UncertainHelix.h:40
Belle2::UncertainHelix::passiveMoveBy
double passiveMoveBy(const TVector3 &by)
Moves origin of the coordinate system (passive transformation) by the given vector.
Definition: UncertainHelix.h:121
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::UncertainHelix::getCovariance
const TMatrixDSym & getCovariance() const
Getter for covariance matrix of perigee parameters in matrix form.
Definition: UncertainHelix.h:104
Belle2::TEST
TEST(TestgetDetectorRegion, TestgetDetectorRegion)
Test Constructors.
Definition: utilityFunctions.cc:18