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 move constructor 44 : Dictionary(Dictionary<data_t>&& other) = default; 45 : 46 : /// default move assignment 47 : Dictionary& operator=(Dictionary<data_t>&& other) = default; 48 : 49 : /// default destructor 50 0 : ~Dictionary() override = default; 51 : 52 : /** 53 : * @brief Update a single atom of the dictionary with a new atom 54 : * 55 : * @param[in] j Index of the atom that should be updated 56 : * @param[in] atom DataContainer containing the new atom 57 : * @throw InvalidArgumentError if atom has the wrong size or index is out of bounds or atom 58 : * is the 0-vector 59 : */ 60 : void updateAtom(index_t j, const DataContainer<data_t>& atom); 61 : 62 : /** 63 : * @brief Get an atom of the dictionary by index 64 : * 65 : * @param[in] j Index of the atom that should returned 66 : * @returns The atom in a DataContainer 67 : * @throw InvalidArgumentError if index is out of bounds 68 : */ 69 : const DataContainer<data_t> getAtom(index_t j) const; 70 : 71 : /** 72 : * @brief Returns the number of atoms in the dictionary 73 : * 74 : * @returns The number of atoms 75 : */ 76 : index_t getNumberOfAtoms() const; 77 : 78 : /** 79 : * @brief Get a new dictionary restricted to a given support 80 : * 81 : * @param[in] support List of indices for the atoms that should be in the new dictionary 82 : * @returns A dictionary containing only the atoms that are defined by support 83 : * @throw InvalidArgumentError if support contains and index that is out of bounds 84 : */ 85 : Dictionary<data_t> getSupportedDictionary(IndexVector_t support) const; 86 : 87 : protected: 88 : /// Copy constructor for internal usage 89 : Dictionary(const Dictionary<data_t>&) = default; 90 : 91 : /// apply the dictionary operation 92 : void applyImpl(const DataContainer<data_t>& x, DataContainer<data_t>& Ax) const override; 93 : 94 : /// apply the adjoint of the dictionary operation 95 : void applyAdjointImpl(const DataContainer<data_t>& y, 96 : DataContainer<data_t>& Aty) const override; 97 : 98 : /// implement the polymorphic clone operation 99 : Dictionary<data_t>* cloneImpl() const override; 100 : 101 : /// implement the polymorphic comparison operation 102 : bool isEqual(const LinearOperator<data_t>& other) const override; 103 : 104 : private: 105 : /// the actual dictionary 106 : DataContainer<data_t> _dictionary; 107 : /// lift the base class variable for the range (signal) descriptor 108 : using LinearOperator<data_t>::_rangeDescriptor; 109 : /// the number of atoms in the dictionary 110 : index_t _nAtoms; 111 : 112 : static const IdenticalBlocksDescriptor& 113 : getIdenticalBlocksDescriptor(const DataContainer<data_t>& data); 114 : static DataContainer<data_t> generateInitialData(const DataDescriptor& signalDescriptor, 115 : index_t nAtoms); 116 : }; 117 : 118 : } // namespace elsa