LCOV - code coverage report
Current view: top level - elsa/functionals/tests - test_L1Norm.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 79 79 100.0 %
Date: 2022-08-25 03:05:39 Functions: 8 8 100.0 %

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

Generated by: LCOV version 1.14