elsa operators

Identity

template<typename data_t = real_t>
class elsa::Identity : public elsa::LinearOperator<real_t>

Operator representing the identity operation.

This class represents a linear operator A that is the identity, i.e. Ax = x.

Author

Matthias Wieczorek - initial code

Author

Tobias Lasser - modularization, rewrite

Template Parameters
  • data_t: data type for the domain and range of the operator, defaulting to real_t

Public Functions

Identity(const DataDescriptor &descriptor)

Constructor for the identity operator, specifying the domain (= range).

Parameters
  • [in] descriptor: DataDescriptor describing the domain and range of the operator

~Identity() override = default

default destructor

Protected Functions

Identity(const Identity<data_t>&) = default

default copy constructor, hidden from non-derived classes to prevent potential slicing

void applyImpl(const DataContainer<data_t> &x, DataContainer<data_t> &Ax) const override

apply the identity operator A to x, i.e. Ax = x

Parameters

void applyAdjointImpl(const DataContainer<data_t> &y, DataContainer<data_t> &Aty) const override

apply the adjoint of the identity operator A to y, i.e. A^ty = y

Parameters

Identity<data_t> *cloneImpl() const override

implement the polymorphic clone operation

bool isEqual(const LinearOperator<data_t> &other) const override

implement the polymorphic comparison operation

Scaling

template<typename data_t = real_t>
class elsa::Scaling : public elsa::LinearOperator<real_t>

Operator representing a scaling operation.

This class represents a linear operator A that scales the input, either by a scalar or by a diagonal scaling matrix.

Author

Matthias Wieczorek - initial code

Author

Maximilian Hornung - minor fixes

Author

Tobias Lasser - modularization, rewrite

Template Parameters
  • data_t: data type for the domain and range of the operator, defaulting to real_t

Public Functions

Scaling(const DataDescriptor &descriptor, data_t scaleFactor)

Constructor for a scalar, isotropic scaling operator.

Parameters
  • [in] descriptor: DataDescriptor describing the domain and the range of the operator

  • [in] scaleFactor: the scalar factor to scale with

Scaling(const DataContainer<data_t> &scaleFactors)

Constructor for a diagonal, anisotropic scaling operator.

Parameters
  • [in] scaleFactors: a DataContainer containing the scaling factor to be put on the diagonal

Scaling(const Scaling<data_t>&) = delete

make copy constructor deletion explicit

~Scaling() override = default

default destructor

bool isIsotropic() const

is the scaling isotropic

data_t getScaleFactor() const

returns the scale factor (throws if scaling is not isotropic)

const DataContainer<data_t> &getScaleFactors() const

returns the scale factors (throws if scaling is isotropic)

Protected Functions

void applyImpl(const DataContainer<data_t> &x, DataContainer<data_t> &Ax) const override

apply the scaling operation

void applyAdjointImpl(const DataContainer<data_t> &y, DataContainer<data_t> &Aty) const override

apply the adjoint of the scaling operation

Scaling<data_t> *cloneImpl() const override

implement the polymorphic clone operation

bool isEqual(const LinearOperator<data_t> &other) const override

implement the polymorphic comparison operation

Private Members

bool _isIsotropic

flag if the scaling is isotropic

data_t _scaleFactor

isotropic scaling factor

std::unique_ptr<DataContainer<data_t>> _scaleFactors = {}

anisotropic scaling factors

FiniteDifferences

template<typename data_t = real_t>
class elsa::FiniteDifferences : public elsa::LinearOperator<real_t>

Operator to compute finite differences.

This class represents a linear operator D that computes finite differences, using the central, forward, or backward differences.

Author

Matthias Wieczorek - initial code

Author

Maximilian Hornung - rewrite and performance optimization

Author

Tobias Lasser - modernization

Template Parameters
  • data_t: data type for the domain and range of the operator, defaulting to real_t

Public Types

enum DiffType

supported types of finite differences

Values:

enumerator FORWARD
enumerator BACKWARD
enumerator CENTRAL

Public Functions

FiniteDifferences(const DataDescriptor &domainDescriptor, DiffType type = DiffType::FORWARD)

Constructor for FiniteDifferences over all dimensions.

