LCOV - code coverage report
Current view: top level - projectors - Blobs.h (source / functions) Hit Total Coverage
Test: test_coverage.info.cleaned Lines: 0 33 0.0 %
Date: 2022-08-04 03:43:28 Functions: 0 12 0.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include "Error.h"
       4             : #include "elsaDefines.h"
       5             : #include "Bessel.h"
       6             : 
       7             : namespace elsa
       8             : {
       9             :     template <class T>
      10             :     struct SelfType {
      11             :         using type = T;
      12             :     };
      13             : 
      14             :     template <class T>
      15             :     using SelfType_t = typename SelfType<T>::type;
      16             : 
      17             :     namespace blobs
      18             :     {
      19             :         // The devinition given by Lewitt (1992):
      20             :         // \f$
      21             :         // b_{m, alpha, a}(r) = \frac{I_m(\alpha * \sqrt{1 - (r/a)^2)}{I_m(\alpha)} * (\sqrt{1 -
      22             :         // (r/a)^2})^m \f$ for any \f$ 0 <= r <= a \f$.
      23             :         template <typename data_t>
      24           0 :         constexpr data_t blob_evaluate(data_t r, SelfType_t<data_t> a, SelfType_t<data_t> alpha,
      25             :                                        int m) noexcept
      26             :         {
      27           0 :             const auto w = static_cast<data_t>(1) - std::pow(r / a, static_cast<data_t>(2));
      28           0 :             if (w >= 0) {
      29           0 :                 const data_t Im1 = math::bessi(m, alpha);
      30           0 :                 const data_t arg = std::sqrt(w);
      31           0 :                 const data_t Im2 = math::bessi(m, alpha * arg);
      32             : 
      33           0 :                 return Im2 / Im1 * std::pow(arg, m);
      34             :             }
      35           0 :             return 0;
      36             :         }
      37             : 
      38             :         /// @brief Compute line integral of blob through a straight line
      39             :         /// The exact formulations are quite easily derived using the fact, that the line
      40             :         /// integral for a single blob is given by:
      41             :         ///
      42             :         /// \f$
      43             :         /// \frac{a}{I_m(\alpha)} \sqrt{\frac{2 \pi}{\alpha}} \left(\sqrt{1 -
      44             :         /// \left(\frac{s}{a}\right)^2}\right)^{m + 0.5} I_{m + 0.5}\left(\alpha \sqrt{1 -
      45             :         /// \left(\frac{s}{a}\right)^2}\right)
      46             :         /// \f$
      47             :         ///
      48             :         /// Then for a given order substitute I_{m + 0.5}(x) with the elementary function
      49             :         /// representations, as they can be found in Abramowitz and Stegun's Handbook of
      50             :         /// mathematical functions (1972):
      51             :         /// \f$ I_{0.5}(x) = \sqrt{\frac{2}{\pi x}} \sinh(x)\$f
      52             :         /// \f$ I_{1.5}(x) = \sqrt{\frac{2}{\pi x}} \left( \cosh(x) \frac{\sinh(x)}{x} \right) \$f
      53             :         /// \f$ I_{2.5}(x) = \sqrt{\frac{2}{\pi x}} \left(\left(\frac{3}{x^2} +
      54             :         /// \frac{1}{x}\right)\sinh(x) - \frac{3}{x^2} \cosh(x)\right)\$f
      55             :         ///
      56             :         /// Which will result in the below formulations. In theory using the recurrent relations,
      57             :         /// this could be extended to further orders, but is deemed unnecessary for now.
      58             :         ///
      59             :         /// TODO: What about alpha = 0? Check if you find anything in the literature for that.
      60             :         ///
      61             :         /// @param distance distance of blob center to straight line, in literature often referred
      62             :         /// to as `r`
      63             :         /// @param radius radius of blob, often referred to as `a`
      64             :         /// @param alpha smoothness factor of blob, expected to be larger than 0
      65             :         /// @param order order of Bessel function, often referred to as `m`
      66             :         ///
      67             :         /// Ref:
      68             :         /// Distance-Driven Projection and Backprojection for Spherically Symmetric Basis Functions
      69             :         /// in CT - Levakhina
      70             :         /// Spherically symmetric volume elements as basis functions for image reconstructions in
      71             :         /// computed laminography - P. Trampert
      72             :         /// Semi-Discrete Iteration Methods in X-Ray Tomography - Jonas Vogelgesang
      73             :         template <typename data_t>
      74           0 :         constexpr data_t blob_projected(data_t s, SelfType_t<data_t> a, SelfType_t<data_t> alpha,
      75             :                                         int m)
      76             :         {
      77             :             // expect alpha > 0
      78             :             using namespace elsa::math;
      79             : 
      80           0 :             const data_t sda = s / a;
      81           0 :             const data_t sdas = std::pow(sda, 2);
      82           0 :             const data_t w = 1.0 - sdas;
      83             : 
      84           0 :             if (w > 1.0e-10) {
      85           0 :                 const auto arg = alpha * std::sqrt(w);
      86           0 :                 if (m == 0) {
      87           0 :                     return (2.0 * a / alpha) * std::sinh(arg) / math::bessi0(alpha);
      88           0 :                 } else if (m == 1) {
      89           0 :                     return (2.0 * a / alpha) * std::sqrt(w)
      90           0 :                            * (std::cosh(arg) - std::sinh(arg) / arg) / math::bessi1(alpha);
      91             : 
      92           0 :                 } else if (m == 2) {
      93           0 :                     return (2.0 * a / alpha) * w
      94           0 :                            * ((3.0 / (arg * arg) + 1.0) * std::sinh(arg) - (3.0 / arg) * cosh(arg))
      95           0 :                            / bessi2(alpha);
      96             :                 } else {
      97           0 :                     throw Error("m out of range in blob_projected()");
      98             :                 }
      99             :             }
     100           0 :             return 0.0;
     101             :         }
     102             : 
     103             :         template <typename data_t>
     104           0 :         constexpr data_t blob_projected(data_t s)
     105             :         {
     106           0 :             return blob_projected(s, 2.f, 10.83f, 2);
     107             :         }
     108             :     } // namespace blobs
     109             : 
     110             :     template <typename data_t>
     111             :     class Blob
     112             :     {
     113             :     public:
     114             :         constexpr Blob(data_t radius, SelfType_t<data_t> alpha, int order);
     115             : 
     116             :         constexpr data_t operator()(data_t s);
     117             : 
     118             :         constexpr data_t radius() const;
     119             : 
     120             :         constexpr data_t alpha() const;
     121             : 
     122             :         constexpr int order() const;
     123             : 
     124             :     private:
     125             :         data_t radius_;
     126             :         data_t alpha_;
     127             :         int order_;
     128             :     };
     129             : 
     130             :     template <typename data_t>
     131             :     class ProjectedBlob
     132             :     {
     133             :     public:
     134           0 :         constexpr ProjectedBlob(data_t radius, SelfType_t<data_t> alpha, int order)
     135           0 :             : radius_(radius), alpha_(alpha), order_(order)
     136             :         {
     137           0 :         }
     138             : 
     139           0 :         constexpr data_t operator()(data_t s)
     140             :         {
     141           0 :             return blobs::blob_projected(s, radius_, alpha_, order_);
     142             :         }
     143             : 
     144           0 :         constexpr data_t radius() const { return radius_; }
     145             : 
     146             :         constexpr data_t alpha() const { return alpha_; }
     147             : 
     148             :         constexpr int order() const { return order_; }
     149             : 
     150             :     private:
     151             :         data_t radius_;
     152             :         data_t alpha_;
     153             :         int order_;
     154             :     };
     155             : 
     156             : } // namespace elsa

Generated by: LCOV version 1.14