This commit is contained in:
2021-10-14 13:47:35 +02:00
commit 6625a8dfaa
4026 changed files with 844291 additions and 0 deletions
@@ -0,0 +1,50 @@
PROJECT(test-geometry)
FILE(GLOB_RECURSE TESTS_SRC_FILES *.cpp *.hpp)
ADD_EXECUTABLE(${PROJECT_NAME} ${TESTS_SRC_FILES})
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY FOLDER ${TESTS_FOLDER}) # Place project in folder unit-test (for some IDE)
# Modify library prefixes and suffixes to comply to Windows or Linux naming
IF(WIN32)
SET(CMAKE_FIND_LIBRARY_PREFIXES "")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".lib" ".dll")
ELSEIF(APPLE)
SET(CMAKE_FIND_LIBRARY_PREFIXES "lib")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".a")
ELSE()
SET(CMAKE_FIND_LIBRARY_PREFIXES "lib")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
ENDIF()
FIND_PATH(PATH_GTEST ${CMAKE_FIND_LIBRARY_PREFIXES}gtest PATHS ${LIST_DEPENDENCIES_PATH} PATH_SUFFIXES gtest)
SET(GTEST_ROOT ${PATH_GTEST}/${CMAKE_FIND_LIBRARY_PREFIXES}gtest)
FIND_PACKAGE(GTest REQUIRED)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${GTEST_BOTH_LIBRARIES})
INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS})
# OpenViBE Module
INCLUDE("FindModuleGeometry")
# OpenViBE Third Party
INCLUDE("FindThirdPartyEigen")
INCLUDE("FindThirdPartyBoost")
# ---------------------------------
# Target macros
# Defines target operating system, architecture and compiler
# ---------------------------------
SET_BUILD_PLATFORM()
# -----------------------------
# Install files
# -----------------------------
ADD_TEST(NAME test_Geometry COMMAND ${PROJECT_NAME})
OV_INSTALL_LAUNCH_SCRIPT(SCRIPT_PREFIX "${PROJECT_NAME}" EXECUTABLE_NAME "${PROJECT_NAME}")
INSTALL(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION ${DIST_BINDIR}
LIBRARY DESTINATION ${DIST_LIBDIR}
ARCHIVE DESTINATION ${DIST_LIBDIR})
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,36 @@
#include "gtest/gtest.h"
// ReSharper disable CppUnusedIncludeDirective
#include "test_Basics.hpp"
#include "test_Covariance.hpp"
#include "test_Mean.hpp"
#include "test_Median.hpp"
#include "test_Misc.hpp"
#include "test_Distance.hpp"
#include "test_Geodesics.hpp"
#include "test_Featurization.hpp"
#include "test_Classifier.hpp"
#include "test_MatrixClassifier.hpp"
#include "test_ASR.hpp"
// ReSharper restore CppUnusedIncludeDirective
int main(int argc, char** argv)
{
try
{
//Code coverage tips (this functions are used only if tests failed)
const size_t dumS = 0;
const double dumD = 0;
const Eigen::MatrixXd dumM = Eigen::MatrixXd::Identity(2, 2);
const std::vector<int> dumV = { 0, 0 };
const Geometry::CMatrixClassifierMDM dumC;
ErrorMsg("", dumS, dumS);
ErrorMsg("", dumD, dumD);
ErrorMsg("", dumM, dumM);
ErrorMsg("", dumV, dumV);
ErrorMsg("", dumC, dumC);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
catch (std::exception&) { return 1; }
}
@@ -0,0 +1,120 @@
///-------------------------------------------------------------------------------------------------
///
/// \file misc.hpp
/// \brief Some constants and functions for google tests
/// \author Thibaut Monseigne (Inria).
/// \version 0.1.
/// \date 26/10/2018.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
/// \remarks
/// - For this test I compare the results with the <a href="https://github.com/alexandrebarachant/pyRiemann">pyRiemann</a> library (<a href="https://github.com/alexandrebarachant/pyRiemann/blob/master/LICENSE">License</a>) or <a href="http://scikit-learn.org">sklearn</a> if pyRiemman just redirect the function.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include <cmath>
#include <vector>
#include <type_traits>
#include <geometry/classifier/IMatrixClassifier.hpp>
#include <geometry/artifacts/CASR.hpp>
const std::string SEP = "\n====================\n";
//*********************************************************************************
//********** Comparison of values with epsilon tolerance for google test **********
//*********************************************************************************
/// <summary> Check if two doubles are almost equal. </summary>
/// <param name="x"> The first value. </param>
/// <param name="y"> The second value. </param>
/// <param name="epsilon"> (Optional) The epsilon tolerance. </param>
/// <returns> True if almost equal, false if not. </returns>
inline bool isAlmostEqual(const double x, const double y, const double epsilon = 0.0001) { return std::abs(x - y) < epsilon; }
/// <summary> Check if sum of two vectors are almost equal. </summary>
/// <typeparam name="T"> Generic numeric type parameter. </typeparam>
/// \copydetails isAlmostEqual(const double, const double, const double)
template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
bool isAlmostEqual(const std::vector<T>& x, const std::vector<T>& y, const double epsilon = 0.0001)
{
double xsum = 0.0, ysum = 0.0;
for (const auto& n : x) { xsum += n; }
for (const auto& n : y) { ysum += n; }
return (x.size() == y.size() && isAlmostEqual(xsum, ysum, epsilon));
}
/// <summary> Check if sum of two matrix are almost equal. </summary>
/// \copydetails isAlmostEqual(const double, const double, const double)
inline bool isAlmostEqual(const Eigen::MatrixXd& x, const Eigen::MatrixXd& y, const double epsilon = 0.0001)
{
return x.size() == y.size() && isAlmostEqual(x.cwiseAbs().sum(), y.cwiseAbs().sum(), epsilon);
}
//*****************************************************************
//********** Error Message Standardization for googltest **********
//*****************************************************************
/// <summary> Error message for size_t. </summary>
/// <param name="name"> The name of the test. </param>
/// <param name="ref"> The reference value. </param>
/// <param name="calc"> The calculate value. </param>
/// <returns> Error message. </returns>
inline std::string ErrorMsg(const std::string& name, const size_t ref, const size_t calc)
{
std::stringstream ss;
ss << SEP << name << " : Reference : " << ref << ", \tCompute : " << calc << SEP;
return ss.str();
}
/// <summary> Error message for doubles. </summary>
/// \copydetails ErrorMsg(const std::string&, const size_t, const size_t)
inline std::string ErrorMsg(const std::string& name, const double ref, const double calc)
{
std::stringstream ss;
ss << SEP << name << " : Reference : " << ref << ", \tCompute : " << calc << SEP;
return ss.str();
}
/// <summary> Error message for numeric vector. </summary>
/// <typeparam name="T"> Generic numeric type parameter. </typeparam>
/// \copydetails ErrorMsg(const std::string&, const size_t, const size_t)
template <typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
std::string ErrorMsg(const std::string& name, const std::vector<T>& ref, const std::vector<T>& calc)
{
std::stringstream ss;
ss << SEP << name << " : " << std::endl << " Reference : \t[";
for (const T& t : ref) { ss << t << ", "; }
if (!ref.empty()) { ss.seekp(ss.str().length() - 2); }
ss << "] " << std::endl << " Compute : \t[";
for (const T& t : calc) { ss << t << ", "; }
if (!ref.empty()) { ss.seekp(ss.str().length() - 2); }
ss << "] " << SEP;
return ss.str();
}
/// <summary> Error message for matrix. </summary>
/// \copydetails ErrorMsg(const std::string&, const size_t, const size_t)
inline std::string ErrorMsg(const std::string& name, const Eigen::MatrixXd& ref, const Eigen::MatrixXd& calc)
{
std::stringstream ss;
ss << SEP << name << " : " << std::endl << "********** Reference **********\n" << ref << std::endl << "********** Compute **********\n" << calc << SEP;
return ss.str();
}
/// <summary> Error message for matrix Classifier. </summary>
/// \copydetails ErrorMsg(const std::string&, const size_t, const size_t)
inline std::string ErrorMsg(const std::string& name, const Geometry::IMatrixClassifier& ref, const Geometry::IMatrixClassifier& calc)
{
std::stringstream ss;
ss << SEP << name << " : " << std::endl << "********** Reference **********\n" << ref << std::endl << "********** Compute **********\n" << calc << SEP;
return ss.str();
}
/// <summary> Error message for ASR. </summary>
/// \copydetails ErrorMsg(const std::string&, const size_t, const size_t)
inline std::string ErrorMsg(const std::string& name, const Geometry::CASR& ref, const Geometry::CASR& calc)
{
std::stringstream ss;
ss << SEP << name << " : " << std::endl << "********** Reference **********\n" << ref << std::endl << "********** Compute **********\n" << calc << SEP;
return ss.str();
}
@@ -0,0 +1,81 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_ASR.hpp
/// \brief Tests for Artifact Subspace Reconstruction.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 29/07/2020.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
/// \remarks We use the EEglab Matlab plugin to compare result for validation
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "init.hpp"
#include "misc.hpp"
#include <geometry/artifacts/CASR.hpp>
#include <geometry/Basics.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_ASR : public testing::Test
{
protected:
std::vector<Eigen::MatrixXd> m_dataset;
void SetUp() override { m_dataset = Geometry::Vector2DTo1D(InitDataset::Dataset()); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_ASR, Train_Euclidian)
{
const Geometry::CASR ref = InitASR::Euclidian::Reference();
const Geometry::CASR calc(Geometry::EMetric::Euclidian, m_dataset);
EXPECT_TRUE(calc == ref) << ErrorMsg("Train ASR in Euclidian metric", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_ASR, Train_Riemann)
{
std::cout << "Riemannian Eigen Value isn't implemented, so result is same as Euclidian metric." << std::endl;
const Geometry::CASR ref = InitASR::Riemann::Reference();
const Geometry::CASR calc(Geometry::EMetric::Riemann, m_dataset);
EXPECT_TRUE(calc == ref) << ErrorMsg("Train ASR in Riemann metric", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_ASR, Process)
{
m_dataset = InitDataset::FirstClassDataset();
Geometry::CASR calc(Geometry::EMetric::Euclidian, m_dataset);
std::vector<Eigen::MatrixXd> testset = InitDataset::SecondClassDataset();
std::vector<Eigen::MatrixXd> result(testset.size());
for (size_t i = 0; i < testset.size(); ++i)
{
testset[i] *= 2;
EXPECT_TRUE(calc.process(testset[i], result[i])) << "ASR Process fail for sample " + std::to_string(i) + ".\n";
}
for (size_t i = 1; i < testset.size(); ++i)
{
EXPECT_FALSE(isAlmostEqual(result[i], testset[i])) << "the sample " + std::to_string(i) + " wasn't reconstructed.\n";
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_ASR, Save)
{
Geometry::CASR calc;
const Geometry::CASR ref = InitASR::Euclidian::Reference();
EXPECT_TRUE(ref.saveXML("test_ASR_Save.xml")) << "Error during Saving : " << std::endl << ref << std::endl;
EXPECT_TRUE(calc.loadXML("test_ASR_Save.xml")) << "Error during Loading : " << std::endl << calc << std::endl;
EXPECT_TRUE(ref == calc) << ErrorMsg("ASR Save", ref, calc);
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,150 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_Basics.hpp
/// \brief Tests for Basic functions of Module.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 09/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "init.hpp"
#include "misc.hpp"
#include <geometry/Basics.hpp>
#include <geometry/Metrics.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_Basics : public testing::Test
{
protected:
std::vector<std::vector<Eigen::MatrixXd>> m_dataSet;
void SetUp() override { m_dataSet = InitDataset::Dataset(); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Basics, MatrixStandardization)
{
std::vector<std::vector<Eigen::MatrixXd>> calcC, refC = InitBasics::Center::Reference();
std::vector<std::vector<Eigen::MatrixXd>> calcS, refS = InitBasics::StandardScaler::Reference();
calcC.resize(m_dataSet.size());
calcS.resize(m_dataSet.size());
for (size_t k = 0; k < m_dataSet.size(); ++k)
{
calcC[k].resize(m_dataSet[k].size());
calcS[k].resize(m_dataSet[k].size());
for (size_t i = 0; i < m_dataSet[k].size(); ++i)
{
EXPECT_TRUE(MatrixStandardization(m_dataSet[k][i], calcC[k][i], Geometry::EStandardization::Center)) << "Error During Centerization" << std::endl;
EXPECT_TRUE(MatrixStandardization(m_dataSet[k][i], calcS[k][i], Geometry::EStandardization::StandardScale)) << "Error During Standard Scaler" << std::endl;
const std::string title = "Matrix Center Sample [" + std::to_string(k) + "][" + std::to_string(i) + "]";
EXPECT_TRUE(isAlmostEqual(refC[k][i], calcC[k][i])) << ErrorMsg(title, refC[k][i], calcC[k][i]);
EXPECT_TRUE(isAlmostEqual(refS[k][i], calcS[k][i])) << ErrorMsg(title, refS[k][i], calcS[k][i]);
}
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Basics, GetElements)
{
Eigen::RowVectorXd ref(3);
const std::vector<size_t> idx{ 0, 4, 7 };
ref << -3, -6, -1;
const Eigen::RowVectorXd calc = Geometry::GetElements(m_dataSet[0][0].row(0), idx); // row = -3, -4, -5, -4, -6, -1, -4, -1, -3, -1
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("GetElements", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Basics, ARange)
{
const std::vector<size_t> ref{ 1, 3, 5, 7, 9 },
calc = Geometry::ARange(size_t(1), size_t(10), size_t(2));
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("ARange", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Basics, Vector2DTo1D)
{
std::vector<Eigen::MatrixXd> calc = Geometry::Vector2DTo1D(m_dataSet);
bool equal = true;
size_t idx = 0;
for (auto& set : m_dataSet) { for (const auto& data : set) { if (!isAlmostEqual(data, calc[idx++])) { equal = false; } } }
EXPECT_TRUE(equal) << "Vector2DTo1D fail";
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Basics, Metrics)
{
EXPECT_TRUE(toString(Geometry::EMetric::Riemann) == "Riemann");
EXPECT_TRUE(toString(Geometry::EMetric::Euclidian) == "Euclidian");
EXPECT_TRUE(toString(Geometry::EMetric::LogEuclidian) == "Log Euclidian");
EXPECT_TRUE(toString(Geometry::EMetric::LogDet) == "Log Determinant");
EXPECT_TRUE(toString(Geometry::EMetric::Kullback) == "Kullback");
EXPECT_TRUE(toString(Geometry::EMetric::ALE) == "AJD-based log-Euclidean");
EXPECT_TRUE(toString(Geometry::EMetric::Harmonic) == "Harmonic");
EXPECT_TRUE(toString(Geometry::EMetric::Wasserstein) == "Wasserstein");
EXPECT_TRUE(toString(Geometry::EMetric::Identity) == "Identity");
EXPECT_TRUE(Geometry::StringToMetric("Riemann") == Geometry::EMetric::Riemann);
EXPECT_TRUE(Geometry::StringToMetric("Euclidian") == Geometry::EMetric::Euclidian);
EXPECT_TRUE(Geometry::StringToMetric("Log Euclidian") == Geometry::EMetric::LogEuclidian);
EXPECT_TRUE(Geometry::StringToMetric("Log Determinant") == Geometry::EMetric::LogDet);
EXPECT_TRUE(Geometry::StringToMetric("Kullback") == Geometry::EMetric::Kullback);
EXPECT_TRUE(Geometry::StringToMetric("AJD-based log-Euclidean") == Geometry::EMetric::ALE);
EXPECT_TRUE(Geometry::StringToMetric("Harmonic") == Geometry::EMetric::Harmonic);
EXPECT_TRUE(Geometry::StringToMetric("Wasserstein") == Geometry::EMetric::Wasserstein);
EXPECT_TRUE(Geometry::StringToMetric("Identity") == Geometry::EMetric::Identity);
EXPECT_TRUE(Geometry::StringToMetric("") == Geometry::EMetric::Identity);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Basics, Validation)
{
const Eigen::MatrixXd m1 = Eigen::MatrixXd::Zero(2, 2),
m2 = Eigen::MatrixXd::Zero(1, 2),
m3;
std::vector<Eigen::MatrixXd> v;
EXPECT_TRUE(Geometry::InRange(1, 0, 2)); // 0 <= 1 <= 2 ?
EXPECT_FALSE(Geometry::InRange(2, 0, 1)); // 0 <= 2 <= 1 ?
EXPECT_FALSE(Geometry::AreNotEmpty(v)); // Empty Vector
v.push_back(m3);
EXPECT_FALSE(Geometry::AreNotEmpty(v)); // Vector with one empty matix
v.push_back(m1);
EXPECT_FALSE(Geometry::AreNotEmpty(v)); // Vector With one empty matrix and one non empty matrix
v.clear();
v.push_back(m1);
v.push_back(m2);
EXPECT_TRUE(Geometry::AreNotEmpty(v)); // Vector With two non empty matrix
EXPECT_TRUE(Geometry::HaveSameSize(m1, m1)); // Same matrix
EXPECT_FALSE(Geometry::HaveSameSize(m3, m3)); // Same but empty
EXPECT_FALSE(Geometry::HaveSameSize(m1, m2)); // DIfferents
EXPECT_FALSE(Geometry::HaveSameSize(m1, m3)); // One empty
EXPECT_FALSE(Geometry::HaveSameSize(v)); // Two different
EXPECT_FALSE(Geometry::AreSquare(v)); // One square
v.clear();
v.push_back(m1);
v.push_back(m1);
EXPECT_TRUE(Geometry::HaveSameSize(v) && Geometry::AreSquare(v)); // Same matrix
Geometry::MatrixPrint(m1); // Only to check
Geometry::MatrixPrint(m3); // Only to check
std::vector<std::string> vs = Geometry::Split("0,1,2,3.a\n", ",");
EXPECT_TRUE(vs.size() == 4 && vs[0] == "0" && vs[1] == "1" && vs[2] == "2" && vs[3] == "3.a") << vs.size() << " " << vs[0] << " " << vs[1] << " " << vs[2] << " " << vs[3] << std::endl;
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,53 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_Classifier.hpp
/// \brief Tests for Classifier Functions.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 09/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "misc.hpp"
#include "init.hpp"
#include <geometry/Classification.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_Classifier : public testing::Test
{
protected:
std::vector<std::vector<Eigen::RowVectorXd>> m_dataSet;
void SetUp() override
{
const std::vector<Eigen::RowVectorXd> tmp = InitFeaturization::TangentSpace::Reference();
m_dataSet = Geometry::Vector1DTo2D(tmp, { NB_TRIALS1, NB_TRIALS2 });
}
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Classifier, LSQR)
{
const Eigen::MatrixXd ref = InitClassif::LSQR::Reference();
Eigen::MatrixXd calc;
Geometry::LSQR(m_dataSet, calc);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("LSQR", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Classifier, FgDACompute)
{
const Eigen::MatrixXd ref = InitClassif::FgDACompute::Reference();
Eigen::MatrixXd calc;
Geometry::FgDACompute(m_dataSet, calc);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("FgDA", ref, calc);
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,158 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_Covariance.hpp
/// \brief Tests for Covariance Matrix Functions.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 09/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "misc.hpp"
#include "init.hpp"
#include <geometry/Covariance.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_Covariances : public testing::Test
{
protected:
std::vector<std::vector<Eigen::MatrixXd>> m_dataSet;
void SetUp() override { m_dataSet = InitDataset::Dataset(); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Covariances, Covariance_Matrix_COR)
{
std::vector<std::vector<Eigen::MatrixXd>> calc, ref = InitCovariance::COR::Dataset();
calc.resize(m_dataSet.size());
for (size_t k = 0; k < m_dataSet.size(); ++k)
{
calc[k].resize(m_dataSet[k].size());
for (size_t i = 0; i < m_dataSet[k].size(); ++i)
{
CovarianceMatrix(m_dataSet[k][i], calc[k][i], Geometry::EEstimator::COR, Geometry::EStandardization::None);
const std::string title = "Covariance Matrix COR Sample [" + std::to_string(k) + "][" + std::to_string(i) + "]";
EXPECT_TRUE(isAlmostEqual(ref[k][i], calc[k][i])) << ErrorMsg(title, ref[k][i], calc[k][i]);
}
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Covariances, Covariance_Matrix_COV)
{
std::vector<std::vector<Eigen::MatrixXd>> calc, ref = InitCovariance::COV::Dataset();
calc.resize(m_dataSet.size());
for (size_t k = 0; k < m_dataSet.size(); ++k)
{
calc[k].resize(m_dataSet[k].size());
for (size_t i = 0; i < m_dataSet[k].size(); ++i)
{
CovarianceMatrix(m_dataSet[k][i], calc[k][i], Geometry::EEstimator::COV, Geometry::EStandardization::None);
const std::string title = "Covariance Matrix COV Sample [" + std::to_string(k) + "][" + std::to_string(i) + "]";
EXPECT_TRUE(isAlmostEqual(ref[k][i], calc[k][i])) << ErrorMsg(title, ref[k][i], calc[k][i]);
}
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Covariances, Covariance_Matrix_LWF)
{
std::vector<std::vector<Eigen::MatrixXd>> calc, ref = InitCovariance::LWF::Reference();
calc.resize(m_dataSet.size());
for (size_t k = 0; k < m_dataSet.size(); ++k)
{
calc[k].resize(m_dataSet[k].size());
for (size_t i = 0; i < m_dataSet[k].size(); ++i)
{
CovarianceMatrix(m_dataSet[k][i], calc[k][i], Geometry::EEstimator::LWF, Geometry::EStandardization::Center);
const std::string title = "Covariance Matrix LWF Sample [" + std::to_string(k) + "][" + std::to_string(i) + "]";
EXPECT_TRUE(isAlmostEqual(ref[k][i], calc[k][i])) << ErrorMsg(title, ref[k][i], calc[k][i]);
}
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Covariances, Covariance_Matrix_MCD)
{
std::cout << "Not implemented" << std::endl;
std::vector<std::vector<Eigen::MatrixXd>> calc;
//std::vector<std::vector<Eigen::MatrixXd>> ref = InitCovariance::MCD::Reference();
calc.resize(m_dataSet.size());
for (size_t k = 0; k < m_dataSet.size(); ++k)
{
calc[k].resize(m_dataSet[k].size());
for (size_t i = 0; i < m_dataSet[k].size(); ++i)
{
CovarianceMatrix(m_dataSet[k][i], calc[k][i], Geometry::EEstimator::MCD, Geometry::EStandardization::Center);
//const std::string title = "Covariance Matrix MCD Sample [" + std::to_string(k) + "][" + std::to_string(i) + "]";
//EXPECT_TRUE(isAlmostEqual(ref[k][i], calc[k][i])) << ErrorMsg(title, ref[k][i], calc[k][i]);
}
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Covariances, Covariance_Matrix_OAS)
{
std::vector<std::vector<Eigen::MatrixXd>> calc, ref = InitCovariance::OAS::Reference();
calc.resize(m_dataSet.size());
for (size_t k = 0; k < m_dataSet.size(); ++k)
{
calc[k].resize(m_dataSet[k].size());
for (size_t i = 0; i < m_dataSet[k].size(); ++i)
{
CovarianceMatrix(m_dataSet[k][i], calc[k][i], Geometry::EEstimator::OAS, Geometry::EStandardization::Center);
const std::string title = "Covariance Matrix OAS Sample [" + std::to_string(k) + "][" + std::to_string(i) + "]";
EXPECT_TRUE(isAlmostEqual(ref[k][i], calc[k][i])) << ErrorMsg(title, ref[k][i], calc[k][i]);
}
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Covariances, Covariance_Matrix_SCM)
{
std::vector<std::vector<Eigen::MatrixXd>> calc, ref = InitCovariance::SCM::Reference();
calc.resize(m_dataSet.size());
for (size_t k = 0; k < m_dataSet.size(); ++k)
{
calc[k].resize(m_dataSet[k].size());
for (size_t i = 0; i < m_dataSet[k].size(); ++i)
{
CovarianceMatrix(m_dataSet[k][i], calc[k][i], Geometry::EEstimator::SCM, Geometry::EStandardization::None);
const std::string title = "Covariance Matrix SCM Sample [" + std::to_string(k) + "][" + std::to_string(i) + "]";
EXPECT_TRUE(isAlmostEqual(ref[k][i], calc[k][i])) << ErrorMsg(title, ref[k][i], calc[k][i]);
}
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Covariances, Covariance_Matrix_IDE)
{
std::vector<std::vector<Eigen::MatrixXd>> calc;
const Eigen::MatrixXd ref = Eigen::MatrixXd::Identity(NB_CHAN, NB_CHAN);
calc.resize(m_dataSet.size());
for (size_t k = 0; k < m_dataSet.size(); ++k)
{
calc[k].resize(m_dataSet[k].size());
for (size_t i = 0; i < m_dataSet[k].size(); ++i)
{
CovarianceMatrix(m_dataSet[k][i], calc[k][i], Geometry::EEstimator::IDE, Geometry::EStandardization::None);
const std::string title = "Covariance Matrix IDE Sample [" + std::to_string(k) + "][" + std::to_string(i) + "]";
EXPECT_TRUE(isAlmostEqual(ref, calc[k][i])) << ErrorMsg(title, ref, calc[k][i]);
}
}
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,119 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_Distance.hpp
/// \brief Tests for Distance Functions.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 09/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "misc.hpp"
#include "init.hpp"
#include <geometry/Distance.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_Distances : public testing::Test
{
protected:
std::vector<Eigen::MatrixXd> m_dataSet;
void SetUp() override { m_dataSet = Geometry::Vector2DTo1D(InitCovariance::LWF::Reference()); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Distances, Euclidian)
{
const std::vector<double> ref = InitDistance::Euclidian::Reference();
const Eigen::MatrixXd mean = InitMeans::Euclidian::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
const double calc = Distance(mean, m_dataSet[i], Geometry::EMetric::Euclidian);
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Distance Euclidian Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Distances, LogEuclidian)
{
const std::vector<double> ref = InitDistance::LogEuclidian::Reference();
const Eigen::MatrixXd mean = InitMeans::LogEuclidian::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
const double calc = Distance(mean, m_dataSet[i], Geometry::EMetric::LogEuclidian);
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Distance LogEuclidian Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Distances, Riemann)
{
const std::vector<double> ref = InitDistance::Riemann::Reference();
const Eigen::MatrixXd mean = InitMeans::Riemann::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
const double calc = Distance(mean, m_dataSet[i], Geometry::EMetric::Riemann);
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Distance Riemann Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Distances, LogDet)
{
const std::vector<double> ref = InitDistance::LogDeterminant::Reference();
const Eigen::MatrixXd mean = InitMeans::LogDeterminant::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
const double calc = Distance(mean, m_dataSet[i], Geometry::EMetric::LogDet);
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Distance LogDet Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Distances, Kullback)
{
const std::vector<double> ref = InitDistance::Kullback::Reference();
const Eigen::MatrixXd mean = InitMeans::Kullback::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
const double calc = Distance(mean, m_dataSet[i], Geometry::EMetric::Kullback);
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Distance Kullback Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Distances, Wasserstein)
{
const std::vector<double> ref = InitDistance::Wasserstein::Reference();
const Eigen::MatrixXd mean = InitMeans::Wasserstein::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
const double calc = Distance(mean, m_dataSet[i], Geometry::EMetric::Wasserstein);
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Distance Wasserstein Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Distances, Identity)
{
const Eigen::MatrixXd mean = InitMeans::Wasserstein::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
const double calc = Distance(mean, m_dataSet[i], Geometry::EMetric::Identity);
EXPECT_TRUE(isAlmostEqual(1, calc)) << ErrorMsg("Distance Wasserstein Sample [" + std::to_string(i) + "]", 1, calc);
}
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,91 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_Featurization.hpp
/// \brief Tests for Matrix Featurization Functions.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 09/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "misc.hpp"
#include "init.hpp"
#include <geometry/Featurization.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_Featurization : public testing::Test
{
protected:
std::vector<Eigen::MatrixXd> m_dataSet;
void SetUp() override { m_dataSet = Geometry::Vector2DTo1D(InitCovariance::LWF::Reference()); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Featurization, TangentSpace)
{
const std::vector<Eigen::RowVectorXd> ref = InitFeaturization::TangentSpace::Reference();
const Eigen::MatrixXd mean = InitMeans::Riemann::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
Eigen::RowVectorXd calc;
EXPECT_TRUE(Geometry::Featurization(m_dataSet[i], calc, true, mean)) << "Error During Processing";
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("TangentSpace Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Featurization, UnTangentSpace)
{
const std::vector<Eigen::RowVectorXd> ref = InitFeaturization::TangentSpace::Reference();
const Eigen::MatrixXd mean = InitMeans::Riemann::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
Eigen::MatrixXd calc;
EXPECT_TRUE(Geometry::UnFeaturization(ref[i], calc, true, mean)) << "Error During Processing";
EXPECT_TRUE(isAlmostEqual(m_dataSet[i], calc)) << ErrorMsg("UnTangentSpace Sample [" + std::to_string(i) + "]", m_dataSet[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Featurization, Squeeze)
{
const std::vector<Eigen::RowVectorXd> ref = InitFeaturization::Squeeze::Reference();
const std::vector<Eigen::RowVectorXd> refDiag = InitFeaturization::SqueezeDiag::Reference();
const Eigen::MatrixXd mean = InitMeans::Riemann::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
Eigen::RowVectorXd calc;
EXPECT_TRUE(Geometry::Featurization(m_dataSet[i], calc, false, mean)) << "Error During Processing";
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Squeeze Sample [" + std::to_string(i) + "]", ref[i], calc);
EXPECT_TRUE(Geometry::SqueezeUpperTriangle(m_dataSet[i], calc, false)) << "Error During Processing";
EXPECT_TRUE(isAlmostEqual(refDiag[i], calc)) << ErrorMsg("Squeeze Sample [" + std::to_string(i) + "]", refDiag[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Featurization, UnSqueeze)
{
const std::vector<Eigen::RowVectorXd> ref = InitFeaturization::Squeeze::Reference();
const std::vector<Eigen::RowVectorXd> refDiag = InitFeaturization::SqueezeDiag::Reference();
const Eigen::MatrixXd mean = InitMeans::Riemann::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
Eigen::MatrixXd calc;
EXPECT_TRUE(Geometry::UnFeaturization(ref[i], calc, false, mean)) << "Error During Processing";
EXPECT_TRUE(isAlmostEqual(m_dataSet[i], calc)) << ErrorMsg("UnSqueeze Sample [" + std::to_string(i) + "]", m_dataSet[i], calc);
EXPECT_TRUE(Geometry::UnSqueezeUpperTriangle(refDiag[i], calc, false)) << "Error During Processing";
EXPECT_TRUE(isAlmostEqual(m_dataSet[i], calc)) << ErrorMsg("UnSqueeze Sample [" + std::to_string(i) + "]", m_dataSet[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,84 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_Geodesics.hpp
/// \brief Tests for Geodesic Functions.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 09/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "misc.hpp"
#include "init.hpp"
#include <geometry/Geodesic.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_Geodesic : public testing::Test
{
protected:
std::vector<Eigen::MatrixXd> m_dataSet;
void SetUp() override { m_dataSet = Geometry::Vector2DTo1D(InitCovariance::LWF::Reference()); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Geodesic, Euclidian)
{
const std::vector<Eigen::MatrixXd> ref = InitGeodesics::Euclidian::Reference();
const Eigen::MatrixXd mean = InitMeans::Euclidian::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
Eigen::MatrixXd calc;
Geodesic(mean, m_dataSet[i], calc, Geometry::EMetric::Euclidian, 0.5);
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Geodesic Euclidian Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Geodesic, LogEuclidian)
{
const std::vector<Eigen::MatrixXd> ref = InitGeodesics::LogEuclidian::Reference();
const Eigen::MatrixXd mean = InitMeans::LogEuclidian::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
Eigen::MatrixXd calc;
Geodesic(mean, m_dataSet[i], calc, Geometry::EMetric::LogEuclidian, 0.5);
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Geodesic LogEuclidian Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Geodesic, Riemann)
{
const std::vector<Eigen::MatrixXd> ref = InitGeodesics::Riemann::Reference();
const Eigen::MatrixXd mean = InitMeans::Riemann::Reference();
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
Eigen::MatrixXd calc;
Geodesic(mean, m_dataSet[i], calc, Geometry::EMetric::Riemann, 0.5);
EXPECT_TRUE(isAlmostEqual(ref[i], calc)) << ErrorMsg("Geodesic Riemann Sample [" + std::to_string(i) + "]", ref[i], calc);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Geodesic, Identity)
{
const Eigen::MatrixXd mean = InitMeans::Riemann::Reference(), ref = Eigen::MatrixXd::Identity(NB_CHAN, NB_CHAN);
for (size_t i = 0; i < m_dataSet.size(); ++i)
{
Eigen::MatrixXd calc;
Geodesic(mean, m_dataSet[i], calc, Geometry::EMetric::Identity, 0.5);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Geodesic Identity Sample [" + std::to_string(i) + "]", ref, calc);
}
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,296 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_MatrixClassifier.hpp
/// \brief Tests for Matrix Classifiers.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 09/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
/// \remarks
/// - For this tests I compare the results with the <a href="https://github.com/alexandrebarachant/pyRiemann">pyRiemann</a> library (<a href="https://github.com/alexandrebarachant/pyRiemann/blob/master/LICENSE">License</a>) or <a href="http://scikit-learn.org">sklearn</a> if pyRiemman just redirect the function.
/// - For the adaptation Classification tests I compare the results with the <a href="https://github.com/alexandrebarachant/covariancetoolbox">covariancetoolbox</a> Matlab library (<a href="https://github.com/alexandrebarachant/covariancetoolbox/blob/master/COPYING">License</a>).
/// - The Matlab toolbox is older and Riemannian mean estimation is diff�rent the test are adapted to switch between the two library
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "misc.hpp"
#include "init.hpp"
#include <geometry/classifier/CMatrixClassifierMDM.hpp>
#include <geometry/classifier/CMatrixClassifierMDMRebias.hpp>
#include <geometry/classifier/CMatrixClassifierFgMDM.hpp>
#include <geometry/classifier/CMatrixClassifierFgMDMRT.hpp>
#include <geometry/classifier/CMatrixClassifierFgMDMRTRebias.hpp>
static const std::vector<std::vector<double>> EMPTY_DIST;
//---------------------------------------------------------------------------------------------------
static void TestClassify(Geometry::IMatrixClassifier& calc, const std::vector<std::vector<Eigen::MatrixXd>>& dataset, const std::vector<size_t>& prediction,
const std::vector<std::vector<double>>& predictionDistance, const Geometry::EAdaptations& adapt)
{
Eigen::MatrixXd result = Eigen::MatrixXd::Zero(NB_CLASS, NB_CLASS);
size_t idx = 0;
for (size_t k = 0; k < dataset.size(); ++k)
{
for (size_t i = 0; i < dataset[k].size(); ++i)
{
const std::string text = "sample [" + std::to_string(k) + "][" + std::to_string(i) + "]";
size_t classid = 0;
std::vector<double> distance, probability;
EXPECT_TRUE(calc.classify(dataset[k][i], classid, distance, probability, adapt, k)) << "Error during Classify " << text;
if (idx < prediction.size()) { EXPECT_TRUE(prediction[idx] == classid) << ErrorMsg("Prediction " + text, prediction[idx], classid); }
if (idx < predictionDistance.size())
{
EXPECT_TRUE(isAlmostEqual(predictionDistance[idx], distance)) << ErrorMsg("Prediction Distance " + text, predictionDistance[idx], distance);
}
idx++;
result(k, classid)++;
}
}
std::cout << "***** Classifier : *****" << std::endl << calc << std::endl << "***** Result : *****" << std::endl << result << std::endl;
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
class Tests_MatrixClassifier : public testing::Test
{
protected:
std::vector<std::vector<Eigen::MatrixXd>> m_dataSet;
void SetUp() override { m_dataSet = InitCovariance::LWF::Reference(); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Train)
{
const Geometry::CMatrixClassifierMDM ref = InitMatrixClassif::MDM::Reference();
Geometry::CMatrixClassifierMDM calc;
EXPECT_TRUE(calc.train(m_dataSet)) << "Error during Training : " << std::endl << calc << std::endl;
EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Train", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Classifify)
{
Geometry::CMatrixClassifierMDM calc = InitMatrixClassif::MDM::ReferenceMatlab();
TestClassify(calc, m_dataSet, InitMatrixClassif::MDM::Prediction(), InitMatrixClassif::MDM::PredictionDistance(), Geometry::EAdaptations::None);
const Geometry::CMatrixClassifierMDM ref = InitMatrixClassif::MDM::ReferenceMatlab(); // No Change
EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Classify Change without adaptation mode", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Classifify_Adapt_Supervised)
{
Geometry::CMatrixClassifierMDM calc = InitMatrixClassif::MDM::ReferenceMatlab();
TestClassify(calc, m_dataSet, InitMatrixClassif::MDM::PredictionSupervised(), InitMatrixClassif::MDM::PredictionDistanceSupervised(),
Geometry::EAdaptations::Supervised);
const Geometry::CMatrixClassifierMDM ref = InitMatrixClassif::MDM::AfterSupervised();
EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Adapt Classify after Supervised adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Classifify_Adapt_Unsupervised)
{
Geometry::CMatrixClassifierMDM calc = InitMatrixClassif::MDM::ReferenceMatlab();
TestClassify(calc, m_dataSet, InitMatrixClassif::MDM::PredictionUnSupervised(), InitMatrixClassif::MDM::PredictionDistanceUnSupervised(),
Geometry::EAdaptations::Unsupervised);
const Geometry::CMatrixClassifierMDM ref = InitMatrixClassif::MDM::AfterUnSupervised();
EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Adapt Classify after Unsupervised adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Save)
{
Geometry::CMatrixClassifierMDM calc;
const Geometry::CMatrixClassifierMDM ref = InitMatrixClassif::MDM::Reference();
EXPECT_TRUE(ref.saveXML("test_MDM_Save.xml")) << "Error during Saving : " << std::endl << ref << std::endl;
EXPECT_TRUE(calc.loadXML("test_MDM_Save.xml")) << "Error during Loading : " << std::endl << calc << std::endl;
EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Save", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDMRT_Train)
{
const Geometry::CMatrixClassifierFgMDMRT ref = InitMatrixClassif::FgMDMRT::Reference();
Geometry::CMatrixClassifierFgMDMRT calc;
EXPECT_TRUE(calc.train(m_dataSet)) << "Error during Training : " << std::endl << calc << std::endl;
EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Train", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDMRT_Classifify)
{
Geometry::CMatrixClassifierFgMDMRT calc = InitMatrixClassif::FgMDMRT::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::FgMDMRT::Prediction(), InitMatrixClassif::FgMDMRT::PredictionDistance(), Geometry::EAdaptations::None);
const Geometry::CMatrixClassifierFgMDMRT ref = InitMatrixClassif::FgMDMRT::Reference();
EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Classify Change without adaptation mode", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDMRT_Classifify_Adapt_Supervised)
{
Geometry::CMatrixClassifierFgMDMRT calc = InitMatrixClassif::FgMDMRT::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::FgMDMRT::PredictionSupervised(), EMPTY_DIST, Geometry::EAdaptations::Supervised);
//const Geometry::CMatrixClassifierFgMDMRT ref = InitMatrixClassif::FgMDMRT::AfterSupervised();
//EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Adapt Classify after Supervised RT adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDMRT_Classifify_Adapt_Unsupervised)
{
Geometry::CMatrixClassifierFgMDMRT calc(InitMatrixClassif::FgMDMRT::Reference());
TestClassify(calc, m_dataSet, InitMatrixClassif::FgMDMRT::PredictionUnSupervised(), EMPTY_DIST, Geometry::EAdaptations::Unsupervised);
//const Geometry::CMatrixClassifierFgMDMRT ref = InitMatrixClassif::FgMDMRT::AfterUnSupervised();
//EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Adapt Classify after Unsupervised RT adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDMRT_Save)
{
Geometry::CMatrixClassifierFgMDMRT calc;
const Geometry::CMatrixClassifierFgMDMRT ref = InitMatrixClassif::FgMDMRT::Reference();
EXPECT_TRUE(ref.saveXML("test_FgMDM_Save.xml")) << "Error during Saving : " << std::endl << ref << std::endl;
EXPECT_TRUE(calc.loadXML("test_FgMDM_Save.xml")) << "Error during Loading : " << std::endl << calc << std::endl;
EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Save", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDM_Classifify_Adapt_Supervised)
{
Geometry::CMatrixClassifierFgMDM calc = InitMatrixClassif::FgMDM::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::FgMDM::PredictionSupervised(), EMPTY_DIST, Geometry::EAdaptations::Supervised);
//const Geometry::CMatrixClassifierFgMDM ref = InitMatrixClassif::FgMDM::AfterSupervised();
//EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Adapt Classify after Supervised adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDM_Classifify_Adapt_Unsupervised)
{
Geometry::CMatrixClassifierFgMDM calc = InitMatrixClassif::FgMDM::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::FgMDM::PredictionUnSupervised(), EMPTY_DIST, Geometry::EAdaptations::Unsupervised);
//const Geometry::CMatrixClassifierFgMDM ref = InitMatrixClassif::FgMDM::AfterUnSupervised();
//EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Adapt Classify after Unsupervised adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Rebias_Train)
{
Geometry::CMatrixClassifierMDMRebias calc;
EXPECT_TRUE(calc.train(m_dataSet)) << "Error during Training : " << std::endl << calc << std::endl;
//const Geometry::CMatrixClassifierMDMRebias ref = InitMatrixClassif::MDMRebias::Reference();
//EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Rebias Train", ref, calc); // The mean method is different in matlab toolbox and python toolbox
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Rebias_Classifify)
{
Geometry::CMatrixClassifierMDMRebias calc = InitMatrixClassif::MDMRebias::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::MDMRebias::Prediction(), InitMatrixClassif::MDMRebias::PredictionDistance(), Geometry::EAdaptations::None);
const Geometry::CMatrixClassifierMDMRebias ref = InitMatrixClassif::MDMRebias::After(); // No Class change but Rebias yes
EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Rebias Classify Change without adaptation mode", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Rebias_Classifify_Adapt_Supervised)
{
Geometry::CMatrixClassifierMDMRebias calc = InitMatrixClassif::MDMRebias::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::MDMRebias::PredictionSupervised(), InitMatrixClassif::MDMRebias::PredictionDistanceSupervised(),
Geometry::EAdaptations::Supervised);
const Geometry::CMatrixClassifierMDMRebias ref = InitMatrixClassif::MDMRebias::AfterSupervised();
EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Rebias Adapt Classify after Supervised adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Rebias_Classifify_Adapt_Unsupervised)
{
Geometry::CMatrixClassifierMDMRebias calc = InitMatrixClassif::MDMRebias::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::MDMRebias::PredictionUnSupervised(), InitMatrixClassif::MDMRebias::PredictionDistanceUnSupervised(),
Geometry::EAdaptations::Unsupervised);
const Geometry::CMatrixClassifierMDMRebias ref = InitMatrixClassif::MDMRebias::AfterUnSupervised();
EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Rebias Adapt Classify after Unsupervised adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, MDM_Rebias_Save)
{
Geometry::CMatrixClassifierMDMRebias calc;
const Geometry::CMatrixClassifierMDMRebias ref = InitMatrixClassif::MDMRebias::Reference();
EXPECT_TRUE(ref.saveXML("test_MDM_Rebias_Save.xml")) << "Error during Saving : " << std::endl << ref << std::endl;
EXPECT_TRUE(calc.loadXML("test_MDM_Rebias_Save.xml")) << "Error during Loading : " << std::endl << calc << std::endl;
EXPECT_TRUE(ref == calc) << ErrorMsg("MDM Rebias Save", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDM_RT_Rebias_Train)
{
Geometry::CMatrixClassifierFgMDMRTRebias calc;
EXPECT_TRUE(calc.train(m_dataSet)) << "Error during Training : " << std::endl << calc << std::endl;
const Geometry::CMatrixClassifierFgMDMRTRebias ref = InitMatrixClassif::FgMDMRTRebias::Reference();
EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Rebias Train", ref, calc); // The mean method is different in matlab toolbox and python toolbox
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDM_RT_Rebias_Save)
{
Geometry::CMatrixClassifierFgMDMRTRebias calc;
const Geometry::CMatrixClassifierFgMDMRTRebias ref = InitMatrixClassif::FgMDMRTRebias::Reference();
EXPECT_TRUE(ref.saveXML("test_FgMDM_Rebias_Save.xml")) << "Error during Saving : " << std::endl << ref << std::endl;
EXPECT_TRUE(calc.loadXML("test_FgMDM_Rebias_Save.xml")) << "Error during Loading : " << std::endl << calc << std::endl;
EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Rebias Save", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDM_RT_Rebias_Classifify)
{
Geometry::CMatrixClassifierFgMDMRTRebias calc = InitMatrixClassif::FgMDMRTRebias::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::FgMDMRTRebias::Prediction(), EMPTY_DIST, Geometry::EAdaptations::None);
//const Geometry::CMatrixClassifierFgMDMRTRebias ref = InitMatrixClassif::FgMDMRTRebias::After();
//EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Rebias Classify Change without adaptation mode", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDM_RT_Rebias_Classifify_Adapt_Supervised)
{
Geometry::CMatrixClassifierFgMDMRTRebias calc = InitMatrixClassif::FgMDMRTRebias::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::FgMDMRTRebias::PredictionSupervised(), EMPTY_DIST, Geometry::EAdaptations::Supervised);
//const Geometry::CMatrixClassifierFgMDMRTRebias ref = InitMatrixClassif::FgMDMRTRebias::AfterSupervised();
//EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Rebias Adapt Classify after Supervised adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_MatrixClassifier, FgMDM_RT_Rebias_Classifify_Adapt_Unsupervised)
{
Geometry::CMatrixClassifierFgMDMRTRebias calc = InitMatrixClassif::FgMDMRTRebias::Reference();
TestClassify(calc, m_dataSet, InitMatrixClassif::FgMDMRTRebias::PredictionUnSupervised(), EMPTY_DIST, Geometry::EAdaptations::Unsupervised);
//const Geometry::CMatrixClassifierFgMDMRTRebias ref = InitMatrixClassif::FgMDMRTRebias::AfterUnSupervised();
//EXPECT_TRUE(ref == calc) << ErrorMsg("FgMDM Rebias Adapt Classify after Unsupervised adaptation", ref, calc);
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,135 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_Mean.hpp
/// \brief Tests for Mean Functions.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 09/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "misc.hpp"
#include "init.hpp"
#include <geometry/Mean.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_Means : public testing::Test
{
protected:
std::vector<Eigen::MatrixXd> m_dataSet;
void SetUp() override { m_dataSet = Geometry::Vector2DTo1D(InitCovariance::LWF::Reference()); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, BadInput)
{
std::vector<Eigen::MatrixXd> bad;
Eigen::MatrixXd calc;
EXPECT_FALSE(Mean(bad, calc, Geometry::EMetric::Riemann));
bad.emplace_back(Eigen::MatrixXd::Zero(1, 2));
bad.emplace_back(Eigen::MatrixXd::Zero(1, 2));
EXPECT_FALSE(Mean(bad, calc, Geometry::EMetric::Riemann));
bad.emplace_back(Eigen::MatrixXd::Zero(2, 2));
EXPECT_FALSE(Mean(bad, calc, Geometry::EMetric::Riemann));
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, Euclidian)
{
const Eigen::MatrixXd ref = InitMeans::Euclidian::Reference();
Eigen::MatrixXd calc;
Mean(m_dataSet, calc, Geometry::EMetric::Euclidian);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Mean Matrix Euclidian", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, LogEuclidian)
{
const Eigen::MatrixXd ref = InitMeans::LogEuclidian::Reference();
Eigen::MatrixXd calc;
Mean(m_dataSet, calc, Geometry::EMetric::LogEuclidian);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Mean Matrix LogEuclidian", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, Riemann)
{
const Eigen::MatrixXd ref = InitMeans::Riemann::Reference();
Eigen::MatrixXd calc;
Mean(m_dataSet, calc, Geometry::EMetric::Riemann);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Mean Matrix Riemann", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, LogDet)
{
const Eigen::MatrixXd ref = InitMeans::LogDeterminant::Reference();
Eigen::MatrixXd calc;
Mean(m_dataSet, calc, Geometry::EMetric::LogDet);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Mean Matrix LogDet", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, Kullback)
{
const Eigen::MatrixXd ref = InitMeans::Kullback::Reference();
Eigen::MatrixXd calc;
Mean(m_dataSet, calc, Geometry::EMetric::Kullback);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Mean Matrix Kullback", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, Wasserstein)
{
std::cout << "Precision Error" << std::endl;
Eigen::MatrixXd calc;
Mean(m_dataSet, calc, Geometry::EMetric::Wasserstein);
//const Eigen::MatrixXd ref = InitMeans::Wasserstein::Reference();
//EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Mean Matrix Wasserstein", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, ALE)
{
std::cout << "Not implemented" << std::endl;
Eigen::MatrixXd calc;
Mean(m_dataSet, calc, Geometry::EMetric::ALE);
//const Eigen::MatrixXd ref = InitMeans::ALE::Reference();
//EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Mean Matrix ALE", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, Harmonic)
{
const Eigen::MatrixXd ref = InitMeans::Harmonic::Reference();
Eigen::MatrixXd calc;
Mean(m_dataSet, calc, Geometry::EMetric::Harmonic);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Mean Matrix Harmonic", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Means, Identity)
{
const Eigen::MatrixXd ref = InitMeans::Identity::Reference();
Eigen::MatrixXd calc;
Mean(m_dataSet, calc, Geometry::EMetric::Identity);
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Mean Matrix Identity", ref, calc);
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,86 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_Median.hpp
/// \brief Tests for Median Functions.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 29/07/2020.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
/// \remarks We use the EEglab Matlab plugin to compare result for validation
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "init.hpp"
#include "misc.hpp"
#include <geometry/Basics.hpp>
#include <geometry/Median.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_Median : public testing::Test
{
protected:
std::vector<Eigen::MatrixXd> m_dataSet;
void SetUp() override { m_dataSet = Geometry::Vector2DTo1D(InitCovariance::LWF::Reference()); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Median, Simple_Median)
{
std::vector<double> v{ 5, 6, 4, 3, 2, 6, 7, 9, 3 };
double calc = Geometry::Median(v);
EXPECT_EQ(calc, 5);
v.pop_back();
calc = Geometry::Median(v);
EXPECT_EQ(calc, 5.5);
Eigen::MatrixXd m(3, 3);
m << 5, 6, 4, 3, 2, 6, 7, 9, 3;
calc = Geometry::Median(m);
EXPECT_EQ(calc, 5);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Median, Euclidian)
{
Eigen::MatrixXd calc;
Eigen::MatrixXd ref(3, 3);
ref << 1.749537973777478, 0.002960131606861, 0.020507254841909,
0.002960131606861, 1.754563395557952, 0.043042786354499,
0.020507254841909, 0.043042786354499, 1.057672472691352;
EXPECT_TRUE(Geometry::Median(m_dataSet, calc, 0.0001, 50, Geometry::EMetric::Euclidian)) << "Error During Median Computing";
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Euclidian Median of Dataset", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Median, Riemann)
{
Eigen::MatrixXd calc;
Eigen::MatrixXd ref(3, 3);
ref << 1.851330747504982, 0.002002346316770, 0.022122030618131,
0.002002346316770, 1.644242996651016, 0.033655563302757,
0.022122030618131, 0.033655563302757, 0.851184143800763;
EXPECT_TRUE(Geometry::Median(m_dataSet, calc, 0.0001, 50, Geometry::EMetric::Riemann)) << "Error During Median Computes";
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Riemann Median of Dataset", ref, calc);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Median, Identity)
{
const Eigen::MatrixXd ref = InitMeans::Identity::Reference();
Eigen::MatrixXd calc;
EXPECT_TRUE(Geometry::Median(m_dataSet, calc, 0.0001, 50, Geometry::EMetric::Identity)) << "Error During Median Computes";
EXPECT_TRUE(isAlmostEqual(ref, calc)) << ErrorMsg("Identity Median of Dataset", ref, calc);
}
//---------------------------------------------------------------------------------------------------
@@ -0,0 +1,158 @@
///-------------------------------------------------------------------------------------------------
///
/// \file test_Misc.hpp
/// \brief Tests for Misc Functions of module.
/// \author Thibaut Monseigne (Inria).
/// \version 1.0.
/// \date 29/07/2020.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>.
/// \remarks We use the EEglab Matlab plugin to compare result for validation
///
///-------------------------------------------------------------------------------------------------
#pragma once
#include "gtest/gtest.h"
#include "init.hpp"
#include "misc.hpp"
#include <geometry/Misc.hpp>
#include <geometry/Basics.hpp>
//---------------------------------------------------------------------------------------------------
class Tests_Misc : public testing::Test
{
//protected:
// std::vector<Eigen::MatrixXd> m_dataSet;
//
// void SetUp() override { m_dataSet = Vector2DTo1D(InitCovariance::LWF::Reference()); }
};
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Misc, Double_Range)
{
const std::vector<double> calc1 = Geometry::doubleRange(0, 10, 2), calc2 = Geometry::doubleRange(0, 10, 2, false),
calc3 = Geometry::doubleRange(0.15, 3.05, 0.5), calc4 = Geometry::doubleRange(0.15, 3.05, 0.5, false),
ref1 = { 0, 2, 4, 6, 8, 10 }, ref2 = { 0, 2, 4, 6, 8 },
ref3 = { 0.15, 0.65, 1.15, 1.65, 2.15, 2.65 }, ref4 = { 0.15, 0.65, 1.15, 1.65, 2.15, 2.65 };
EXPECT_TRUE(isAlmostEqual(ref1, calc1)) << ErrorMsg("Double closed Range with integer value", ref1, calc1);
EXPECT_TRUE(isAlmostEqual(ref2, calc2)) << ErrorMsg("Double opened Range with integer value", ref2, calc2);
EXPECT_TRUE(isAlmostEqual(ref3, calc3)) << ErrorMsg("Double closed Range with double value", ref3, calc3);
EXPECT_TRUE(isAlmostEqual(ref4, calc4)) << ErrorMsg("Double opened Range with double value", ref4, calc4);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Misc, Round_Index_Range)
{
const std::vector<size_t> calc1 = Geometry::RoundIndexRange(0, 10, 2), calc2 = Geometry::RoundIndexRange(0, 10, 2, false),
calc3 = Geometry::RoundIndexRange(0.15, 3.15, 0.2), calc4 = Geometry::RoundIndexRange(0.15, 3.05, 0.2, false, false),
ref1 = { 0, 2, 4, 6, 8, 10 }, ref2 = { 0, 2, 4, 6, 8 },
ref3 = { 0, 1, 2, 3 }, ref4 = { 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3 };
EXPECT_TRUE(isAlmostEqual(ref1, calc1)) << ErrorMsg("Round Index closed Range with integer value", ref1, calc1);
EXPECT_TRUE(isAlmostEqual(ref2, calc2)) << ErrorMsg("Round Index opened Range with integer value", ref2, calc2);
EXPECT_TRUE(isAlmostEqual(ref3, calc3)) << ErrorMsg("Round Index closed Range with double value", ref3, calc3);
EXPECT_TRUE(isAlmostEqual(ref4, calc4)) << ErrorMsg("Round Index opened Range with double value", ref4, calc4);
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Misc, Bin_Histogramm)
{
//========== Create Dataset ==========
const std::vector<Eigen::MatrixXd> matrices = Geometry::Vector2DTo1D(InitDataset::Dataset());
std::vector<std::vector<double>> dataset(NB_CHAN);
// Transform Dataset to vector per channel
for (size_t i = 0; i < NB_CHAN; ++i) { dataset[i].reserve(NB_SAMPLE * matrices.size()); }
for (const auto& m : matrices) { for (size_t i = 0; i < NB_CHAN; ++i) { for (size_t j = 0; j < NB_SAMPLE; ++j) { dataset[i].push_back(m(i, j)); } } }
// Sort and remove first (to begin by 0)
for (auto& d : dataset)
{
std::sort(d.begin(), d.end());
const auto first = d[0];
for (auto& e : d) { e -= first; }
}
//========== Create Ref ==========
const std::vector<std::vector<size_t>> ref =
{
{ 12, 10, 0, 15, 15, 0, 6, 12, 0, 11, 11, 0, 11, 14, 3 },
{ 17, 0, 26, 0, 0, 18, 0, 28, 0, 0, 15, 0, 7, 0, 9 },
{ 36, 0, 0, 34, 0, 0, 0, 0, 0, 15, 0, 0, 20, 0, 15 }
};
//========== Test ==========
for (size_t i = 0; i < NB_CHAN; ++i)
{
const std::vector<size_t> hist = Geometry::BinHist(dataset[i], 15);
EXPECT_TRUE(isAlmostEqual(hist, ref[i])) << ErrorMsg("Bin Histogramm", hist, ref[i]);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Misc, Fit_Distribution)
{
const std::vector<Eigen::MatrixXd> matrices = Geometry::Vector2DTo1D(InitDataset::Dataset());
std::vector<std::vector<double>> dataset(NB_CHAN);
// Transform Dataset to vector per channel
for (size_t i = 0; i < NB_CHAN; ++i) { dataset[i].reserve(NB_SAMPLE * matrices.size()); }
for (const auto& m : matrices) { for (size_t i = 0; i < NB_CHAN; ++i) { for (size_t j = 0; j < NB_SAMPLE; ++j) { dataset[i].push_back(m(i, j)); } } }
// Begin Fit Distribution
std::vector<double> mu(NB_CHAN), sigma(NB_CHAN);
const std::vector<double> refMu = { -0.840258269642149, - 2.10169835819046, 0.898301641809541 },
refSigma = { 2.76541902273525, 0.435493584265319, 0.435493584265319 };
for (size_t i = 0; i < NB_CHAN; ++i)
{
Geometry::FitDistribution(dataset[i], mu[i], sigma[i]);
EXPECT_TRUE(isAlmostEqual(mu[i], refMu[i])) << ErrorMsg("Fit Distribution Mu", mu[i], refMu[i]);
EXPECT_TRUE(isAlmostEqual(sigma[i], refSigma[i])) << ErrorMsg("Fit Distribution Sigma", sigma[i], refSigma[i]);
}
}
//---------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Misc, Sorted_Eigen_Vector_Euclidian)
{
std::vector<Eigen::MatrixXd> matrices = Geometry::Vector2DTo1D(InitCovariance::LWF::Reference());
const size_t n = matrices.size();
std::vector<Eigen::MatrixXd> vectors = InitEigenVector::Euclidian::Vectors();
std::vector<std::vector<double>> values = InitEigenVector::Euclidian::Values();
for (size_t i = 0; i < n; ++i)
{
Eigen::MatrixXd vec;
std::vector<double> val;
Geometry::sortedEigenVector(matrices[i], vec, val, Geometry::EMetric::Euclidian);
EXPECT_TRUE(isAlmostEqual(vectors[i], vec)) << ErrorMsg("Eigen Vector sample " + std::to_string(i) + " : ", vectors[i], vec);
EXPECT_TRUE(isAlmostEqual(values[i], val)) << ErrorMsg("Eigen Value sample " + std::to_string(i) + " : ", values[i], val);
}
}
//---------------------------------------------------------------------------------------------------
/*
//---------------------------------------------------------------------------------------------------
TEST_F(Tests_Misc, Sorted_Eigen_Vector_Riemann)
{
std::cout << "Not implemented" << std::endl;
std::vector<Eigen::MatrixXd> matrices = Geometry::Vector2DTo1D(InitCovariance::LWF::Reference());
const size_t n = matrices.size();
//std::vector<Eigen::MatrixXd> vectors = InitEigenVector::Riemann::Vectors();
//std::vector<std::vector<double>> values = InitEigenVector::Riemann::Values();
for (size_t i = 0; i < n; ++i)
{
Eigen::MatrixXd vec;
std::vector<double> val;
Geometry::sortedEigenVector(matrices[i], vec, val, Geometry::EMetric::Riemann);
//EXPECT_TRUE(isAlmostEqual(vectors[i], vec)) << ErrorMsg("Eigen Vector sample " + std::to_string(i) + " : ", vectors[i], vec);
//EXPECT_TRUE(isAlmostEqual(values[i], val)) << ErrorMsg("Eigen Value sample " + std::to_string(i) + " : ", values[i], val);
}
}
//---------------------------------------------------------------------------------------------------
*/