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

          Line data    Source code
       1             : /**
       2             :  * @file test_CircleTrajectoryGenerator.cpp
       3             :  *
       4             :  * @brief Test for CircleTrajectoryGenerator class
       5             :  *
       6             :  * @author David Frank - initial code
       7             :  * @author Nikola Dinev - fixes
       8             :  * @author Tobias Lasser - modernization, fixes
       9             :  */
      10             : 
      11             : #include "doctest/doctest.h"
      12             : 
      13             : #include "CircleTrajectoryGenerator.h"
      14             : #include "Logger.h"
      15             : #include "VolumeDescriptor.h"
      16             : #include "testHelpers.h"
      17             : 
      18             : using namespace elsa;
      19             : using namespace doctest;
      20             : 
      21           4 : TEST_CASE("CircleTrajectoryGenerator: Create a Circular Trajectory")
      22             : {
      23             :     using namespace geometry;
      24             : 
      25           4 :     const index_t s = 64;
      26             : 
      27             :     // Detector size is the volume size scalled by the square root of 2
      28           4 :     const auto expectedDetectorSize = static_cast<index_t>(s * std::sqrt(2));
      29             : 
      30           6 :     GIVEN("A 2D descriptor and 256 angles")
      31             :     {
      32           2 :         index_t numberOfAngles = 256;
      33           4 :         IndexVector_t volSize(2);
      34           2 :         volSize << s, s;
      35           4 :         VolumeDescriptor desc{volSize};
      36             : 
      37           3 :         WHEN("We create a half circular trajectory for this scenario")
      38             :         {
      39           1 :             index_t halfCircular = 180;
      40           1 :             real_t diffCenterSource{s * 100};
      41           1 :             real_t diffCenterDetector{s};
      42             : 
      43             :             auto sdesc = CircleTrajectoryGenerator::createTrajectory(
      44           2 :                 numberOfAngles, desc, halfCircular, diffCenterSource, diffCenterDetector);
      45             : 
      46             :             // Check that the detector size is correct
      47           1 :             REQUIRE_EQ(sdesc->getNumberOfCoefficientsPerDimension()[0], expectedDetectorSize);
      48             : 
      49           2 :             THEN("Every geomList in our list has the same camera center and the same projection "
      50             :                  "matrix")
      51             :             {
      52           1 :                 const real_t sourceToCenter = diffCenterSource;
      53           1 :                 const real_t centerToDetector = diffCenterDetector;
      54             : 
      55           2 :                 real_t angle = static_cast<real_t>(1.0) * static_cast<real_t>(halfCircular)
      56           1 :                                / real_t(numberOfAngles - 1);
      57         257 :                 for (index_t i = 0; i < numberOfAngles; ++i) {
      58         256 :                     real_t currAngle = static_cast<real_t>(i) * angle * pi_t / 180.0f;
      59             :                     Geometry tmpGeom(SourceToCenterOfRotation{sourceToCenter},
      60             :                                      CenterOfRotationToDetector{centerToDetector},
      61         512 :                                      Radian{currAngle}, VolumeData2D{volSize},
      62         768 :                                      SinogramData2D{sdesc->getSpacingPerDimension(),
      63        1280 :                                                     sdesc->getLocationOfOrigin()});
      64             : 
      65         256 :                     auto geom = sdesc->getGeometryAt(i);
      66         256 :                     CHECK(geom);
      67             : 
      68             :                     const auto centerNorm =
      69         256 :                         (tmpGeom.getCameraCenter() - geom->getCameraCenter()).norm();
      70             :                     const auto projMatNorm =
      71         256 :                         (tmpGeom.getProjectionMatrix() - geom->getProjectionMatrix()).norm();
      72             :                     const auto invProjMatNorm =
      73         256 :                         (tmpGeom.getInverseProjectionMatrix() - geom->getInverseProjectionMatrix())
      74         256 :                             .norm();
      75         256 :                     REQUIRE_UNARY(checkApproxEq(centerNorm, 0));
      76         256 :                     REQUIRE_UNARY(checkApproxEq(projMatNorm, 0, 0.0000001));
      77         256 :                     REQUIRE_UNARY(checkApproxEq(invProjMatNorm, 0, 0.0000001));
      78             :                 }
      79             :             }
      80             :         }
      81             : 
      82           3 :         WHEN("We create a full circular trajectory for this scenario")
      83             :         {
      84           1 :             index_t fullyCircular = 359;
      85           1 :             real_t diffCenterSource{s * 100};
      86           1 :             real_t diffCenterDetector{s};
      87             : 
      88             :             auto sdesc = CircleTrajectoryGenerator::createTrajectory(
      89           2 :                 numberOfAngles, desc, fullyCircular, diffCenterSource, diffCenterDetector);
      90             : 
      91             :             // Check that the detector size is correct
      92           1 :             REQUIRE_EQ(sdesc->getNumberOfCoefficientsPerDimension()[0], expectedDetectorSize);
      93             : 
      94           2 :             THEN("Every geomList in our list has the same camera center and the same projection "
      95             :                  "matrix")
      96             :             {
      97           1 :                 const real_t sourceToCenter = diffCenterSource;
      98           1 :                 const real_t centerToDetector = diffCenterDetector;
      99             : 
     100           2 :                 real_t angle = static_cast<real_t>(1.0) * static_cast<real_t>(fullyCircular)
     101           1 :                                / static_cast<real_t>(numberOfAngles - 1);
     102         257 :                 for (index_t i = 0; i < numberOfAngles; ++i) {
     103         256 :                     real_t currAngle = static_cast<real_t>(i) * angle * pi_t / 180.0f;
     104             : 
     105             :                     Geometry tmpGeom(SourceToCenterOfRotation{sourceToCenter},
     106             :                                      CenterOfRotationToDetector{centerToDetector},
     107         512 :                                      Radian{currAngle}, VolumeData2D{volSize},
     108         768 :                                      SinogramData2D{sdesc->getSpacingPerDimension(),
     109        1280 :                                                     sdesc->getLocationOfOrigin()});
     110             : 
     111         256 :                     auto geom = sdesc->getGeometryAt(i);
     112         256 :                     CHECK(geom);
     113             : 
     114             :                     const auto centerNorm =
     115         256 :                         (tmpGeom.getCameraCenter() - geom->getCameraCenter()).norm();
     116             :                     const auto projMatNorm =
     117         256 :                         (tmpGeom.getProjectionMatrix() - geom->getProjectionMatrix()).norm();
     118             :                     const auto invProjMatNorm =
     119         256 :                         (tmpGeom.getInverseProjectionMatrix() - geom->getInverseProjectionMatrix())
     120         256 :                             .norm();
     121         256 :                     REQUIRE_UNARY(checkApproxEq(centerNorm, 0));
     122         256 :                     REQUIRE_UNARY(checkApproxEq(projMatNorm, 0, 0.0000001));
     123         256 :                     REQUIRE_UNARY(checkApproxEq(invProjMatNorm, 0, 0.0000001));
     124             :                 }
     125             :             }
     126             :         }
     127             :     }
     128             : 
     129           6 :     GIVEN("A 3D descriptor and 256 angles")
     130             :     {
     131           2 :         index_t numberOfAngles = 256;
     132           4 :         IndexVector_t volSize(3);
     133           2 :         volSize << s, s, s;
     134           4 :         VolumeDescriptor desc{volSize};
     135             : 
     136           3 :         WHEN("We create a half circular trajectory for this scenario")
     137             :         {
     138           1 :             index_t halfCircular = 180;
     139           1 :             real_t diffCenterSource{s * 100};
     140           1 :             real_t diffCenterDetector{s};
     141             : 
     142             :             auto sdesc = CircleTrajectoryGenerator::createTrajectory(
     143           2 :                 numberOfAngles, desc, halfCircular, diffCenterSource, diffCenterDetector);
     144             : 
     145             :             // Check that the detector size is correct
     146           1 :             REQUIRE_EQ(sdesc->getNumberOfCoefficientsPerDimension()[0], expectedDetectorSize);
     147           1 :             REQUIRE_EQ(sdesc->getNumberOfCoefficientsPerDimension()[1], expectedDetectorSize);
     148             : 
     149           2 :             THEN("Every geomList in our list has the same camera center and the same projection "
     150             :                  "matrix")
     151             :             {
     152           1 :                 const real_t sourceToCenter = diffCenterSource;
     153           1 :                 const real_t centerToDetector = diffCenterDetector;
     154             : 
     155           2 :                 real_t angleInc = 1.0f * static_cast<real_t>(halfCircular)
     156           1 :                                   / static_cast<real_t>(numberOfAngles - 1);
     157         257 :                 for (index_t i = 0; i < numberOfAngles; ++i) {
     158         256 :                     real_t angle = static_cast<real_t>(i) * angleInc * pi_t / 180.0f;
     159             : 
     160             :                     Geometry tmpGeom(SourceToCenterOfRotation{sourceToCenter},
     161             :                                      CenterOfRotationToDetector{centerToDetector},
     162         512 :                                      VolumeData3D{volSize},
     163         768 :                                      SinogramData3D{sdesc->getSpacingPerDimension(),
     164         512 :                                                     sdesc->getLocationOfOrigin()},
     165        1024 :                                      RotationAngles3D{Gamma{angle}});
     166             : 
     167         256 :                     auto geom = sdesc->getGeometryAt(i);
     168         256 :                     CHECK(geom);
     169             : 
     170             :                     const auto centerNorm =
     171         256 :                         (tmpGeom.getCameraCenter() - geom->getCameraCenter()).norm();
     172             :                     const auto projMatNorm =
     173         256 :                         (tmpGeom.getProjectionMatrix() - geom->getProjectionMatrix()).norm();
     174             :                     const auto invProjMatNorm =
     175         256 :                         (tmpGeom.getInverseProjectionMatrix() - geom->getInverseProjectionMatrix())
     176         256 :                             .norm();
     177         256 :                     REQUIRE(checkApproxEq(centerNorm, 0));
     178         256 :                     REQUIRE(checkApproxEq(projMatNorm, 0, 0.0000001));
     179         256 :                     REQUIRE(checkApproxEq(invProjMatNorm, 0, 0.0000001));
     180             :                 }
     181             :             }
     182             :         }
     183           3 :         WHEN("We create a full circular trajectory for this scenario")
     184             :         {
     185           1 :             const index_t fullyCircular = 359;
     186           1 :             real_t diffCenterSource{s * 100};
     187           1 :             real_t diffCenterDetector{s};
     188             : 
     189             :             auto sdesc = CircleTrajectoryGenerator::createTrajectory(
     190           2 :                 numberOfAngles, desc, fullyCircular, diffCenterSource, diffCenterDetector);
     191             : 
     192             :             // Check that the detector size is correct
     193           1 :             REQUIRE_EQ(sdesc->getNumberOfCoefficientsPerDimension()[0], expectedDetectorSize);
     194           1 :             REQUIRE_EQ(sdesc->getNumberOfCoefficientsPerDimension()[1], expectedDetectorSize);
     195             : 
     196           2 :             THEN("Every geomList in our list has the same camera center and the same projection "
     197             :                  "matrix")
     198             :             {
     199           1 :                 const auto sourceToCenter = diffCenterSource;
     200           1 :                 const auto centerToDetector = diffCenterDetector;
     201             : 
     202           1 :                 real_t angleInc = 1.0f * static_cast<real_t>(fullyCircular)
     203           1 :                                   / static_cast<real_t>(numberOfAngles - 1);
     204         257 :                 for (index_t i = 0; i < numberOfAngles; ++i) {
     205         256 :                     real_t angle = static_cast<real_t>(i) * angleInc * pi_t / 180.0f;
     206             : 
     207             :                     Geometry tmpGeom(SourceToCenterOfRotation{sourceToCenter},
     208             :                                      CenterOfRotationToDetector{centerToDetector},
     209         512 :                                      VolumeData3D{volSize},
     210         768 :                                      SinogramData3D{sdesc->getSpacingPerDimension(),
     211         512 :                                                     sdesc->getLocationOfOrigin()},
     212        1024 :                                      RotationAngles3D{Gamma{angle}});
     213             : 
     214         256 :                     auto geom = sdesc->getGeometryAt(i);
     215         256 :                     CHECK(geom);
     216             : 
     217             :                     const auto centerNorm =
     218         256 :                         (tmpGeom.getCameraCenter() - geom->getCameraCenter()).norm();
     219             :                     const auto projMatNorm =
     220         256 :                         (tmpGeom.getProjectionMatrix() - geom->getProjectionMatrix()).norm();
     221             :                     const auto invProjMatNorm =
     222         256 :                         (tmpGeom.getInverseProjectionMatrix() - geom->getInverseProjectionMatrix())
     223         256 :                             .norm();
     224         256 :                     REQUIRE_UNARY(checkApproxEq(centerNorm, 0));
     225         256 :                     REQUIRE_UNARY(checkApproxEq(projMatNorm, 0, 0.0000001));
     226         256 :                     REQUIRE_UNARY(checkApproxEq(invProjMatNorm, 0, 0.0000001));
     227             :                 }
     228             :             }
     229             :         }
     230             :     }
     231           4 : }

Generated by: LCOV version 1.15