Line data Source code
1 : #pragma once 2 : 3 : #include "elsaDefines.h" 4 : #include "DetectorDescriptor.h" 5 : #include "PlanarDetectorDescriptor.h" 6 : #include "VolumeDescriptor.h" 7 : #include "DataContainer.h" 8 : #include "SiddonsMethod.h" 9 : #include "JosephsMethod.h" 10 : 11 : namespace elsa 12 : { 13 : /** 14 : * @brief Class representing a subset sampling method. 15 : * 16 : * @author Michael Loipführer - initial code 17 : * 18 : * @tparam DetectorDescriptor_t 19 : * @tparam data_t data type for the domain and range of the problem, defaulting to real_t 20 : * 21 : */ 22 : template <typename DetectorDescriptor_t, typename data_t = real_t> 23 : class SubsetSampler : public Cloneable<SubsetSampler<DetectorDescriptor_t, data_t>> 24 : { 25 : public: 26 : /// enum to differentiate between different subset sampling strategies 27 : enum class SamplingStrategy { 28 : ROUND_ROBIN, /// (default) divides data points into subsets via simple round-robin 29 : ROTATIONAL_CLUSTERING, /// equally spaces the data points based on their rotation 30 : }; 31 : 32 : /** 33 : * @brief Constructor for SubsetSampler 34 : * 35 : * @param[in] volumeDescriptor of the problem 36 : * @param[in] detectorDescriptor describes the geometry and trajectory of the measurements 37 : * @param[in] nSubsets is number of subsets that should be generated 38 : * @param[in] samplingStrategy the strategy with which to sample the subsets 39 : */ 40 : SubsetSampler(const VolumeDescriptor& volumeDescriptor, 41 : const DetectorDescriptor_t& detectorDescriptor, index_t nSubsets, 42 : SamplingStrategy samplingStrategy = SamplingStrategy::ROUND_ROBIN); 43 : 44 : /// default destructor 45 18 : ~SubsetSampler() = default; 46 : 47 : /** 48 : * @brief return a new DataContainer with a BlockDescriptor containing the reordered 49 : * sinogram data in each block corresponding to a subset 50 : * 51 : * @param[in] sinogram the original sinogram 52 : */ 53 : DataContainer<data_t> getPartitionedData(const DataContainer<data_t>& sinogram); 54 : 55 : /** 56 : * @brief return 57 : * 58 : * @tparam projector_t the type of projector to instantiate 59 : */ 60 : template <typename Projector_t> 61 : std::unique_ptr<LinearOperator<data_t>> getProjector() 62 6 : { 63 6 : return std::make_unique<Projector_t>(_volumeDescriptor, _fullDetectorDescriptor); 64 6 : } 65 : 66 : /** 67 : * @brief return a list of projectors that correspond to each subset 68 : * 69 : * @tparam projector_t the type of projector to instantiate 70 : */ 71 : template <typename Projector_t> 72 : std::vector<std::unique_ptr<LinearOperator<data_t>>> getSubsetProjectors() 73 6 : { 74 6 : std::vector<std::unique_ptr<LinearOperator<data_t>>> projectors; 75 : 76 24 : for (const auto& detectorDescriptor : _detectorDescriptors) { 77 24 : projectors.emplace_back( 78 24 : std::make_unique<Projector_t>(_volumeDescriptor, detectorDescriptor)); 79 24 : } 80 : 81 6 : return projectors; 82 6 : } 83 : 84 : /** 85 : * @brief Helper method implementing a general round robin splitting of a list of indices. 86 : * 87 : * @return mapping of data indices to subsets 88 : */ 89 : static std::vector<std::vector<index_t>> 90 : splitRoundRobin(const std::vector<index_t>& indices, index_t nSubsets); 91 : 92 : /** 93 : * @brief Helper method implementing rotational distance based sampling. Iteratively loop 94 : * through all data points and assign the closest on based on the angle of rotation to the 95 : * next subset. 96 : * 97 : * @return mapping of data indices to subsets 98 : */ 99 : static std::vector<std::vector<index_t>> 100 : splitRotationalClustering(const DetectorDescriptor_t& detectorDescriptor, 101 : index_t nSubsets); 102 : 103 : protected: 104 : /// default copy constructor for cloning 105 : SubsetSampler<DetectorDescriptor_t, data_t>( 106 : const SubsetSampler<DetectorDescriptor_t, data_t>& other); 107 : /// implement the polymorphic comparison operation 108 : bool isEqual(const SubsetSampler<DetectorDescriptor_t, data_t>& other) const override; 109 : 110 : /// implement the polymorphic clone operation 111 : SubsetSampler<DetectorDescriptor_t, data_t>* cloneImpl() const override; 112 : 113 : private: 114 : /// mapping of data point indices to respective subsets 115 : std::vector<std::vector<index_t>> _indexMapping; 116 : 117 : /// volume descriptor of the problem 118 : VolumeDescriptor _volumeDescriptor; 119 : 120 : /// the full detector descriptor of the problem 121 : DetectorDescriptor_t _fullDetectorDescriptor; 122 : 123 : /// list of detector descriptors corresponding to each block 124 : std::vector<DetectorDescriptor_t> _detectorDescriptors; 125 : 126 : /// number of subsets 127 : index_t _nSubsets; 128 : }; 129 : } // namespace elsa