This implementation uses zero padding such that it’s equal to the following matrix formulation (in 1D)

  • Dforward = full(spdiags([-e e], 0:1, n, n));

  • Dbackward = full(spdiags([-e e], -1:0, n, n));

  • Dcentral = spdiags(0.5*[-e e], [-1,1], n, n);

Parameters
  • [in] domainDescriptor: Descriptor for domain

  • [in] type: denoting the type of finite differences

Note: the descriptor for the range is automatically generated from the domain.

FiniteDifferences(const DataDescriptor &domainDescriptor, const BooleanVector_t &activeDims, DiffType type = DiffType::FORWARD)

Constructor for FiniteDifferences over selected dimensions.

This implementation uses zero padding such that it’s equal to the following matrix formulation (in 1D)

  • Dforward = full(spdiags([-e e], 0:1, n, n));

  • Dbackward = full(spdiags([-e e], -1:0, n, n));

  • Dcentral = spdiags(0.5*[-e e], [-1,1], n, n);

Parameters
  • [in] domainDescriptor: Descriptor for domain

  • [in] activeDims: Boolean vector defining which dimensions are active or not

  • [in] type: denoting the type of finite differences

Note: the descriptor for the range is automatically generated from the domain.

~FiniteDifferences() override = default

default destructor

Protected Functions

FiniteDifferences(const FiniteDifferences<data_t>&) = default

default copy constructor, hidden from non-derived classes to prevent potential slicing

void applyImpl(const DataContainer<data_t> &x, DataContainer<data_t> &Ax) const override

apply the finite differences operator

void applyAdjointImpl(const DataContainer<data_t> &y, DataContainer<data_t> &Aty) const override

apply the adjoint of the finite differences operator

FiniteDifferences<data_t> *cloneImpl() const override

implement the polymorphic clone operation

bool isEqual(const LinearOperator<data_t> &other) const override

implement the polymorphic comparison operation

Private Functions

void precomputeHelpers()

precompute some helper variables to optimize speed

template<typename FDtype>
void applyHelper(const DataContainer<data_t> &x, DataContainer<data_t> &Ax, FDtype type) const

precomputed helper for active dim counter

the actual finite differences computations (with mode as template parameter for performance)

template<typename FDtype>
void applyAdjointHelper(const DataContainer<data_t> &y, DataContainer<data_t> &Aty, FDtype type) const

the actual finite differences computations (with mode as template parameter for performance)

Private Members

DiffType _type

type of the finite differences to be computed

BooleanVector_t _activeDims

boolean vector for active dimensions when computing finite differences

IndexVector_t _coordDelta

precomputed helper for coordinate diffs

IndexVector_t _dimCounter

precomputed helper for coordinate deltas

BlockLinearOperator

template<typename data_t = real_t>
class elsa::BlockLinearOperator : public elsa::LinearOperator<real_t>

Class representing a block operator matrix.

A block linear operator represents a block operator matrix

$ B $ consisting of multiple matrices $ A_i, i=1,\ldots,n $ stacked:
  • rowwise

    \[ B = \begin{bmatrix} A_{1}\\ A_{2}\\ \vdots\\ A_{n} \end{bmatrix} \]

  • columnwise

    \[ B = \begin{bmatrix} A_{1} & A_{2} & \hdots & A_{n} \end{bmatrix} \]

Author

Matthias Wieczorek - initial code

Author

David Frank - rewrite

Author

Nikola Dinev - automatic descriptor generation, rewrite

Template Parameters
  • data_t: data type for the domain and range of the operator, defaulting to real_t

Public Types

enum BlockType

possible arrangements of the blocks

Values:

enumerator ROW
enumerator COL
using OperatorList = typename std::vector<std::unique_ptr<LinearOperator<data_t>>>

convenience typedef for a vector of pointers to LinearOperator

Public Functions

BlockLinearOperator(const OperatorList &ops, BlockType blockType)

Construct a BlockLinearOperator of the given BlockType from the list of operators.

The domain and range descriptors of the

BlockLinearOperator are generated automatically based on the descriptors of the operators in the list. For the block descriptor, a PartitionDescriptor is preferentially generated, if not possible a RandomBlocksDescriptor is generated instead. For the non-block descriptor the best common descriptor is chosen (see DataDescriptor::bestCommon()).
Parameters
  • [in] ops: the list of operators

  • [in] blockType: the fashion in which the operators are to be stacked

