Line data Source code
1 : #pragma once 2 : 3 : #include "DataContainer.h" 4 : #include "Functional.h" 5 : #include "LinearOperator.h" 6 : 7 : #include <memory> 8 : #include <optional> 9 : 10 : namespace elsa 11 : { 12 : /** 13 : * @brief Class representing a negative log-likelihood functional for transmission tomography. 14 : * 15 : * @author Matthias Wieczorek - initial code 16 : * @author Maximilian Hornung - modularization 17 : * @author Tobias Lasser - rewrite 18 : * 19 : * @tparam data_t data type for the domain of the residual of the functional, defaulting to 20 : * real_t 21 : * 22 : * The TransmissionLogLikelihood functional evaluates as \f$ \sum_{i=1}^n (b_i \exp(-x_i) + r_i) 23 : * - y_i\log(b_i \exp(-x_i) + r_i) \f$, with \f$ b=(b_i) \f$ denoting the mean number of photons 24 : * per detector (blank scan), \f$ y=(y_i) \f$ denoting the measurements, \f$ r=(r_i) \f$ 25 : * denoting the mean number of background events, and \f$ x=(x_i) \f$. 26 : * 27 : * Typically, \f$ x \f$ is wrapped in a LinearResidual without a data vector, i.e. \f$ x \mapsto 28 : * Ax \f$. 29 : */ 30 : template <typename data_t = real_t> 31 : class TransmissionLogLikelihood : public Functional<data_t> 32 : { 33 : public: 34 : /** 35 : * @brief Constructor for transmission log-likelihood, using y and b, and a residual as 36 : * input 37 : * 38 : * @param[in] A linear operator to apply to x 39 : * @param[in] y the measurement data vector 40 : * @param[in] b the blank scan data vector 41 : */ 42 : TransmissionLogLikelihood(const LinearOperator<data_t>& A, const DataContainer<data_t>& y, 43 : const DataContainer<data_t>& b); 44 : 45 : /** 46 : * @brief Constructor for transmission log-likelihood, using y, b, and r, and a residual as 47 : * input 48 : * 49 : * @param[in] A linear operator to apply to x 50 : * @param[in] y the measurement data vector 51 : * @param[in] b the blank scan data vector 52 : * @param[in] r the background event data vector 53 : */ 54 : TransmissionLogLikelihood(const LinearOperator<data_t>& A, const DataContainer<data_t>& y, 55 : const DataContainer<data_t>& b, const DataContainer<data_t>& r); 56 : 57 : /// make copy constructor deletion explicit 58 : TransmissionLogLikelihood(const TransmissionLogLikelihood<data_t>&) = delete; 59 : 60 : /// default destructor 61 14 : ~TransmissionLogLikelihood() override = default; 62 : 63 : bool isDifferentiable() const override; 64 : 65 : protected: 66 : /// the evaluation of the transmission log-likelihood 67 : data_t evaluateImpl(const DataContainer<data_t>& Rx) const override; 68 : 69 : /// the computation of the gradient (in place) 70 : void getGradientImpl(const DataContainer<data_t>& Rx, 71 : DataContainer<data_t>& out) const override; 72 : 73 : /// the computation of the Hessian 74 : LinearOperator<data_t> getHessianImpl(const DataContainer<data_t>& Rx) const override; 75 : 76 : /// implement the polymorphic clone operation 77 : TransmissionLogLikelihood<data_t>* cloneImpl() const override; 78 : 79 : /// implement the polymorphic comparison operation 80 : bool isEqual(const Functional<data_t>& other) const override; 81 : 82 : private: 83 : /// optional linear operator to apply to x 84 : std::unique_ptr<LinearOperator<data_t>> A_{}; 85 : 86 : /// the measurement data vector y 87 : DataContainer<data_t> y_; 88 : 89 : /// the blank scan data vector b 90 : DataContainer<data_t> b_; 91 : 92 : /// the background event data vector r 93 : std::optional<DataContainer<data_t>> r_{}; 94 : }; 95 : } // namespace elsa