LCOV - code coverage report
Current view: top level - core/tests - test_StrongTypes.cpp (source / functions) Hit Total Coverage
Test: test_coverage.info.cleaned Lines: 278 278 100.0 %
Date: 2022-02-28 03:37:41 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file test_StrongTypes.cpp
       3             :  *
       4             :  * @brief Test for Strong type classes
       5             :  *
       6             :  * @author David Frank - initial code
       7             :  */
       8             : 
       9             : #include "doctest/doctest.h"
      10             : #include "StrongTypes.h"
      11             : 
      12             : using namespace elsa;
      13             : using namespace doctest;
      14             : 
      15             : TEST_SUITE_BEGIN("core");
      16             : 
      17           4 : TEST_CASE("StrongTypes: Testing RotationAngles")
      18             : {
      19             : 
      20             :     using namespace geometry;
      21             :     using namespace geometry::detail;
      22             : 
      23           5 :     GIVEN("A 1D RotationAngles")
      24             :     {
      25           1 :         RotationAngles<1> angle{Degree{90}};
      26             : 
      27           1 :         THEN("The value and size are correct") { CHECK_EQ(angle[0], Radian{pi_t / 2}); }
      28             :     }
      29             : 
      30           5 :     GIVEN("A 2D RotationAngles")
      31             :     {
      32           1 :         RotationAngles<2> angle{Degree{90}, Radian{pi_t / 4}};
      33             : 
      34           2 :         THEN("The value and size are correct")
      35             :         {
      36           1 :             CHECK_EQ(angle[0], Radian{pi_t / 2});
      37           1 :             CHECK_EQ(angle[1], Radian{pi_t / 4});
      38             :         }
      39             :     }
      40             : 
      41           5 :     GIVEN("A 3D RotationAngles")
      42             :     {
      43           1 :         RotationAngles<3> angle{Degree{90}, Radian{pi_t / 4}, Degree{180}};
      44             : 
      45           2 :         THEN("The value and size are correct")
      46             :         {
      47           1 :             CHECK_EQ(angle[0], Radian{pi_t / 2});
      48           1 :             CHECK_EQ(angle[1], Radian{pi_t / 4});
      49           1 :             CHECK_EQ(angle[2], Radian{pi_t});
      50             :         }
      51             :     }
      52             : 
      53           5 :     GIVEN("A RotationAngles3D")
      54             :     {
      55           1 :         RotationAngles3D angle{Degree{90}, Radian{pi_t / 4}, Degree{180}};
      56             : 
      57           2 :         THEN("The value and size are correct")
      58             :         {
      59           1 :             auto [g, b, a] = angle;
      60             : 
      61           1 :             CHECK_EQ(angle[0], Radian{pi_t / 2});
      62           1 :             CHECK_EQ(angle.gamma(), Radian{pi_t / 2});
      63           1 :             CHECK_EQ(g, Radian{pi_t / 2});
      64             : 
      65           1 :             CHECK_EQ(angle[1], Radian{pi_t / 4});
      66           1 :             CHECK_EQ(angle.beta(), Radian{pi_t / 4});
      67           1 :             CHECK_EQ(b, Radian{pi_t / 4});
      68             : 
      69           1 :             CHECK_EQ(angle[2], Radian{pi_t});
      70           1 :             CHECK_EQ(angle.alpha(), Radian{pi_t});
      71           1 :             CHECK_EQ(a, Radian{pi_t});
      72             :         }
      73             :     }
      74           4 : }
      75             : 
      76           5 : TEST_CASE("StrongTypes: Testing StaticRealVector")
      77             : {
      78             :     using namespace geometry;
      79             :     using namespace geometry::detail;
      80             : 
      81           6 :     GIVEN("A default constructed StaticRealVector")
      82             :     {
      83           2 :         StaticRealVector<0> vec;
      84             : 
      85           2 :         THEN("The Eigen Vector is of size 0")
      86             :         {
      87           1 :             auto eigenVec = vec.get();
      88           1 :             REQUIRE_EQ(eigenVec.size(), 0);
      89             :         }
      90             :     }
      91             : 
      92           6 :     GIVEN("A 1D StaticRealVector")
      93             :     {
      94           2 :         StaticRealVector<1> vec{1};
      95             : 
      96           2 :         THEN("The value and size are correct")
      97             :         {
      98           1 :             auto eigenVec = vec.get();
      99           1 :             CHECK_EQ(eigenVec.size(), 1);
     100             : 
     101           1 :             CHECK_EQ(vec[0], Approx(1));
     102             :         }
     103             :     }
     104             : 
     105           6 :     GIVEN("A 2D StaticRealVector")
     106             :     {
     107           2 :         StaticRealVector<2> vec{1, 2};
     108             : 
     109           2 :         THEN("The value and size are correct")
     110             :         {
     111           1 :             auto eigenVec = vec.get();
     112           1 :             CHECK_EQ(eigenVec.size(), 2);
     113             : 
     114           1 :             CHECK_EQ(vec[0], Approx(1));
     115           1 :             CHECK_EQ(vec[1], Approx(2));
     116             :         }
     117             :     }
     118             : 
     119           6 :     GIVEN("A 3D StaticRealVector")
     120             :     {
     121           2 :         StaticRealVector<3> vec{1, 2, 3};
     122             : 
     123           2 :         THEN("The value and size are correct")
     124             :         {
     125           1 :             auto eigenVec = vec.get();
     126           1 :             CHECK_EQ(eigenVec.size(), 3);
     127             : 
     128           1 :             CHECK_EQ(vec[0], Approx(1));
     129           1 :             CHECK_EQ(vec[1], Approx(2));
     130           1 :             CHECK_EQ(vec[2], Approx(3));
     131             :         }
     132             :     }
     133             : 
     134           6 :     GIVEN("A 4D StaticRealVector")
     135             :     {
     136           2 :         StaticRealVector<4> vec{1, 2, 3, 6};
     137             : 
     138           2 :         THEN("The value and size are correct")
     139             :         {
     140           1 :             auto eigenVec = vec.get();
     141           1 :             CHECK_EQ(eigenVec.size(), 4);
     142             : 
     143           1 :             CHECK_EQ(vec[0], Approx(1));
     144           1 :             CHECK_EQ(vec[1], Approx(2));
     145           1 :             CHECK_EQ(vec[2], Approx(3));
     146           1 :             CHECK_EQ(vec[3], Approx(6));
     147             :         }
     148             :     }
     149           5 : }
     150             : 
     151           5 : TEST_CASE("StrongTypes: Testing GeometryData")
     152             : {
     153             :     using namespace geometry;
     154             :     using namespace geometry::detail;
     155             : 
     156           6 :     GIVEN("A default constructed GeometryData")
     157             :     {
     158           2 :         GeometryData<0> data;
     159             : 
     160           2 :         THEN("The Eigen Vector is of size 0")
     161             :         {
     162           1 :             CHECK_EQ(data.getSpacing().size(), 0);
     163           1 :             CHECK_EQ(data.getLocationOfOrigin().size(), 0);
     164             :         }
     165             :     }
     166             : 
     167           7 :     GIVEN("A GeometryData for 1D data")
     168             :     {
     169           6 :         GeometryData data{Spacing1D{1}, OriginShift1D{0}};
     170             : 
     171           3 :         THEN("Spacing and Origin is of correct size and correct values")
     172             :         {
     173           1 :             CHECK_EQ(data.getSpacing().size(), 1);
     174           1 :             CHECK_EQ(data.getSpacing()[0], Approx(1));
     175             : 
     176           1 :             CHECK_EQ(data.getLocationOfOrigin().size(), 1);
     177           1 :             CHECK_EQ(data.getLocationOfOrigin()[0], Approx(0));
     178             :         }
     179             : 
     180           3 :         THEN("We can construct it from coefficients")
     181             :         {
     182           1 :             auto coeffs = IndexVector_t::Constant(1, 5);
     183             : 
     184           2 :             GeometryData<1> data2{Size1D{coeffs}};
     185             : 
     186           1 :             CHECK_EQ(data2.getSpacing().size(), 1);
     187           1 :             CHECK_EQ(data2.getSpacing()[0], Approx(1));
     188             : 
     189           1 :             CHECK_EQ(data2.getLocationOfOrigin().size(), 1);
     190           1 :             CHECK_EQ(data2.getLocationOfOrigin()[0], Approx(2.5));
     191             :         }
     192             :     }
     193             : 
     194           7 :     GIVEN("A GeometryData for 2D data")
     195             :     {
     196           6 :         GeometryData data{Spacing2D{1, 0.5}, OriginShift2D{0, 0.2}};
     197             : 
     198           3 :         THEN("Spacing and Origin is of correct size and correct values")
     199             :         {
     200           1 :             CHECK_EQ(data.getSpacing().size(), 2);
     201           1 :             CHECK_EQ(data.getSpacing()[0], Approx(1));
     202           1 :             CHECK_EQ(data.getSpacing()[1], Approx(0.5));
     203             : 
     204           1 :             CHECK_EQ(data.getLocationOfOrigin().size(), 2);
     205           1 :             CHECK_EQ(data.getLocationOfOrigin()[0], Approx(0));
     206           1 :             CHECK_EQ(data.getLocationOfOrigin()[1], Approx(0.2));
     207             :         }
     208             : 
     209           3 :         THEN("We can construct it from coefficients")
     210             :         {
     211           1 :             auto coeffs = IndexVector_t::Constant(2, 5);
     212             : 
     213           2 :             GeometryData<2> data2{Size2D{coeffs}, Spacing2D{2, 2}};
     214             : 
     215           1 :             CHECK_EQ(data2.getSpacing().size(), 2);
     216           1 :             CHECK_EQ(data2.getSpacing()[0], Approx(2));
     217           1 :             CHECK_EQ(data2.getSpacing()[1], Approx(2));
     218             : 
     219           1 :             CHECK_EQ(data2.getLocationOfOrigin().size(), 2);
     220           1 :             CHECK_EQ(data2.getLocationOfOrigin()[0], Approx(5));
     221           1 :             CHECK_EQ(data2.getLocationOfOrigin()[1], Approx(5));
     222             :         }
     223             :     }
     224           5 : }
     225             : 
     226           5 : TEST_CASE("StrongTypes: Testing VolumeData")
     227             : {
     228             :     using namespace geometry;
     229             : 
     230           6 :     GIVEN("Size coefficients for 2D")
     231             :     {
     232           2 :         IndexVector_t size(2);
     233           1 :         size << 10, 10;
     234             : 
     235           2 :         THEN("Then Spacing and location of origin is calculated correctly")
     236             :         {
     237           2 :             VolumeData2D volData{Size2D{size}};
     238             : 
     239           1 :             CHECK_EQ(volData.getSpacing().size(), 2);
     240           1 :             CHECK_EQ(volData.getSpacing()[0], Approx(1));
     241           1 :             CHECK_EQ(volData.getSpacing()[1], Approx(1));
     242             : 
     243           1 :             CHECK_EQ(volData.getLocationOfOrigin().size(), 2);
     244           1 :             CHECK_EQ(volData.getLocationOfOrigin()[0], Approx(5));
     245           1 :             CHECK_EQ(volData.getLocationOfOrigin()[1], Approx(5));
     246             :         }
     247             :     }
     248             : 
     249           7 :     GIVEN("Size coefficients and Spacing for 2D")
     250             :     {
     251           4 :         IndexVector_t size(2);
     252           2 :         size << 10, 10;
     253             : 
     254           4 :         RealVector_t spacing(2);
     255           2 :         spacing << 0.5, 2;
     256             : 
     257           3 :         THEN("Then Spacing and location of origin is calculated correctly")
     258             :         {
     259           2 :             VolumeData2D volData{Size2D{size}, Spacing2D{spacing}};
     260             : 
     261           1 :             CHECK_EQ(volData.getSpacing().size(), 2);
     262           1 :             CHECK_EQ(volData.getSpacing()[0], Approx(0.5));
     263           1 :             CHECK_EQ(volData.getSpacing()[1], Approx(2));
     264             : 
     265           1 :             CHECK_EQ(volData.getLocationOfOrigin().size(), 2);
     266           1 :             CHECK_EQ(volData.getLocationOfOrigin()[0], Approx(2.5));
     267           1 :             CHECK_EQ(volData.getLocationOfOrigin()[1], Approx(10));
     268             :         }
     269           3 :         THEN("Structured bindings produce correct results")
     270             :         {
     271           2 :             auto [sp, o] = VolumeData2D{Size2D{size}, Spacing2D{spacing}};
     272             : 
     273           1 :             CHECK_EQ(sp.size(), 2);
     274           1 :             CHECK_EQ(sp[0], Approx(0.5));
     275           1 :             CHECK_EQ(sp[1], Approx(2));
     276             : 
     277           1 :             CHECK_EQ(o.size(), 2);
     278           1 :             CHECK_EQ(o[0], Approx(2.5));
     279           1 :             CHECK_EQ(o[1], Approx(10));
     280             :         }
     281             :     }
     282             : 
     283           6 :     GIVEN("Size coefficients for 3D")
     284             :     {
     285           2 :         IndexVector_t size(3);
     286           1 :         size << 10, 10, 10;
     287             : 
     288           2 :         THEN("Then Spacing and location of origin is calculated correctly")
     289             :         {
     290           2 :             VolumeData3D volData{Size3D{size}};
     291             : 
     292           1 :             CHECK_EQ(volData.getSpacing().size(), 3);
     293           1 :             CHECK_EQ(volData.getSpacing()[0], Approx(1));
     294           1 :             CHECK_EQ(volData.getSpacing()[1], Approx(1));
     295           1 :             CHECK_EQ(volData.getSpacing()[2], Approx(1));
     296             : 
     297           1 :             CHECK_EQ(volData.getLocationOfOrigin().size(), 3);
     298           1 :             CHECK_EQ(volData.getLocationOfOrigin()[0], Approx(5));
     299           1 :             CHECK_EQ(volData.getLocationOfOrigin()[1], Approx(5));
     300           1 :             CHECK_EQ(volData.getLocationOfOrigin()[2], Approx(5));
     301             :         }
     302             :     }
     303             : 
     304           6 :     GIVEN("Size coefficients and Spacing for 2D")
     305             :     {
     306           2 :         IndexVector_t size(3);
     307           1 :         size << 10, 10, 10;
     308             : 
     309           2 :         RealVector_t spacing(3);
     310           1 :         spacing << 0.5, 2, 1;
     311             : 
     312           2 :         THEN("Then Spacing and location of origin is calculated correctly")
     313             :         {
     314           2 :             VolumeData3D volData{Size3D{size}, Spacing3D{spacing}};
     315             : 
     316           1 :             CHECK_EQ(volData.getSpacing().size(), 3);
     317           1 :             CHECK_EQ(volData.getSpacing()[0], Approx(0.5));
     318           1 :             CHECK_EQ(volData.getSpacing()[1], Approx(2));
     319           1 :             CHECK_EQ(volData.getSpacing()[2], Approx(1));
     320             : 
     321           1 :             CHECK_EQ(volData.getLocationOfOrigin().size(), 3);
     322           1 :             CHECK_EQ(volData.getLocationOfOrigin()[0], Approx(2.5));
     323           1 :             CHECK_EQ(volData.getLocationOfOrigin()[1], Approx(10));
     324           1 :             CHECK_EQ(volData.getLocationOfOrigin()[2], Approx(5));
     325             :         }
     326             :     }
     327           5 : }
     328             : 
     329           6 : TEST_CASE("StrongTypes: Testing SinogramData")
     330             : {
     331             :     using namespace geometry;
     332             : 
     333           7 :     GIVEN("Size coefficients for 2D")
     334             :     {
     335           2 :         IndexVector_t size(2);
     336           1 :         size << 10, 10;
     337             : 
     338           2 :         THEN("Then Spacing and location of origin is calculated correctly")
     339             :         {
     340           2 :             SinogramData2D volData{Size2D{size}};
     341             : 
     342           1 :             CHECK_EQ(volData.getSpacing().size(), 2);
     343           1 :             CHECK_EQ(volData.getSpacing()[0], Approx(1));
     344           1 :             CHECK_EQ(volData.getSpacing()[1], Approx(1));
     345             : 
     346           1 :             CHECK_EQ(volData.getLocationOfOrigin().size(), 2);
     347           1 :             CHECK_EQ(volData.getLocationOfOrigin()[0], Approx(5));
     348           1 :             CHECK_EQ(volData.getLocationOfOrigin()[1], Approx(5));
     349             :         }
     350             :     }
     351             : 
     352           7 :     GIVEN("Size coefficients and Spacing for 2D")
     353             :     {
     354           2 :         IndexVector_t size(2);
     355           1 :         size << 10, 10;
     356             : 
     357           2 :         RealVector_t spacing(2);
     358           1 :         spacing << 0.5, 2;
     359             : 
     360           2 :         THEN("Then Spacing and location of origin is calculated correctly")
     361             :         {
     362           3 :             SinogramData2D sinoData{Size2D{size}, Spacing2D{spacing}};
     363             : 
     364           1 :             CHECK_EQ(sinoData.getSpacing().size(), 2);
     365           1 :             CHECK_EQ(sinoData.getSpacing()[0], Approx(0.5));
     366           1 :             CHECK_EQ(sinoData.getSpacing()[1], Approx(2));
     367             : 
     368           1 :             CHECK_EQ(sinoData.getLocationOfOrigin().size(), 2);
     369           1 :             CHECK_EQ(sinoData.getLocationOfOrigin()[0], Approx(2.5));
     370           1 :             CHECK_EQ(sinoData.getLocationOfOrigin()[1], Approx(10));
     371             : 
     372           5 :             CHECK_THROWS(SinogramData2D{Size2D{size}, Spacing2D{RealVector_t(3)}});
     373             :         }
     374             :     }
     375             : 
     376           7 :     GIVEN("Spacing and Origin shift in 2D")
     377             :     {
     378           2 :         RealVector_t spacing(2);
     379           1 :         spacing << 1, 1;
     380             : 
     381           2 :         RealVector_t shift(2);
     382           1 :         shift << 1, 1;
     383             : 
     384           2 :         THEN("Then Spacing and location of origin is calculated correctly")
     385             :         {
     386           3 :             auto [s, o] = SinogramData2D{Spacing2D{spacing}, OriginShift2D{shift}};
     387             : 
     388           1 :             CHECK_EQ(s.size(), 2);
     389           1 :             CHECK_EQ(s[0], Approx(1));
     390           1 :             CHECK_EQ(s[1], Approx(1));
     391             : 
     392           1 :             CHECK_EQ(o.size(), 2);
     393           1 :             CHECK_EQ(o[0], Approx(1));
     394           1 :             CHECK_EQ(o[1], Approx(1));
     395             : 
     396             :             // Test that exceptions are thrown
     397           5 :             CHECK_THROWS(SinogramData2D{Spacing2D{spacing}, RealVector_t(3)});
     398           5 :             CHECK_THROWS(SinogramData2D{RealVector_t(3), OriginShift2D{shift}});
     399           4 :             CHECK_THROWS(SinogramData2D{RealVector_t(3), RealVector_t(3)});
     400             :         }
     401             :     }
     402             : 
     403           7 :     GIVEN("Size coefficients for 3D")
     404             :     {
     405           2 :         IndexVector_t size(3);
     406           1 :         size << 10, 10, 10;
     407             : 
     408           2 :         THEN("Then Spacing and location of origin is calculated correctly")
     409             :         {
     410           2 :             SinogramData3D sinoData{Size3D{size}};
     411             : 
     412           1 :             CHECK_EQ(sinoData.getSpacing().size(), 3);
     413           1 :             CHECK_EQ(sinoData.getSpacing()[0], Approx(1));
     414           1 :             CHECK_EQ(sinoData.getSpacing()[1], Approx(1));
     415           1 :             CHECK_EQ(sinoData.getSpacing()[2], Approx(1));
     416             : 
     417           1 :             CHECK_EQ(sinoData.getLocationOfOrigin().size(), 3);
     418           1 :             CHECK_EQ(sinoData.getLocationOfOrigin()[0], Approx(5));
     419           1 :             CHECK_EQ(sinoData.getLocationOfOrigin()[1], Approx(5));
     420           1 :             CHECK_EQ(sinoData.getLocationOfOrigin()[2], Approx(5));
     421             :         }
     422             :     }
     423             : 
     424           7 :     GIVEN("Size coefficients and Spacing for 2D")
     425             :     {
     426           2 :         IndexVector_t size(3);
     427           1 :         size << 10, 10, 10;
     428             : 
     429           2 :         RealVector_t spacing(3);
     430           1 :         spacing << 0.5, 2, 1;
     431             : 
     432           2 :         THEN("Then Spacing and location of origin is calculated correctly")
     433             :         {
     434           2 :             auto [s, o] = SinogramData3D{Size3D{size}, Spacing3D{spacing}};
     435             : 
     436           1 :             CHECK_EQ(s.size(), 3);
     437           1 :             CHECK_EQ(s[0], Approx(0.5));
     438           1 :             CHECK_EQ(s[1], Approx(2));
     439           1 :             CHECK_EQ(s[2], Approx(1));
     440             : 
     441           1 :             CHECK_EQ(o.size(), 3);
     442           1 :             CHECK_EQ(o[0], Approx(2.5));
     443           1 :             CHECK_EQ(o[1], Approx(10));
     444           1 :             CHECK_EQ(o[2], Approx(5));
     445             :         }
     446             :     }
     447             : 
     448           7 :     GIVEN("Spacing and Origin shift in 3D")
     449             :     {
     450           2 :         RealVector_t spacing(3);
     451           1 :         spacing << 1, 1, 1;
     452             : 
     453           2 :         RealVector_t shift(3);
     454           1 :         shift << 1, 1, 1;
     455             : 
     456           2 :         THEN("Then Spacing and location of origin is calculated correctly")
     457             :         {
     458           3 :             SinogramData3D volData{Spacing3D{spacing}, OriginShift3D{shift}};
     459             : 
     460           1 :             CHECK_EQ(volData.getSpacing().size(), 3);
     461           1 :             CHECK_EQ(volData.getSpacing()[0], Approx(1));
     462           1 :             CHECK_EQ(volData.getSpacing()[1], Approx(1));
     463           1 :             CHECK_EQ(volData.getSpacing()[2], Approx(1));
     464             : 
     465           1 :             CHECK_EQ(volData.getLocationOfOrigin().size(), 3);
     466           1 :             CHECK_EQ(volData.getLocationOfOrigin()[0], Approx(1));
     467           1 :             CHECK_EQ(volData.getLocationOfOrigin()[1], Approx(1));
     468           1 :             CHECK_EQ(volData.getLocationOfOrigin()[2], Approx(1));
     469             : 
     470             :             // Test that exceptions are thrown
     471           5 :             CHECK_THROWS(SinogramData3D{Spacing3D{spacing}, RealVector_t(2)});
     472           5 :             CHECK_THROWS(SinogramData3D{RealVector_t(4), OriginShift3D{shift}});
     473           4 :             CHECK_THROWS(SinogramData3D{RealVector_t(1), RealVector_t(3)});
     474             :         }
     475             :     }
     476           6 : }
     477             : 
     478           2 : TEST_CASE("StrongTypes: Testing Threshold")
     479             : {
     480             :     using namespace geometry;
     481             : 
     482           3 :     GIVEN("Valid arguments for Thresholds")
     483             :     {
     484           1 :         real_t one = 1;
     485           1 :         real_t half = 1.0 / 2;
     486           1 :         real_t nine = 9;
     487             : 
     488           2 :         THEN("Overloaded relational operators are implemented correctly")
     489             :         {
     490           1 :             Threshold<real_t> tOne{one};
     491           1 :             Threshold<real_t> tHalf{half};
     492           1 :             Threshold<real_t> tNine{nine};
     493             : 
     494           1 :             CHECK_EQ(tOne, one);
     495           1 :             CHECK_GT((nine - tOne), tOne);
     496           1 :             CHECK_GE(nine, tHalf);
     497           1 :             CHECK_NE(tNine, half);
     498           1 :             CHECK_LT(tHalf, (one + tNine));
     499           1 :             CHECK_LE((tHalf + half), (one + tNine));
     500             :         }
     501             :     }
     502             : 
     503           3 :     GIVEN("Invalid arguments for Thresholds")
     504             :     {
     505           1 :         real_t zero = 0;
     506           1 :         real_t neg1 = -1;
     507             : 
     508           2 :         THEN("An exception is thrown as such Thresholds cannot be constructed")
     509             :         {
     510           2 :             CHECK_THROWS(Threshold<real_t>{zero});
     511           2 :             CHECK_THROWS(Threshold<real_t>{neg1});
     512             :         }
     513             :     }
     514           2 : }
     515             : 
     516             : TEST_SUITE_END();

Generated by: LCOV version 1.15