LCOV - code coverage report
Current view: top level - elsa/generators - PhantomGenerator.cpp (source / functions) Hit Total Coverage
Test: coverage-all.lcov Lines: 108 114 94.7 %
Date: 2022-08-25 03:05:39 Functions: 10 10 100.0 %

          Line data    Source code
       1             : #include "PhantomGenerator.h"
       2             : #include "EllipseGenerator.h"
       3             : #include "Logger.h"
       4             : #include "VolumeDescriptor.h"
       5             : #include "CartesianIndices.h"
       6             : 
       7             : #include <cmath>
       8             : #include <stdexcept>
       9             : 
      10             : namespace elsa
      11             : {
      12             :     template <typename data_t>
      13             :     DataContainer<data_t> PhantomGenerator<data_t>::createCirclePhantom(IndexVector_t volumesize,
      14             :                                                                         data_t radius)
      15          32 :     {
      16          32 :         VolumeDescriptor dd(volumesize);
      17          32 :         DataContainer<data_t> dc(dd);
      18          32 :         dc = 0;
      19             : 
      20          32 :         const Vector_t<data_t> sizef = volumesize.template cast<data_t>();
      21          32 :         const auto center = (sizef.array() / 2).matrix();
      22             : 
      23       69632 :         for (auto pos : CartesianIndices(volumesize)) {
      24       69632 :             const Vector_t<data_t> p = pos.template cast<data_t>();
      25       69632 :             if ((p - center).norm() <= radius) {
      26       12038 :                 dc(pos) = 1;
      27       12038 :             }
      28       69632 :         }
      29             : 
      30          32 :         return dc;
      31          32 :     }
      32             : 
      33             :     template <typename data_t>
      34             :     DataContainer<data_t> PhantomGenerator<data_t>::createRectanglePhantom(IndexVector_t volumesize,
      35             :                                                                            IndexVector_t lower,
      36             :                                                                            IndexVector_t upper)
      37           8 :     {
      38           8 :         VolumeDescriptor dd(volumesize);
      39           8 :         DataContainer<data_t> dc(dd);
      40           8 :         dc = 0;
      41             : 
      42        9856 :         for (auto pos : CartesianIndices(lower, upper)) {
      43        9856 :             dc(pos) = 1;
      44        9856 :         }
      45             : 
      46           8 :         return dc;
      47           8 :     }
      48             : 
      49             :     template <typename data_t>
      50             :     DataContainer<data_t> PhantomGenerator<data_t>::createModifiedSheppLogan(IndexVector_t sizes)
      51          23 :     {
      52             :         // sanity check
      53          23 :         if (sizes.size() < 2 || sizes.size() > 3)
      54           0 :             throw InvalidArgumentError(
      55           0 :                 "PhantomGenerator::createModifiedSheppLogan: only 2d or 3d supported");
      56          23 :         if (sizes.size() == 2 && sizes[0] != sizes[1])
      57           0 :             throw InvalidArgumentError(
      58           0 :                 "PhantomGenerator::createModifiedSheppLogan: 2d size has to be square");
      59          23 :         if (sizes.size() == 3 && (sizes[0] != sizes[1] || sizes[0] != sizes[2]))
      60           0 :             throw InvalidArgumentError(
      61           0 :                 "PhantomGenerator::createModifiedSheppLogan: 3d size has to be cubed");
      62             : 
      63          23 :         Logger::get("PhantomGenerator")
      64          23 :             ->info("creating modified Shepp Logan phantom of size {}^{}", sizes[0], sizes.size());
      65             : 
      66          23 :         VolumeDescriptor dd(sizes);
      67          23 :         DataContainer<data_t> dc(dd);
      68          23 :         dc = 0;
      69             : 
      70          23 :         if (sizes.size() == 2) {
      71          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(dc, 1.0,
      72          16 :                                                           {scaleShift(dd, 0), scaleShift(dd, 0)},
      73          16 :                                                           {scale(dd, 0.69f), scale(dd, 0.92f)}, 0);
      74          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(
      75          16 :                 dc, -0.8f, {scaleShift(dd, 0), scaleShift(dd, -0.0184f)},
      76          16 :                 {scale(dd, 0.6624f), scale(dd, 0.8740f)}, 0);
      77          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(
      78          16 :                 dc, -0.2f, {scaleShift(dd, 0.22f), scaleShift(dd, 0)},
      79          16 :                 {scale(dd, 0.11f), scale(dd, 0.31f)}, -18);
      80          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(
      81          16 :                 dc, -0.2f, {scaleShift(dd, -0.22f), scaleShift(dd, 0)},
      82          16 :                 {scale(dd, 0.16f), scale(dd, 0.41f)}, 18);
      83          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(
      84          16 :                 dc, 0.1f, {scaleShift(dd, 0), scaleShift(dd, 0.35f)},
      85          16 :                 {scale(dd, 0.21f), scale(dd, 0.25)}, 0);
      86          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(
      87          16 :                 dc, 0.1f, {scaleShift(dd, 0), scaleShift(dd, 0.1f)},
      88          16 :                 {scale(dd, 0.046f), scale(dd, 0.046f)}, 0);
      89          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(
      90          16 :                 dc, 0.1f, {scaleShift(dd, 0), scaleShift(dd, -0.1f)},
      91          16 :                 {scale(dd, 0.046f), scale(dd, 0.046f)}, 0);
      92          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(
      93          16 :                 dc, 0.1f, {scaleShift(dd, -0.08f), scaleShift(dd, -0.605f)},
      94          16 :                 {scale(dd, 0.046f), scale(dd, 0.023f)}, 0);
      95          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(
      96          16 :                 dc, 0.1f, {scaleShift(dd, 0), scaleShift(dd, -0.606f)},
      97          16 :                 {scale(dd, 0.023f), scale(dd, 0.023f)}, 0);
      98          16 :             EllipseGenerator<data_t>::drawFilledEllipse2d(
      99          16 :                 dc, 0.1f, {scaleShift(dd, 0.06f), scaleShift(dd, -0.605f)},
     100          16 :                 {scale(dd, 0.023f), scale(dd, 0.046f)}, 0);
     101          16 :         }
     102             : 
     103          23 :         if (sizes.size() == 3) {
     104           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     105           7 :                 dc, 1.0, {scaleShift(dd, 0), scaleShift(dd, 0), scaleShift(dd, 0)},
     106           7 :                 {scale(dd, 0.69f), scale(dd, 0.92f), scale(dd, 0.81f)}, 0, 0, 0);
     107           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     108           7 :                 dc, -0.8f, {scaleShift(dd, 0), scaleShift(dd, -0.0184f), scaleShift(dd, 0)},
     109           7 :                 {scale(dd, 0.6624f), scale(dd, 0.874f), scale(dd, 0.78f)}, 0, 0, 0);
     110           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     111           7 :                 dc, -0.2f, {scaleShift(dd, 0.22f), scaleShift(dd, 0), scaleShift(dd, 0)},
     112           7 :                 {scale(dd, 0.11f), scale(dd, 0.31f), scale(dd, 0.22f)}, -18, 0, 10);
     113           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     114           7 :                 dc, -0.2f, {scaleShift(dd, -0.22f), scaleShift(dd, 0), scaleShift(dd, 0)},
     115           7 :                 {scale(dd, 0.16f), scale(dd, 0.41f), scale(dd, 0.28f)}, 18, 0, 10);
     116           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     117           7 :                 dc, 0.1f, {scaleShift(dd, 0), scaleShift(dd, 0.35f), scaleShift(dd, -0.15f)},
     118           7 :                 {scale(dd, 0.21f), scale(dd, 0.25f), scale(dd, 0.41f)}, 0, 0, 0);
     119           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     120           7 :                 dc, 0.1f, {scaleShift(dd, 0), scaleShift(dd, 0.1f), scaleShift(dd, 0.25f)},
     121           7 :                 {scale(dd, 0.046f), scale(dd, 0.046f), scale(dd, 0.05f)}, 0, 0, 0);
     122           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     123           7 :                 dc, 0.1f, {scaleShift(dd, 0), scaleShift(dd, -0.1f), scaleShift(dd, 0.25f)},
     124           7 :                 {scale(dd, 0.046f), scale(dd, 0.046f), scale(dd, 0.05f)}, 0, 0, 0);
     125           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     126           7 :                 dc, 0.1f, {scaleShift(dd, -0.08f), scaleShift(dd, -0.605f), scaleShift(dd, 0)},
     127           7 :                 {scale(dd, 0.046f), scale(dd, 0.023f), scale(dd, 0.05f)}, 0, 0, 0);
     128           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     129           7 :                 dc, 0.1f, {scaleShift(dd, 0), scaleShift(dd, -0.606f), scaleShift(dd, 0)},
     130           7 :                 {scale(dd, 0.023f), scale(dd, 0.023f), scale(dd, 0.02f)}, 0, 0, 0);
     131           7 :             EllipseGenerator<data_t>::drawFilledEllipsoid3d(
     132           7 :                 dc, 0.1f, {scaleShift(dd, 0.06f), scaleShift(dd, -0.605f), scaleShift(dd, 0)},
     133           7 :                 {scale(dd, 0.023f), scale(dd, 0.046f), scale(dd, 0.02f)}, 0, 0, 0);
     134           7 :         }
     135             : 
     136          23 :         return dc;
     137          23 :     }
     138             : 
     139             :     template <typename data_t>
     140             :     index_t PhantomGenerator<data_t>::scale(const DataDescriptor& dd, data_t value)
     141         530 :     {
     142         530 :         return std::lround(
     143         530 :             value * static_cast<data_t>(dd.getNumberOfCoefficientsPerDimension()[0] - 1) / 2.0f);
     144         530 :     }
     145             : 
     146             :     template <typename data_t>
     147             :     index_t PhantomGenerator<data_t>::scaleShift(const DataDescriptor& dd, data_t value)
     148         530 :     {
     149         530 :         return std::lround(value
     150         530 :                            * static_cast<data_t>(dd.getNumberOfCoefficientsPerDimension()[0] - 1)
     151         530 :                            / 2.0f)
     152         530 :                + (dd.getNumberOfCoefficientsPerDimension()[0] / 2);
     153         530 :     }
     154             : 
     155             :     // ------------------------------------------
     156             :     // explicit template instantiation
     157             :     template class PhantomGenerator<float>;
     158             :     template class PhantomGenerator<double>;
     159             : 
     160             : } // namespace elsa

Generated by: LCOV version 1.14