Belle II Software development
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
23using namespace Belle2;
24using namespace TrackFindingCDC;
25
26
27TEST(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
51TEST(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
62TEST(TrackFindingCDCTest, numerics_SinEqLine_getIPeriodFromIHalfPeriod)
63{
64 int iHalfPeriod = -1;
65 int iPeriod = SinEqLine::getIPeriodFromIHalfPeriod(iHalfPeriod);
66 EXPECT_EQ(-1, iPeriod);
67}
68
69
70TEST(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
86TEST(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
101TEST(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
120TEST(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
138TEST(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
157TEST(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
177TEST(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
197TEST(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
213TEST(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
229TEST(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{};
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
247TEST(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{};
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
266TEST(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:32
static const double deg
degree to radians
Definition: Unit.h:109
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.