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