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 18 : TEST_CASE_TEMPLATE("L0PseudoNorm: Testing without residual", TestType, float, double) 24 : { 25 : using Vector = Eigen::Matrix<TestType, Eigen::Dynamic, 1>; 26 : 27 12 : GIVEN("just data (no residual)") 28 : { 29 12 : IndexVector_t numCoeff(1); 30 6 : numCoeff << 4; 31 12 : VolumeDescriptor volDescr(numCoeff); 32 : 33 12 : WHEN("instantiating") 34 : { 35 12 : L0PseudoNorm<TestType> l0PseudoNorm(volDescr); 36 : 37 8 : THEN("the functional is as expected") 38 : { 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 : } 47 : 48 8 : THEN("a clone behaves as expected") 49 : { 50 4 : auto l0Clone = l0PseudoNorm.clone(); 51 : 52 2 : REQUIRE_NE(l0Clone.get(), &l0PseudoNorm); 53 2 : REQUIRE_EQ(*l0Clone, l0PseudoNorm); 54 : } 55 : 56 8 : THEN("the evaluate, gradient and Hessian work as expected") 57 : { 58 4 : Vector dataVec(volDescr.getNumberOfCoefficients()); 59 2 : dataVec << 7, 0, 2, 5; 60 4 : DataContainer<TestType> dc(volDescr, dataVec); 61 : 62 2 : REQUIRE_UNARY(checkApproxEq(l0PseudoNorm.evaluate(dc), 3)); 63 4 : REQUIRE_THROWS_AS(l0PseudoNorm.getGradient(dc), std::logic_error); 64 4 : REQUIRE_THROWS_AS(l0PseudoNorm.getHessian(dc), std::logic_error); 65 : } 66 : } 67 : } 68 6 : } 69 : 70 18 : TEST_CASE_TEMPLATE("L0PseudoNorm: Testing with residual", TestType, float, double) 71 : { 72 : using Vector = Eigen::Matrix<TestType, Eigen::Dynamic, 1>; 73 : 74 12 : GIVEN("a residual with data") 75 : { 76 12 : IndexVector_t numCoeff(1); 77 6 : numCoeff << 4; 78 12 : VolumeDescriptor volDescr(numCoeff); 79 : 80 12 : Vector randomData(volDescr.getNumberOfCoefficients()); 81 6 : randomData.setRandom(); 82 12 : DataContainer<TestType> dc(volDescr, randomData); 83 : 84 12 : Identity<TestType> idOp(volDescr); 85 : 86 12 : LinearResidual<TestType> linRes(idOp, dc); 87 : 88 12 : WHEN("instantiating") 89 : { 90 12 : L0PseudoNorm<TestType> l0PseudoNorm(linRes); 91 : 92 8 : THEN("the functional is as expected") 93 : { 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 : } 101 : 102 8 : THEN("a clone behaves as expected") 103 : { 104 4 : auto l0Clone = l0PseudoNorm.clone(); 105 : 106 2 : REQUIRE_NE(l0Clone.get(), &l0PseudoNorm); 107 2 : REQUIRE_EQ(*l0Clone, l0PseudoNorm); 108 : } 109 : 110 8 : THEN("the evaluate, gradient and Hessian work as expected") 111 : { 112 4 : Vector dataVec(volDescr.getNumberOfCoefficients()); 113 2 : dataVec.setRandom(); 114 4 : DataContainer<TestType> x(volDescr, dataVec); 115 : 116 2 : REQUIRE_UNARY(checkApproxEq(l0PseudoNorm.evaluate(x), 117 : (TestType)(randomData.array().cwiseAbs() 118 : >= std::numeric_limits<TestType>::epsilon()) 119 : .count())); 120 4 : REQUIRE_THROWS_AS(l0PseudoNorm.getGradient(x), std::logic_error); 121 4 : REQUIRE_THROWS_AS(l0PseudoNorm.getHessian(x), std::logic_error); 122 : } 123 : } 124 : } 125 6 : } 126 : 127 : TEST_SUITE_END();