Line data Source code
1 : /** 2 : * @file test_L0PseudoNorm.cpp 3 : * 4 : * @brief Tests for the L0PseudoNorm class 5 : * 6 : * @author Andi Braimllari 7 : */ 8 : 9 : #include <doctest/doctest.h> 10 : 11 : #include "testHelpers.h" 12 : #include "L0PseudoNorm.h" 13 : #include "LinearResidual.h" 14 : #include "Identity.h" 15 : #include "VolumeDescriptor.h" 16 : #include "TypeCasts.hpp" 17 : 18 : using namespace elsa; 19 : using namespace doctest; 20 : 21 : TEST_SUITE_BEGIN("functionals"); 22 : 23 : TEST_CASE_TEMPLATE("L0PseudoNorm: Testing without residual", TestType, float, double) 24 6 : { 25 6 : using Vector = Eigen::Matrix<TestType, Eigen::Dynamic, 1>; 26 : 27 6 : GIVEN("just data (no residual)") 28 6 : { 29 6 : IndexVector_t numCoeff(1); 30 6 : numCoeff << 4; 31 6 : VolumeDescriptor volDescr(numCoeff); 32 : 33 6 : WHEN("instantiating") 34 6 : { 35 6 : L0PseudoNorm<TestType> l0PseudoNorm(volDescr); 36 : 37 6 : THEN("the functional is as expected") 38 6 : { 39 2 : REQUIRE_EQ(l0PseudoNorm.getDomainDescriptor(), volDescr); 40 : 41 2 : const auto& residual = l0PseudoNorm.getResidual(); 42 2 : const auto* linRes = downcast_safe<LinearResidual<TestType>>(&residual); 43 2 : REQUIRE_UNARY(linRes); 44 2 : REQUIRE_UNARY_FALSE(linRes->hasDataVector()); 45 2 : REQUIRE_UNARY_FALSE(linRes->hasOperator()); 46 2 : } 47 : 48 6 : THEN("a clone behaves as expected") 49 6 : { 50 2 : auto l0Clone = l0PseudoNorm.clone(); 51 : 52 2 : REQUIRE_NE(l0Clone.get(), &l0PseudoNorm); 53 2 : REQUIRE_EQ(*l0Clone, l0PseudoNorm); 54 2 : } 55 : 56 6 : THEN("the evaluate, gradient and Hessian work as expected") 57 6 : { 58 2 : Vector dataVec(volDescr.getNumberOfCoefficients()); 59 2 : dataVec << 7, 0, 2, 5; 60 2 : DataContainer<TestType> dc(volDescr, dataVec); 61 : 62 2 : REQUIRE_UNARY(checkApproxEq(l0PseudoNorm.evaluate(dc), 3)); 63 2 : REQUIRE_THROWS_AS(l0PseudoNorm.getGradient(dc), std::logic_error); 64 2 : REQUIRE_THROWS_AS(l0PseudoNorm.getHessian(dc), std::logic_error); 65 2 : } 66 6 : } 67 6 : } 68 6 : } 69 : 70 : TEST_CASE_TEMPLATE("L0PseudoNorm: Testing with residual", TestType, float, double) 71 6 : { 72 6 : using Vector = Eigen::Matrix<TestType, Eigen::Dynamic, 1>; 73 : 74 6 : GIVEN("a residual with data") 75 6 : { 76 6 : IndexVector_t numCoeff(1); 77 6 : numCoeff << 4; 78 6 : VolumeDescriptor volDescr(numCoeff); 79 : 80 6 : Vector randomData(volDescr.getNumberOfCoefficients()); 81 6 : randomData.setRandom(); 82 6 : DataContainer<TestType> dc(volDescr, randomData); 83 : 84 6 : Identity<TestType> idOp(volDescr); 85 : 86 6 : LinearResidual<TestType> linRes(idOp, dc); 87 : 88 6 : WHEN("instantiating") 89 6 : { 90 6 : L0PseudoNorm<TestType> l0PseudoNorm(linRes); 91 : 92 6 : THEN("the functional is as expected") 93 6 : { 94 2 : REQUIRE_EQ(l0PseudoNorm.getDomainDescriptor(), volDescr); 95 : 96 2 : const auto& residual = l0PseudoNorm.getResidual(); 97 2 : const auto* lRes = downcast_safe<LinearResidual<TestType>>(&residual); 98 2 : REQUIRE_UNARY(lRes); 99 2 : REQUIRE_EQ(*lRes, linRes); 100 2 : } 101 : 102 6 : THEN("a clone behaves as expected") 103 6 : { 104 2 : auto l0Clone = l0PseudoNorm.clone(); 105 : 106 2 : REQUIRE_NE(l0Clone.get(), &l0PseudoNorm); 107 2 : REQUIRE_EQ(*l0Clone, l0PseudoNorm); 108 2 : } 109 : 110 6 : THEN("the evaluate, gradient and Hessian work as expected") 111 6 : { 112 2 : Vector dataVec(volDescr.getNumberOfCoefficients()); 113 2 : dataVec.setRandom(); 114 2 : DataContainer<TestType> x(volDescr, dataVec); 115 : 116 2 : REQUIRE_UNARY(checkApproxEq(l0PseudoNorm.evaluate(x), 117 2 : (TestType)(randomData.array().cwiseAbs() 118 2 : >= std::numeric_limits<TestType>::epsilon()) 119 2 : .count())); 120 2 : REQUIRE_THROWS_AS(l0PseudoNorm.getGradient(x), std::logic_error); 121 2 : REQUIRE_THROWS_AS(l0PseudoNorm.getHessian(x), std::logic_error); 122 2 : } 123 6 : } 124 6 : } 125 6 : } 126 : 127 : TEST_SUITE_END();