Exceptions
  • InvalidArgumentError: if ops is empty

BlockLinearOperator(const DataDescriptor &domainDescriptor, const DataDescriptor &rangeDescriptor, const OperatorList &ops, BlockType blockType)

Construct a BlockLinearOperator of the given BlockType from the list of operators, and additionally manually set the domain and range descriptors of the operator.

Parameters
  • [in] domainDescriptor: descriptor of the domain of the operator

  • [in] rangeDescriptor: descriptor of the range of the operator

  • [in] ops: the list of operators

  • [in] blockType: the fashion in which the operators are to be stacked

Exceptions
  • InvalidArgumentError: if the passed in descriptors are not suitable for the BlockLinearOperator

~BlockLinearOperator() override = default

default destructor

const LinearOperator<data_t> &getIthOperator(index_t i) const

return the operator corresponding to the i-th block of the matrix

index_t numberOfOps() const

return the total number of blocks

Protected Functions

BlockLinearOperator(const BlockLinearOperator &other)

protected copy constructor; used for cloning

void applyImpl(const DataContainer<data_t> &x, DataContainer<data_t> &Ax) const override

apply the block linear operator

void applyAdjointImpl(const DataContainer<data_t> &y, DataContainer<data_t> &Aty) const override

apply the adjoint of the block linear operator

BlockLinearOperator<data_t> *cloneImpl() const override

implement the polymorphic clone operation

bool isEqual(const LinearOperator<data_t> &other) const override

implement the polymorphic comparison operation

Private Members

OperatorList _operatorList

list specifying the individual operators corresponding to each block

BlockType _blockType

determines in which fashion the operators are concatenated - rowwise or columnwise

Private Static Functions

std::unique_ptr<DataDescriptor> determineDomainDescriptor(const OperatorList &operatorList, BlockType blockType)

returns the best fitting domain descriptor based on the operator list and block type

std::unique_ptr<DataDescriptor> determineRangeDescriptor(const OperatorList &operatorList, BlockType blockType)

returns the best fitting range descriptor based on the operator list and block type

std::unique_ptr<BlockDescriptor> bestBlockDescriptor(const std::vector<const DataDescriptor*>&)

finds the best fitting block descriptor, such that each block is described by the corresponding descriptor in the list

Dictionary

template<typename data_t = real_t>
class elsa::Dictionary : public elsa::LinearOperator<real_t>

Operator representing a dictionary operation.

This class represents a linear operator D that given a representation vector x generates a signal y by multplication

$ y = D*x $
Author

Jonas Buerger - initial code

Template Parameters
  • data_t: data type for the domain and range of the operator, defaulting to real_t

Public Functions

Dictionary(const DataDescriptor &signalDescriptor, index_t nAtoms)

Constructor for an empty dictionary.

Parameters
  • [in] signalDescriptor: DataDescriptor describing the domain of the signals that should be produced

  • [in] nAtoms: The number of atoms that should be in the dictionary

Dictionary(const DataContainer<data_t> &dictionary)

Constructor for an initialized dictionary.

Parameters
  • [in] dictionary: DataContainer containing the entries of the dictionary

Exceptions
  • InvalidArgumentError: if dictionary doesn’t have a IdenticalBlocksDescriptor or at least one of the atoms is the 0-vector

Dictionary(const Dictionary<data_t> &other) = default

default copy constructor

Dictionary &operator=(const Dictionary<data_t> &other) = default

default copy assignment

Dictionary(Dictionary<data_t> &&other) noexcept = default

default move constructor

Dictionary &operator=(Dictionary<data_t> &&other) noexcept = default

default move assignment

~Dictionary() override = default

default destructor

void updateAtom(index_t j, const DataContainer<data_t> &atom)

Update a single atom of the dictionary with a new atom.

Parameters
  • [in] j: Index of the atom that should be updated

  • [in] atom: DataContainer containing the new atom

Exceptions
  • InvalidArgumentError: if atom has the wrong size or index is out of bounds or atom is the 0-vector

const DataContainer<data_t> getAtom(index_t j) const

Get an atom of the dictionary by index.

Return

