Belle II Software  release-08-01-10
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 
19 using namespace std;
20 using namespace Belle2;
21 
22 namespace 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 
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.
std::array< std::vector< double >, 3 > m_testData
data that is used in the tests
TEST_F(GlobalLabelTest, LargeNumberOfTimeDependentParameters)
Test large number of time-dep params for registration and retrieval.
Definition: globalLabel.cc:72
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.