Belle II Software development
decorrelationMatrix.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
9#include <gtest/gtest.h>
10
11#include <tracking/trackFindingVXD/filterTools/DecorrelationMatrix.h>
12#include <tracking/trackFindingVXD/filterTools/DecorrelationMatrixHelper.h>
13
14#include <Eigen/Dense>
15
16#include <fstream>
17#include <cstdio>
18
19using namespace std;
20using namespace Belle2;
21
22namespace VXDTFFilterTest {
23
25 using TestMatrix = Eigen::Matrix<double, 3, 3, Eigen::RowMajor>;
26
28 const std::vector<double> v1 = {
29 0.537667139546100,
30 1.833885014595086,
31 -2.258846861003648,
32 0.862173320368121,
33 0.318765239858981,
34 -1.307688296305273,
35 -0.433592022305684,
36 0.342624466538650,
37 3.578396939725760,
38 2.769437029884877
39 };
40
42 const std::vector<double> v2 = {
43 -1.349886940156521,
44 3.034923466331855,
45 0.725404224946106,
46 -0.063054873189656,
47 0.714742903826096,
48 -0.204966058299775,
49 -0.124144348216312,
50 1.489697607785465,
51 1.409034489800479,
52 1.417192413429614
53 };
54
56 const std::vector<double> v3 = {
57 0.671497133608080,
58 -1.207486922685038,
59 0.717238651328838,
60 1.630235289164729,
61 0.488893770311789,
62 1.034693009917860,
63 0.726885133383238,
64 -0.303440924786016,
65 0.293871467096658,
66 -0.787282803758638
67 };
68
70 class DecorrelationMatrixTest : public ::testing::Test {
71 protected:
77 virtual void SetUp()
78 {
79 m_testData = {{v1, v2, v3}};
80
81 TestMatrix tmpMatrix;
82 // cpp check does not like commas
83 tmpMatrix << 3.132492133948475, 0.974827954209597, -0.761264020048923,
84 0.974827954209597, 1.486186070946439, -0.840189849104485,
85 // cppcheck-suppress constStatement
86 -0.761264020048923, -0.840189849104485, 0.739017883637750;
87
88 // MATLAB calculates the empirical covariance matrix with a prefactor (n-1)^-1, but we do with a prefactor of n^-1 so this has
89 // to be corrected (n=3 in the test cases)
90 m_covMatrix = (double)(v3.size() - 1) / (double)v3.size() * tmpMatrix;
91 }
92
94 std::array<std::vector<double>, 3> m_testData;
95
98
100 TestMatrix m_identity = TestMatrix::Identity();
101 };
102
104 TEST_F(DecorrelationMatrixTest, TestSetUp)
105 {
106 EXPECT_EQ(3, m_testData.size());
107 for (const auto& vec : m_testData) { EXPECT_EQ(10, vec.size()); }
108 }
109
111 TEST_F(DecorrelationMatrixTest, TestConstructor)
112 {
113 DecorrelationMatrix<3> matrix{};
114 const auto& internalMatrix = matrix.getMatrix();
115
116 for (auto i = 0; i < internalMatrix.outerSize(); ++i) {
117 for (auto j = 0; j < internalMatrix.innerSize(); ++j) {
118 EXPECT_DOUBLE_EQ(m_identity(i, j), internalMatrix(i, j));
119 }
120 }
121 }
122
124 TEST_F(DecorrelationMatrixTest, TestCalculateDecorrMatrix)
125 {
126 DecorrelationMatrix<3> matrix{};
127 matrix.calculateDecorrMatrix(m_testData);
128
129 // test that the size of the input and the output vector does not change
130 std::vector<double> testVec = { m_testData[0][0], m_testData[1][0], m_testData[2][0] };
131 auto outputVec = matrix.decorrelate(testVec);
132 EXPECT_EQ(testVec.size(), outputVec.size());
133
134 // test that the covariance matrix of the decorrelated test data is indeed the identity (at least numerically)
135 auto outputData = matrix.decorrelate(m_testData);
136 auto covMat = calculateCovMatrix(outputData);
137 for (auto i = 0; i < covMat.outerSize(); ++i) {
138 for (auto j = 0; j < covMat.innerSize(); ++j) {
139 if (i == j) {
140 EXPECT_FLOAT_EQ(m_identity(i, j), covMat(i, j)); // the diagonal should be ones, even with considering numerics
141 } else {
142 EXPECT_NEAR(m_identity(i, j), covMat(i, j), 1e-15); // EXPECT_FLOAT_EQ is to stringent for the numerical calculations
143 }
144 }
145 }
146
147 // COULDDO: test non-normalized version as well
148 }
149
151 TEST_F(DecorrelationMatrixTest, TestCaluclateCovMatrix)
152 {
153 // test if the correct covariance matrix gets calculated
154 const TestMatrix covMat = calculateCovMatrix(m_testData);
155 EXPECT_EQ(covMat.outerSize(), 3);
156 EXPECT_EQ(covMat.innerSize(), 3);
157 for (auto i = 0; i < covMat.outerSize(); ++i) {
158 for (auto j = 0; j < covMat.innerSize(); ++j) {
159 EXPECT_DOUBLE_EQ(m_covMatrix(i, j), covMat(i, j));
160 }
161 }
162
163 // check if an identity matrix is returned if the input is incorrect
164 auto badTestData = m_testData;
165 badTestData[0].erase(badTestData[0].begin()); // remove first element from the first vector in the array
166 const TestMatrix badMat = calculateCovMatrix(badTestData);
167 EXPECT_EQ(3, badMat.outerSize());
168 EXPECT_EQ(3, badMat.innerSize());
169 EXPECT_TRUE(badMat == m_identity);
170 }
171
175 TEST_F(DecorrelationMatrixTest, TestDecorrelationMatrixIO)
176 {
177 const char* filename = "tmp_matrix_testoutput.dat";
178
179 ofstream ofs(filename);
180 DecorrelationMatrix<3> covMatrix(m_covMatrix);
181 ofs << covMatrix.print() << std::endl;
182 ofs.close();
183
184 ifstream ifs(filename);
185 DecorrelationMatrix<3> inMatrix{};
186 EXPECT_TRUE(inMatrix.readFromStream(ifs));
187 ifs.close();
188
189 const TestMatrix& inMat = inMatrix.getMatrix();
190 for (auto i = 0; i < m_covMatrix.outerSize(); ++i) {
191 for (auto j = 0; j < m_covMatrix.innerSize(); ++j) {
192 EXPECT_DOUBLE_EQ(m_covMatrix(i, j), inMat(i, j));
193 }
194 }
195
196 ASSERT_EQ(0, remove(filename)); // assert that the temporarily created file gets deleted again
197 }
198}
Class holding a Matrix that can be used to decorrelate input data to Machine Learning classifiers.
const MatrixT & getMatrix() const
get the currently stored matrix
TestMatrix m_covMatrix
covariance matrix of the data as calculated via MATLAB
virtual void SetUp()
Fills the data into the internal data structure that is used for testing.
TestMatrix m_identity
provide the identity matrix as class-member since it is used in many testcases
std::array< std::vector< double >, 3 > m_testData
data that is used in the tests
const Eigen::Matrix< double, Ndims, Ndims, Eigen::RowMajor > calculateCovMatrix(std::array< std::vector< double >, Ndims > inputData)
calculates the empirical covariance matrix from the inputData.
void calculateDecorrMatrix(std::array< std::vector< double >, Ndims > inputData, bool normalise=true)
calculate the transformation matrix that when applied to the input data yields linearly uncorrelated ...
std::string print() const
print the matrix to a string.
Abstract base class for different kinds of events.
helper struct for testing purposes providing the necessary coordinate accessors NOTE: this is only te...
const std::vector< double > v3
MATLAB generated random vector.
Eigen::Matrix< double, 3, 3, Eigen::RowMajor > TestMatrix
typedef for less typing effort
const std::vector< double > v2
MATLAB generated random vector.
const std::vector< double > v1
MATLAB generated random vector.
STL namespace.