LCOV - code coverage report
Current view: top level - elsa/generators/tests - test_CircleTrajectoryGenerator.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 171 171 100.0 %
Date: 2022-08-25 03:05:39 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             : TEST_CASE("CircleTrajectoryGenerator: Create a Circular Trajectory")
      22           4 : {
      23           4 :     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           4 :     GIVEN("A 2D descriptor and 256 angles")
      31           4 :     {
      32           2 :         index_t numberOfAngles = 256;
      33           2 :         IndexVector_t volSize(2);
      34           2 :         volSize << s, s;
      35           2 :         VolumeDescriptor desc{volSize};
      36             : 
      37           2 :         WHEN("We create a half circular trajectory for this scenario")
      38           2 :         {
      39           1 :             index_t halfCircular = 180;
      40           1 :             real_t diffCenterSource{s * 100};
      41           1 :             real_t diffCenterDetector{s};
      42             : 
      43           1 :             auto sdesc = CircleTrajectoryGenerator::createTrajectory(
      44           1 :                 numberOfAngles, desc, halfCircular, diffCenterSource, diffCenterDetector);
      45             : 
      46             :             // Check that the detector size is correct
      47           1 :             REQUIRE_EQ(sdesc->getNumberOfCoefficientsPerDimension()[0], expectedDetectorSize);
      48             : 
      49           1 :             THEN("Every geomList in our list has the same camera center and the same projection "
      50           1 :                  "matrix")
      51           1 :             {
      52           1 :                 const real_t sourceToCenter = diffCenterSource;
      53           1 :                 const real_t centerToDetector = diffCenterDetector;
      54             : 
      55           1 :                 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         256 :                     Geometry tmpGeom(SourceToCenterOfRotation{sourceToCenter},
      60         256 :                                      CenterOfRotationToDetector{centerToDetector},
      61         256 :                                      Radian{currAngle}, VolumeData2D{volSize},
      62         256 :                                      SinogramData2D{sdesc->getSpacingPerDimension(),
      63         256 :                                                     sdesc->getLocationOfOrigin()});
      64             : 
      65         256 :                     auto geom = sdesc->getGeometryAt(i);
      66         256 :                     CHECK(geom);
      67             : 
      68         256 :                     const auto centerNorm =
      69         256 :                         (tmpGeom.getCameraCenter() - geom->getCameraCenter()).norm();
      70         256 :                     const auto projMatNorm =
      71         256 :                         (tmpGeom.getProjectionMatrix() - geom->getProjectionMatrix()).norm();
      72         256 :                     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         256 :                 }
      79           1 :             }
      80           1 :         }
      81             : 
      82           2 :         WHEN("We create a full circular trajectory for this scenario")
      83           2 :         {
      84           1 :             index_t fullyCircular = 359;
      85           1 :             real_t diffCenterSource{s * 100};
      86           1 :             real_t diffCenterDetector{s};
      87             : 
      88           1 :             auto sdesc = CircleTrajectoryGenerator::createTrajectory(
      89           1 :                 numberOfAngles, desc, fullyCircular, diffCenterSource, diffCenterDetector);
      90             : 
      91             :             // Check that the detector size is correct
      92           1 :             REQUIRE_EQ(sdesc->getNumberOfCoefficientsPerDimension()[0], expectedDetectorSize);
      93             : 
      94           1 :             THEN("Every geomList in our list has the same camera center and the same projection "
      95           1 :                  "matrix")
      96           1 :             {
      97           1 :                 const real_t sourceToCenter = diffCenterSource;
      98           1 :                 const real_t centerToDetector = diffCenterDetector;
      99             : 
     100           1 :                 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         256 :                     Geometry tmpGeom(SourceToCenterOfRotation{sourceToCenter},
     106         256 :                                      CenterOfRotationToDetector{centerToDetector},
     107         256 :                                      Radian{currAngle}, VolumeData2D{volSize},
     108         256 :                                      SinogramData2D{sdesc->getSpacingPerDimension(),
     109         256 :                                                     sdesc->getLocationOfOrigin()});
     110             : 
     111         256 :                     auto geom = sdesc->getGeometryAt(i);
     112         256 :                     CHECK(geom);
     113             : 
     114         256 :                     const auto centerNorm =
     115         256 :                         (tmpGeom.getCameraCenter() - geom->getCameraCenter()).norm();
     116         256 :                     const auto projMatNorm =
     117         256 :                         (tmpGeom.getProjectionMatrix() - geom->getProjectionMatrix()).norm();
     118         256 :                     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         256 :                 }
     125           1 :             }
     126           1 :         }
     127           2 :     }
     128             : 
     129           4 :     GIVEN("A 3D descriptor and 256 angles")
     130           4 :     {
     131           2 :         index_t numberOfAngles = 256;
     132           2 :         IndexVector_t volSize(3);
     133           2 :         volSize << s, s, s;
     134           2 :         VolumeDescriptor desc{volSize};
     135             : 
     136           2 :         WHEN("We create a half circular trajectory for this scenario")
     137           2 :         {
     138           1 :             index_t halfCircular = 180;
     139           1 :             real_t diffCenterSource{s * 100};
     140           1 :             real_t diffCenterDetector{s};
     141             : 
     142           1 :             auto sdesc = CircleTrajectoryGenerator::createTrajectory(
     143           1 :                 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           1 :             THEN("Every geomList in our list has the same camera center and the same projection "
     150           1 :                  "matrix")
     151           1 :             {
     152           1 :                 const real_t sourceToCenter = diffCenterSource;
     153           1 :                 const real_t centerToDetector = diffCenterDetector;
     154             : 
     155           1 :                 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         256 :                     Geometry tmpGeom(SourceToCenterOfRotation{sourceToCenter},
     161         256 :                                      CenterOfRotationToDetector{centerToDetector},
     162         256 :                                      VolumeData3D{volSize},
     163         256 :                                      SinogramData3D{sdesc->getSpacingPerDimension(),
     164         256 :                                                     sdesc->getLocationOfOrigin()},
     165         256 :                                      RotationAngles3D{Gamma{angle}});
     166             : 
     167         256 :                     auto geom = sdesc->getGeometryAt(i);
     168         256 :                     CHECK(geom);
     169             : 
     170         256 :                     const auto centerNorm =
     171         256 :                         (tmpGeom.getCameraCenter() - geom->getCameraCenter()).norm();
     172         256 :                     const auto projMatNorm =
     173         256 :                         (tmpGeom.getProjectionMatrix() - geom->getProjectionMatrix()).norm();
     174         256 :                     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         256 :                 }
     181           1 :             }
     182           1 :         }
     183           2 :         WHEN("We create a full circular trajectory for this scenario")
     184           2 :         {
     185           1 :             const index_t fullyCircular = 359;
     186           1 :             real_t diffCenterSource{s * 100};
     187           1 :             real_t diffCenterDetector{s};
     188             : 
     189           1 :             auto sdesc = CircleTrajectoryGenerator::createTrajectory(
     190           1 :                 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           1 :             THEN("Every geomList in our list has the same camera center and the same projection "
     197           1 :                  "matrix")
     198           1 :             {
     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         256 :                     Geometry tmpGeom(SourceToCenterOfRotation{sourceToCenter},
     208         256 :                                      CenterOfRotationToDetector{centerToDetector},
     209         256 :                                      VolumeData3D{volSize},
     210         256 :                                      SinogramData3D{sdesc->getSpacingPerDimension(),
     211         256 :                                                     sdesc->getLocationOfOrigin()},
     212         256 :                                      RotationAngles3D{Gamma{angle}});
     213             : 
     214         256 :                     auto geom = sdesc->getGeometryAt(i);
     215         256 :                     CHECK(geom);
     216             : 
     217         256 :                     const auto centerNorm =
     218         256 :                         (tmpGeom.getCameraCenter() - geom->getCameraCenter()).norm();
     219         256 :                     const auto projMatNorm =
     220         256 :                         (tmpGeom.getProjectionMatrix() - geom->getProjectionMatrix()).norm();
     221         256 :                     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         256 :                 }
     228           1 :             }
     229           1 :         }
     230           2 :     }
     231           4 : }

Generated by: LCOV version 1.14