Belle II Software  release-08-01-10
numerics.test.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include <tracking/trackFindingCDC/numerics/SinEqLine.h>
9 
10 #include <tracking/trackFindingCDC/geometry/Line2D.h>
11 
12 #include <tracking/trackFindingCDC/numerics/CovarianceMatrixUtil.h>
13 
14 #include <tracking/trackFindingCDC/numerics/Median.h>
15 #include <tracking/trackFindingCDC/numerics/WithWeight.h>
16 #include <tracking/trackFindingCDC/numerics/ESign.h>
17 
18 #include <framework/gearbox/Unit.h>
19 
20 #include <gtest/gtest.h>
21 
22 
23 using namespace Belle2;
24 using namespace TrackFindingCDC;
25 
26 
27 TEST(TrackFindingCDCTest, numerics_sign)
28 {
29  EXPECT_EQ(ESign::c_Plus, sign(INFINITY));
30  EXPECT_EQ(ESign::c_Plus, sign(2));
31  EXPECT_EQ(ESign::c_Plus, sign(0.0));
32  EXPECT_EQ(ESign::c_Minus, sign(-0.0));
33  EXPECT_EQ(ESign::c_Minus, sign(-2));
34  EXPECT_EQ(ESign::c_Minus, sign(-INFINITY));
35  EXPECT_EQ(ESign::c_Invalid, sign(NAN));
36 
37  EXPECT_TRUE(ESignUtil::isValid(ESign::c_Plus));
38  EXPECT_TRUE(ESignUtil::isValid(ESign::c_Minus));
39  EXPECT_TRUE(ESignUtil::isValid(ESign::c_Zero));
40 
41  EXPECT_FALSE(ESignUtil::isValid(ESign::c_Invalid));
42  EXPECT_FALSE(ESignUtil::isValid(static_cast<ESign>(7)));
43 
44  EXPECT_EQ(ESign::c_Minus, ESignUtil::opposite(ESign::c_Plus));
45  EXPECT_EQ(ESign::c_Plus, ESignUtil::opposite(ESign::c_Minus));
46  EXPECT_EQ(ESign::c_Zero, ESignUtil::opposite(ESign::c_Zero));
47  EXPECT_EQ(ESign::c_Invalid, ESignUtil::opposite(ESign::c_Invalid));
48 }
49 
50 
51 TEST(TrackFindingCDCTest, numerics_SinEqLine_isIncreasing)
52 {
53 
54  Vector2D lower(0.0, 1.0);
55  Vector2D upper(1.0, 2.0);
56 
57  EXPECT_EQ(EIncDec::c_Increasing, SinEqLine::getEIncDec(lower, upper));
58 
59 }
60 
61 
62 TEST(TrackFindingCDCTest, numerics_SinEqLine_getIPeriodFromIHalfPeriod)
63 {
64  int iHalfPeriod = -1;
65  int iPeriod = SinEqLine::getIPeriodFromIHalfPeriod(iHalfPeriod);
66  EXPECT_EQ(-1, iPeriod);
67 }
68 
69 
70 TEST(TrackFindingCDCTest, numerics_SinEqLine_computeRootInInterval_simple)
71 {
72 
73  // Simple sin.
74  SinEqLine sinEqLine(0.0, 0.0);
75 
76  double rootX = sinEqLine.computeRootInInterval(M_PI / 2, 3 * M_PI / 2);
77  double rootY = sinEqLine.map(rootX);
78 
79  EXPECT_NEAR(M_PI, rootX, 10e-7);
80  EXPECT_NEAR(0.0, rootY, 10e-7);
81 
82 }
83 
84 
85 
86 TEST(TrackFindingCDCTest, numerics_SinEqLine_computeRootInInterval_const)
87 {
88 
89  // Constant sin.
90  SinEqLine sinEqLine(0.0, 1.0 / 2.0);
91 
92  double rootX = sinEqLine.computeRootInInterval(M_PI / 2, 3 * M_PI / 2);
93  double rootY = sinEqLine.map(rootX);
94 
95  EXPECT_NEAR(150.0 * Unit::deg, rootX, 10e-7);
96  EXPECT_NEAR(0.0, rootY, 10e-7);
97 
98 }
99 
100 
101 TEST(TrackFindingCDCTest, numerics_SinEqLine_computeRootInInterval_complex)
102 {
103 
104  // Setup a line that is a
105  double rootX = 150.0 * Unit::deg;
106  Line2D line = Line2D::fromSlopeIntercept(1.0 / 2.0, 1.0 / 2.0);
107  line.moveAlongFirst(rootX);
108 
109  SinEqLine sinEqLine(line);
110 
111  double solvedRootX = sinEqLine.computeRootInInterval(M_PI / 2, 3 * M_PI / 2);
112  double solvedRootY = sinEqLine.map(rootX);
113 
114  EXPECT_NEAR(rootX, solvedRootX, 10e-7);
115  EXPECT_NEAR(0.0, solvedRootY, 10e-7);
116 
117 }
118 
119 
120 TEST(TrackFindingCDCTest, numerics_SinEqLine_computeRootLargerThanExtemumInHalfPeriod_simple)
121 {
122 
123  // Setup a line that is a
124  double rootX = 0.0 * Unit::deg;
125  Line2D line = Line2D::fromSlopeIntercept(-1.0 / 2.0, 0);
126 
127  SinEqLine sinEqLine(line);
128 
129  double solvedRootX = sinEqLine.computeRootLargerThanExtemumInHalfPeriod(-1);
130  double solvedRootY = sinEqLine.map(rootX);
131 
132  EXPECT_NEAR(rootX, solvedRootX, 10e-7);
133  EXPECT_NEAR(0.0, solvedRootY, 10e-7);
134 
135 }
136 
137 
138 TEST(TrackFindingCDCTest, numerics_SinEqLine_computeRootLargerThanExtemumInHalfPeriod)
139 {
140 
141  // Setup a line that is a
142  double rootX = 150.0 * Unit::deg;
143  Line2D line = Line2D::fromSlopeIntercept(1.0 / 2.0, 1.0 / 2.0);
144  line.moveAlongFirst(rootX);
145 
146  SinEqLine sinEqLine(line);
147 
148  double solvedRootX = sinEqLine.computeRootLargerThanExtemumInHalfPeriod(0);
149  double solvedRootY = sinEqLine.map(rootX);
150 
151  EXPECT_NEAR(rootX, solvedRootX, 10e-7);
152  EXPECT_NEAR(0.0, solvedRootY, 10e-7);
153 
154 }
155 
156 
157 TEST(TrackFindingCDCTest, numerics_SinEqLine_computeSmallestPositiveRoot)
158 {
159 
160  // Setup a line that is a
161  double rootX = 150.0 * Unit::deg;
162  Line2D line = Line2D::fromSlopeIntercept(1.0 / 2.0, 1.0 / 2.0);
163  line.moveAlongFirst(rootX);
164 
165  SinEqLine sinEqLine(line);
166 
167  double solvedRootX = sinEqLine.computeSmallestPositiveRoot();
168  double solvedRootY = sinEqLine.map(rootX);
169 
170  EXPECT_NEAR(rootX, solvedRootX, 10e-7);
171  EXPECT_NEAR(0.0, solvedRootY, 10e-7);
172 
173 }
174 
175 
176 
177 TEST(TrackFindingCDCTest, numerics_SinEqLine_computeSmallestPositiveRoot_largeSlope)
178 {
179 
180  // Setup a line that is a
181  double rootX = 150.0 * Unit::deg;
182  Line2D line = Line2D::fromSlopeIntercept(2.0, 1.0 / 2.0);
183  line.moveAlongFirst(rootX);
184 
185  SinEqLine sinEqLine(line);
186 
187  double solvedRootX = sinEqLine.computeSmallestPositiveRoot();
188  double solvedRootY = sinEqLine.map(rootX);
189 
190  EXPECT_NEAR(rootX, solvedRootX, 10e-7);
191  EXPECT_NEAR(0.0, solvedRootY, 10e-7);
192 
193 }
194 
195 
196 
197 TEST(TrackFindingCDCTest, numerics_SinEqLine_computeRootForLargeSlope)
198 {
199  // Setup a line that is a
200  double rootX = 150.0 * Unit::deg;
201  Line2D line = Line2D::fromSlopeIntercept(2.0, 1.0 / 2.0);
202  line.moveAlongFirst(rootX);
203 
204  SinEqLine sinEqLine(line);
205 
206  double solvedRootX = sinEqLine.computeRootForLargeSlope();
207  double solvedRootY = sinEqLine.map(rootX);
208 
209  EXPECT_NEAR(rootX, solvedRootX, 10e-7);
210  EXPECT_NEAR(0.0, solvedRootY, 10e-7);
211 }
212 
213 TEST(TrackFindingCDCTest, numerics_median)
214 {
215  std::vector<double> fourValues{0.0, 3.0, 5.0, 100};
216  EXPECT_EQ(4.0, median(std::move(fourValues)));
217 
218  std::vector<double> threeValues{0.0, 3.0, 5.0, 100.0, 1000.0};
219  EXPECT_EQ(5.0, median(std::move(threeValues)));
220 
221  std::vector<WithWeight<double>> weightedValues{{0.0, 0.2},
222  {3.0, 0.1},
223  {5.0, 0.1},
224  {100.0, 0.3},
225  {1000.0, 0.3}};
226  EXPECT_EQ(100.0, weightedMedian(std::move(weightedValues)));
227 }
228 
229 TEST(TrackFindingCDCTest, covariance_simple_average)
230 {
231  // Simple average of two scalar values
232  const ParameterVector<1> par1{ -1};
233  const CovarianceMatrix<1> cov1{2};
234 
235  const ParameterVector<1> par2{1};
236  const CovarianceMatrix<1> cov2{2};
237 
238  ParameterVector<1> par{};
239  CovarianceMatrix<1> cov{};
240 
241  double chi2 = CovarianceMatrixUtil::average(par1, cov1, par2, cov2, par, cov);
242  EXPECT_NEAR(0, par[0], 1E-8);
243  EXPECT_NEAR(1, cov[0], 1E-8);
244  EXPECT_NEAR(1, chi2, 1E-8);
245 }
246 
247 TEST(TrackFindingCDCTest, covariance_half_projection_average)
248 {
249  // Same average of two scalar values but one is 'projected' stretched by a factor of 2
250  const JacobianMatrix<1, 1> ambi1{2};// Ambiguity is 2.
251  const ParameterVector<1> par1{ -2}; // Parameter scales with 2
252  const CovarianceMatrix<1> cov1{8}; // Covariance scales with 2 * 2
253 
254  const ParameterVector<1> par2{1};
255  const CovarianceMatrix<1> cov2{2};
256 
257  ParameterVector<1> par{};
258  CovarianceMatrix<1> cov{};
259 
260  double chi2 = CovarianceMatrixUtil::average(par1, cov1, ambi1, par2, cov2, par, cov);
261  EXPECT_NEAR(0, par[0], 1E-8);
262  EXPECT_NEAR(1, cov[0], 1E-8);
263  EXPECT_NEAR(1, chi2, 1E-8);
264 }
265 
266 TEST(TrackFindingCDCTest, covariance_kalman_update_average)
267 {
268  // Same average of two scalar values but one is 'projected' / stretched by a factor of 2
269  // Now as an inplace update using the Kalman formula.
270  const JacobianMatrix<1, 1> ambi1{2}; // Ambiguity is 2.
271  const ParameterVector<1> par1{ -2}; // Parameter scales with 2
272  const CovarianceMatrix<1> cov1{8}; // Covariance scales with 2 * 2
273 
274  ParameterVector<1> par{1};
275  CovarianceMatrix<1> cov{2};
276 
277  double chi2 = CovarianceMatrixUtil::kalmanUpdate(par1, cov1, ambi1, par, cov);
278  EXPECT_NEAR(0, par[0], 1E-8);
279  EXPECT_NEAR(1, cov[0], 1E-8);
280  EXPECT_NEAR(1, chi2, 1E-8);
281 }
R E
internal precision of FFTW codelets
A two dimensional normal line.
Definition: Line2D.h:37
static Line2D fromSlopeIntercept(const double slope, const double intercept)
Constructs a line from its slope and intercept over the first coordinate (default forward orientation...
Definition: Line2D.h:70
A matrix implementation to be used as an interface typ through out the track finder.
Definition: PlainMatrix.h:40
Helper class to calculate roots for the function f(x) = sin x - slope * x - intercept.
Definition: SinEqLine.h:36
static EIncDec getEIncDec(const Vector2D &lower, const Vector2D &upper)
Determines if the function is increasing or decreasing in the intervall.
Definition: SinEqLine.h:133
static int getIPeriodFromIHalfPeriod(int iHalfPeriod)
Helper function to translate the index of the half period to index of the containing period.
Definition: SinEqLine.h:151
A two dimensional vector which is equipped with functions for correct handeling of orientation relat...
Definition: Vector2D.h:35
static const double deg
degree to radians
Definition: Unit.h:109
TEST(TestgetDetectorRegion, TestgetDetectorRegion)
Test Constructors.
ESign
Enumeration for the distinct sign values of floating point variables.
Definition: ESign.h:27
ESign opposite(ESign s)
Return the opposite sign. Leaves ESign::c_Invalid the same.
Definition: ESign.h:42
bool isValid(ESign s)
Returns true if sign is ESign::c_Plus, ESign::c_Minus or ESign::c_Zero.
Definition: ESign.h:46
Abstract base class for different kinds of events.
static double kalmanUpdate(const ParameterVector< N1 > &par1, const CovarianceMatrix< N1 > &cov1, const JacobianMatrix< N1, M > &ambiguity1, ParameterVector< M > &par2, CovarianceMatrix< M > &cov2)
Updates a parameter and its covariance by integrating information from parameter vector in a projecte...
static double average(const ParameterVector< N > &par1, const CovarianceMatrix< N > &cov1, const ParameterVector< N > &par2, const CovarianceMatrix< N > &cov2, ParameterVector< N > &par, CovarianceMatrix< N > &cov)
Averages two parameter vectors taking into account their respective covariances.