The atom in a DataContainer

Parameters
  • [in] j: Index of the atom that should returned

Exceptions
  • InvalidArgumentError: if index is out of bounds

index_t getNumberOfAtoms() const

Returns the number of atoms in the dictionary.

Return

The number of atoms

Dictionary<data_t> getSupportedDictionary(IndexVector_t support) const

Get a new dictionary restricted to a given support.

Return

A dictionary containing only the atoms that are defined by support

Parameters
  • [in] support: List of indices for the atoms that should be in the new dictionary

Exceptions
  • InvalidArgumentError: if support contains and index that is out of bounds

Protected Functions

void applyImpl(const DataContainer<data_t> &x, DataContainer<data_t> &Ax) const override

apply the dictionary operation

void applyAdjointImpl(const DataContainer<data_t> &y, DataContainer<data_t> &Aty) const override

apply the adjoint of the dictionary operation

Dictionary<data_t> *cloneImpl() const override

implement the polymorphic clone operation

bool isEqual(const LinearOperator<data_t> &other) const override

implement the polymorphic comparison operation

Private Members

DataContainer<data_t> _dictionary

the actual dictionary

index_t _nAtoms

the number of atoms in the dictionary

ShearletTransform

template<typename ret_t = real_t, typename data_t = real_t>
class elsa::ShearletTransform : public elsa::LinearOperator<real_t>

Class representing a (regular) Cone-Adapted Discrete Shearlet Transform.

ShearletTransform represents a band-limited (compact support in Fourier domain) representation system. It oversamples a 2D signal of (W, H) to (W, H, L). Most of the computation is taken for the spectra, which is stored after the first run. It only handles signals with one channel, e.g. grayscale images. Increasing the number of scales will increase precision.

Author

Andi Braimllari - initial code

Template Parameters
  • data_t: data type for the domain and range of the problem, defaulting to real_t

Note that this class only handles the 2D scenario.

References: https://www.math.uh.edu/~dlabate/SHBookIntro.pdf https://www.math.uh.edu/~dlabate/Athens.pdf https://arxiv.org/pdf/1202.1773.pdf

Public Functions

ShearletTransform(IndexVector_t spatialDimensions)

Constructor for a (regular) cone-adapted discrete shearlet transform.

Parameters
  • [in] spatialDimensions: the width and height of the input image

ShearletTransform(index_t width, index_t height)

Constructor for a (regular) cone-adapted discrete shearlet transform.

Parameters
  • [in] width: the width of the input image

  • [in] height: the height of the input image

ShearletTransform(index_t width, index_t height, index_t numOfScales)

Constructor for a (regular) cone-adapted discrete shearlet transform.

Parameters
  • [in] width: the width of the input image

  • [in] height: the height of the input image

  • [in] numOfScales: the number of scales

ShearletTransform(index_t width, index_t height, index_t numOfScales, std::optional<DataContainer<data_t>> spectra)

Constructor for a (regular) cone-adapted discrete shearlet transform.

Parameters
  • [in] width: the width of the input image

  • [in] height: the height of the input image

  • [in] numOfScales: the number of scales

  • [in] spectra: the spectra

~ShearletTransform() override = default

default destructor

void computeSpectra() const

method for computing the spectra, should only be called once as subsequent calls will generate the same spectra

bool isSpectraComputed() const

method indicating if the spectra has already been computed

auto getSpectra() const -> DataContainer<data_t>

return the spectra

auto getWidth() const -> index_t

return the width

auto getHeight() const -> index_t

return the height

auto getNumOfLayers() const -> index_t

return the oversampling factor

Protected Functions

ShearletTransform<ret_t, data_t> *cloneImpl() const override

implement the polymorphic clone operation

bool isEqual(const LinearOperator<ret_t> &other) const override

implement the polymorphic comparison operation

Private Functions

auto getShapeFractions() const -> shape_fractions

helper function to calculate input data fractions.

Private Members

std::optional<DataContainer<data_t>> _spectra = std::nullopt

variable to store the spectra

index_t _width

variables to store the spatial extents

index_t _numOfScales

variable to store the number of scales

index_t _numOfLayers

variable to store the oversampling factor

struct shape_fractions

Fractions of the input data shape, needed internally in many functions.