Line data Source code
1 : #pragma once 2 : 3 : #include "LinearOperator.h" 4 : #include "IdenticalBlocksDescriptor.h" 5 : #include "Timer.h" 6 : 7 : #include <limits> 8 : #include <memory> 9 : 10 : namespace elsa 11 : { 12 : /** 13 : * @brief Operator representing a dictionary operation. 14 : * 15 : * @author Jonas Buerger - initial code 16 : * 17 : * @tparam data_t data type for the domain and range of the operator, defaulting to real_t 18 : * 19 : * This class represents a linear operator D that given a representation vector x 20 : * generates a signal y by multplication \f$ y = D*x \f$ 21 : */ 22 : template <typename data_t = real_t> 23 : class Dictionary : public LinearOperator<data_t> 24 : { 25 : public: 26 : /** 27 : * @brief Constructor for an empty dictionary. 28 : * 29 : * @param[in] signalDescriptor DataDescriptor describing the domain of the signals that 30 : * should be produced @param[in] nAtoms The number of atoms that should be in the dictionary 31 : */ 32 : Dictionary(const DataDescriptor& signalDescriptor, index_t nAtoms); 33 : 34 : /** 35 : * @brief Constructor for an initialized dictionary. 36 : * 37 : * @param[in] dictionary DataContainer containing the entries of the dictionary 38 : * @throw InvalidArgumentError if dictionary doesn't have a IdenticalBlocksDescriptor or at 39 : * least one of the atoms is the 0-vector 40 : */ 41 : explicit Dictionary(const DataContainer<data_t>& dictionary); 42 : 43 : /// default copy constructor 44 3 : Dictionary(const Dictionary<data_t>& other) = default; 45 : 46 : /// default copy assignment 47 : Dictionary& operator=(const Dictionary<data_t>& other) = default; 48 : 49 : /// default move constructor 50 : Dictionary(Dictionary<data_t>&& other) noexcept = default; 51 : 52 : /// default move assignment 53 : Dictionary& operator=(Dictionary<data_t>&& other) noexcept = default; 54 : 55 : /// default destructor 56 47 : ~Dictionary() override = default; 57 : 58 : /** 59 : * @brief Update a single atom of the dictionary with a new atom 60 : * 61 : * @param[in] j Index of the atom that should be updated 62 : * @param[in] atom DataContainer containing the new atom 63 : * @throw InvalidArgumentError if atom has the wrong size or index is out of bounds or atom 64 : * is the 0-vector 65 : */ 66 : void updateAtom(index_t j, const DataContainer<data_t>& atom); 67 : 68 : /** 69 : * @brief Get an atom of the dictionary by index 70 : * 71 : * @param[in] j Index of the atom that should returned 72 : * @returns The atom in a DataContainer 73 : * @throw InvalidArgumentError if index is out of bounds 74 : */ 75 : const DataContainer<data_t> getAtom(index_t j) const; 76 : 77 : /** 78 : * @brief Returns the number of atoms in the dictionary 79 : * 80 : * @returns The number of atoms 81 : */ 82 : index_t getNumberOfAtoms() const; 83 : 84 : /** 85 : * @brief Get a new dictionary restricted to a given support 86 : * 87 : * @param[in] support List of indices for the atoms that should be in the new dictionary 88 : * @returns A dictionary containing only the atoms that are defined by support 89 : * @throw InvalidArgumentError if support contains and index that is out of bounds 90 : */ 91 : Dictionary<data_t> getSupportedDictionary(IndexVector_t support) const; 92 : 93 0 : DataContainer<data_t> getDictionary() const { return _dictionary; } 94 : 95 : protected: 96 : /// apply the dictionary operation 97 : void applyImpl(const DataContainer<data_t>& x, DataContainer<data_t>& Ax) const override; 98 : 99 : /// apply the adjoint of the dictionary operation 100 : void applyAdjointImpl(const DataContainer<data_t>& y, 101 : DataContainer<data_t>& Aty) const override; 102 : 103 : /// implement the polymorphic clone operation 104 : Dictionary<data_t>* cloneImpl() const override; 105 : 106 : /// implement the polymorphic comparison operation 107 : bool isEqual(const LinearOperator<data_t>& other) const override; 108 : 109 : private: 110 : /// the actual dictionary 111 : DataContainer<data_t> _dictionary; 112 : /// lift the base class variable for the range (signal) descriptor 113 : using LinearOperator<data_t>::_rangeDescriptor; 114 : /// the number of atoms in the dictionary 115 : index_t _nAtoms; 116 : 117 : static const IdenticalBlocksDescriptor& 118 : getIdenticalBlocksDescriptor(const DataContainer<data_t>& data); 119 : static DataContainer<data_t> generateInitialData(const DataDescriptor& signalDescriptor, 120 : index_t nAtoms); 121 : }; 122 : 123 : } // namespace elsa