CTL  0.6.1
Computed Tomography Library
Classes | Public Types | Public Member Functions | Protected Member Functions | Private Attributes | Friends | List of all members
CTL::ProjectorExtension Class Reference

The ProjectorExtension class provides the interface to extend projectors with additional functionality using the concept of decoration. More...

#include <projectorextension.h>

Inheritance diagram for CTL::ProjectorExtension:
Inheritance graph
[legend]
Collaboration diagram for CTL::ProjectorExtension:
Collaboration graph
[legend]

Classes

class  MetaProjector
 

Public Types

enum  { Type = 100 }
 
- Public Types inherited from CTL::AbstractProjector
enum  { Type = 0 }
 
- Public Types inherited from CTL::SerializationInterface
enum  { Type = -1, UserType = 65536 }
 

Public Member Functions

int type () const override
 
void configure (const AcquisitionSetup &setup) override
 
ProjectionData project (const VolumeData &volume) override
 
 ProjectorExtension (AbstractProjector *projector=nullptr)
 
 ProjectorExtension (std::unique_ptr< AbstractProjector > projector)
 
ProjectionData projectComposite (const CompositeVolume &volume) override
 Provides the functionality to forward project CompositeVolume data. More...
 
ProjectionData projectSparse (const SparseVoxelVolume &volume) override
 Provides the functionality to forward project SparseVoxelVolume data. More...
 
bool isLinear () const override
 Returns true if the projection operation is linear. More...
 
virtual void use (AbstractProjector *other)
 
void use (std::unique_ptr< AbstractProjector > other)
 
void fromVariant (const QVariant &variant) override
 Sets the contents of the object based on the QVariant variant. More...
 
QVariant toVariant () const override
 Stores the contents of this instance in a QVariant. More...
 
AbstractProjectorrelease ()
 
void reset ()
 
- Public Member Functions inherited from CTL::AbstractProjector
 AbstractProjector (const AbstractProjector &)=delete
 
 AbstractProjector (AbstractProjector &&)=default
 
AbstractProjectoroperator= (const AbstractProjector &)=delete
 
AbstractProjectoroperator= (AbstractProjector &&)=default
 
 ~AbstractProjector () override=default
 
ProjectionData configureAndProject (const AcquisitionSetup &setup, const VolumeData &volume)
 Performs a forward projection with a precedent configuration of the projector. More...
 
ProjectionData configureAndProject (const AcquisitionSetup &setup, const CompositeVolume &volume)
 Performs a forward projection with a precedent configuration of the projector. More...
 
ProjectionData configureAndProject (const AcquisitionSetup &setup, const SparseVoxelVolume &volume)
 Performs a forward projection with a precedent configuration of the projector. More...
 
virtual QVariant parameter () const
 Returns the parameters of this instance as QVariant. More...
 
virtual void setParameter (const QVariant &parameter)
 Sets the parameters of this instance based on the passed QVariant parameter. Parameters need to follow the naming convention as described in parameter(). More...
 
virtual ProjectorNotifiernotifier ()
 Returns a pointer to the notifier of the projector. More...
 
void connectNotifierToMessageHandler (bool includeProgress=false)
 Connects the notifier to the CTL's MessageHandler. More...
 
- Public Member Functions inherited from CTL::SerializationInterface
virtual ~SerializationInterface ()=default
 

Protected Member Functions

virtual ProjectionData extendedProject (const MetaProjector &nestedProjector)
 
- Protected Member Functions inherited from CTL::SerializationInterface
 SerializationInterface ()=default
 
 SerializationInterface (const SerializationInterface &)=default
 
 SerializationInterface (SerializationInterface &&)=default
 
SerializationInterfaceoperator= (const SerializationInterface &)=default
 
SerializationInterfaceoperator= (SerializationInterface &&)=default
 

Private Attributes

std::unique_ptr< AbstractProjector_projector
 The nested projector object.
 

Friends

template<class >
struct SerializationHelper::RegisterWithSerializationHelper
 

Related Functions

(Note that these are not member functions.)

std::unique_ptr< ProjectorExtensionType > makeExtension (AbstractProjector *projector=nullptr)
 
std::unique_ptr< ProjectorExtensionType > makeExtension (std::unique_ptr< AbstractProjector > projector)
 

Detailed Description

The ProjectorExtension class provides the interface to extend projectors with additional functionality using the concept of decoration.

The ProjectorExtension class allowes to extend the functionalty of any projector, i.e. of any class derived from AbstractProjector. The idea is that an extension uses another projector as a nested projector that is called. Before and after that call any modification can be made. The nested projector itself may also be an extension. Note that the nested projector is owned by the extension meaning that when the extension gets destroyed the nested projector will be destroyed too.

There are several syntactical ways to extend another projector/extension. The following snippets show exemplarily the PoissonNoiseExtension extending the OCL::RayCasterProjector. Each pattern supports raw pointers as well as std::unique_ptrs.

  1. By using the contructor
    // with `new` and raw pointers
    auto extRaw = new PoissonNoiseExtension(new OCL::RayCasterProjector);
    // with make functions and `std::unique_ptr`s (safer in terms of accidental memory leaks)
    auto extUPtr = makeExtension<PoissonNoiseExtension>(makeProjector<OCL::RayCasterProjector>());
  2. By using the ProjectorExtension::use method
    auto ext = makeExtension<PoissonNoiseExtension>();
    ext->use(makeProjector<OCL::RayCasterProjector>());
  3. By using pipe operators (pay attention to the order)
    auto ext1 = makeProjector<OCL::RayCasterProjector>() | makeExtension<PoissonNoiseExtension>();
    // or in separate steps
    std::unique_ptr<AbstractProjector> ext2;
    ext2 = makeProjector<OCL::RayCasterProjector>();
    ext2 |= makeExtension<PoissonNoiseExtension>();
    // also mixtures of unique and raw pointers are possible
    auto ext3 = makeProjector<OCL::RayCasterProjector>() | new PoissonNoiseExtension;
  4. (3b) By using the pipe function for two raw pointers (because two raw pointers cannot be combined via '|' or '|=')
    AbstractProjector* ext;
    ext = new OCL::RayCasterProjector;
    pipe(ext, new PoissonNoiseExtension);
    // multiple concatenation is also possible similar to the pipe operators
    pipe(pipe(ext, new PoissonNoiseExtension), new ProjectorExtension);
    // Note: '... | ProjectorExtension' does not change the projector's behavior

In order to build and manage a larger pipeline of ProjectorExtensions, see the helper class ProjectionPipeline. A pre-defined (suggested) pipeline is provided by the StandardPipeline class.

When implementing a custom extension, your class must be a subclass of ProjectorExtension. There are two possiblilties to implement such an extension:

  1. Override extendedProject, or
  2. Override all three project methods, i.e. project, projectComposite, and projectSparse.

Doing 1. and 2. at the same time is not sensible as the implementation of extendedProject will have no effect.

You would like to override the AbstractProjector::configure method as well in order to initialize your Extension with informations from the AcquisitionSetup. When doing so, you should also call ProjectorExtension::configure in order to configure the nested projector.

If your extension \( E \) leads to a non-linear projector (regarding project or projectComposite), i.e. \( E(a\boldsymbol{v_{1}}+\boldsymbol{v_{2}})\neq aE\boldsymbol{v_{1}}+E\boldsymbol{v_{2}} \) , with volumes \( \boldsymbol{v_{1}} \), \( \boldsymbol{v_{2}} \) and \( a\in \mathbb{R} \), then you should override AbstractProjector::isLinear so that it returns false. Otherwise do not override this method—in particular do not override with true.

The full effect of an extension can be formalized as follows. An extension \( E \) can be decomposed into three operators:

\( E\left\{A_{\boldsymbol{\pi}}\right\}\boldsymbol{v}=P\,A_{\Pi\boldsymbol{\pi}}\,V\boldsymbol{v}, \)

a modficication \( V \) of the VolumeData \( \boldsymbol{v} \), a modification \( \Pi \) of the AcquisitionSetup \( \boldsymbol{\pi} \) and a modification \( P \) of the ProjectionData after projection with the nested projector \( A_{\Pi\boldsymbol{\pi}} \) (that uses the modified AcquisitionSetup \( \Pi\boldsymbol{\pi} \)). All three operators "maintain the dimensionality" of the objects they affect. Only the nested projector \( A \) maps from volume space to projection space. In case you directly use the ProjectorExtension class (without any customization) all three operators are identity maps, i.e. it reduces to

\( E\left\{A_{\boldsymbol{\pi}}\right\}\boldsymbol{v}=A_{\boldsymbol{\pi}}\,\boldsymbol{v}\,, \)

meaning that only the nested projector is applied.

In case you opt for variant 1, i.e. you override the extendedProject method, you can only implement the \( P \) and \( \Pi \) operators, i.e.

\( E\left\{A_{\boldsymbol{\pi}}\right\}\boldsymbol{v}=PA_{\Pi\boldsymbol{\pi}}\,\boldsymbol{v}\,. \)

If even a custom \( \Pi \) is not provided, it leads to an extension that performs only post-processing of the ProjectionData, i.e. it represents a part in a classical pipeline. The variant 2 effectively enables the implementation of all the three operators \( V \), \( \Pi \) and \( P \).

When considering a concatenation of two extensions, first/inner \( E_1 \) and then/outer \( E_2 \) (i.e. E2->use(E1) or equivalent E1|E2), the following order of operators is applied by design:

\( \left(E_{2}\circ E_{1}\right)\left\{ A_{\boldsymbol{\pi}}\right\} \boldsymbol{v}= P_{2}P_{1}\,A_{\Pi_{1}\Pi_{2}\boldsymbol{\boldsymbol{\pi}}}\,V_{1}V_{2}\boldsymbol{v}. \)

In other words \( P \) is a post-processing operator while \( \Pi \) and \( V \) are pre-processing operators. This is simply due to the fact that the AcquisitionSetup/VolumeData could be changed before calling configure/project(Composite) of the nested projector whereas the ProjectionData may be changed afterwards.

See also
configure(), project().

Constructor & Destructor Documentation

◆ ProjectorExtension() [1/2]

CTL::ProjectorExtension::ProjectorExtension ( AbstractProjector projector = nullptr)
explicit

Constructs a ProjectorExtension object and sets the nested projector to projector. The nested projector is internally used as a basis for computing forward projections. Note that the constructed object takes over the ownership of projector.

◆ ProjectorExtension() [2/2]

CTL::ProjectorExtension::ProjectorExtension ( std::unique_ptr< AbstractProjector projector)
explicit

Constructs a ProjectorExtension object and sets the nested projector to projector. A good practice to create a ProjectorExtension on the heap is to use the make function makeExtension(std::unique_ptr<AbstractProjector> projector) which will interally use this constructor.

Member Function Documentation

◆ configure()

void CTL::ProjectorExtension::configure ( const AcquisitionSetup setup)
overridevirtual

This overrides the configure() method and calls the configure method of the nested projector object.

Re-implement this method to retrieve all information required for the purpose of the desired extension. Make sure to delegate this call to the base class (ProjectorExtension) at the end of the method.

Throws std::runtime_error if the nested projector object is unset.

Implements CTL::AbstractProjector.

Reimplemented in CTL::SpectralEffectsExtension.

◆ extendedProject()

ProjectionData CTL::ProjectorExtension::extendedProject ( const MetaProjector nestedProjector)
protectedvirtual

This protected virtual method can be overridden in a subclass in order to implement a custom ProjectorExtension. An implementation of extendedProject is convenient, because an implementation of the two functions project and projectComposite can be avoided. However, this strategy enables only ProjectorExtensions that perform post-processing of the ProjectionData from the nested projector and/or a modification of the AcquisitionSetup (by calling ProjectorExtension::configure), but no change of the VolumeData.

You can simply obtain the ProjectionData from the nestedProjector via the call nestedProjector.project(), no matter if the client called project or projectComposite. Subsequent processing can be implemented before the data will be returned.

Reimplemented in CTL::ArealFocalSpotExtension, CTL::PoissonNoiseExtension, and CTL::DetectorSaturationExtension.

◆ fromVariant()

void CTL::ProjectorExtension::fromVariant ( const QVariant &  variant)
overridevirtual

Sets the contents of the object based on the QVariant variant.

Implementation of the deserialization interface. This method uses setParameter() to deserialize class members.

Reimplemented from CTL::AbstractProjector.

◆ isLinear()

bool CTL::ProjectorExtension::isLinear ( ) const
overridevirtual

Returns true if the projection operation is linear.

By default, this method returns true. Override this method to return false in case of sub-classing that leads to non-linear operations. Overrides of this method should never return an unconditional true (as this might outrule underlying non-linearity).

Reimplemented from CTL::AbstractProjector.

Reimplemented in CTL::SpectralEffectsExtension.

◆ project()

ProjectionData CTL::ProjectorExtension::project ( const VolumeData volume)
overridevirtual

This overrides the project() method and calls the project method of the nested projector object.

Re-implement this method to modify the projections in order to realize the desired functionality of your extension.

Throws std::runtime_error if the nested projector object is unset.

Implements CTL::AbstractProjector.

Reimplemented in CTL::SpectralEffectsExtension.

◆ projectComposite()

ProjectionData CTL::ProjectorExtension::projectComposite ( const CompositeVolume volume)
overridevirtual

Provides the functionality to forward project CompositeVolume data.

This method takes a composite dataset volume and returns the full set of forward projections according to the AcquisitionSetup set in the configure() step.

By default, this method performs separate calls to project() for each individual voxel volume stored in the composite volume. The final projection result is the sum of all these individual projections (extinction domain). Change this behavior in sub-classes, if this is not suitable for your desired purpose. This is typically the case for non-linear operations.

If you intend to call configure() and projectComposite() directly after each other, you should use configureAndProject() instead.

Reimplemented from CTL::AbstractProjector.

Reimplemented in CTL::SpectralEffectsExtension.

◆ projectSparse()

ProjectionData CTL::ProjectorExtension::projectSparse ( const SparseVoxelVolume volume)
overridevirtual

Provides the functionality to forward project SparseVoxelVolume data.

This method takes a sparse dataset volume and returns the full set of forward projections according to the AcquisitionSetup set in the configure() step.

By default, this method performs converts volume to a regular VoxelVolume<float> and calls project() with it. Re-implement this method in sub-classes if you can provide more efficient ways of forward projecting sparse data.

If you intend to call configure() and projectSparse() directly after each other, you should use configureAndProject() instead.

Reimplemented from CTL::AbstractProjector.

Reimplemented in CTL::SpectralEffectsExtension.

◆ release()

AbstractProjector * CTL::ProjectorExtension::release ( )

Releases the nested projector object.

This transfers the ownership of the projector object to the caller. The internal nested projector pointer is set to nullptr.

◆ reset()

void CTL::ProjectorExtension::reset ( )

Resets this instance. This deletes the nested projector object and sets the internal pointer to nullptr.

◆ toVariant()

QVariant CTL::ProjectorExtension::toVariant ( ) const
overridevirtual

Stores the contents of this instance in a QVariant.

Implementation of the serialization interface. Stores the object's type-id (from SerializationInterface::toVariant()).

This method uses parameter() to serialize class members.

Reimplemented from CTL::AbstractProjector.

Reimplemented in CTL::SpectralEffectsExtension.

◆ type()

int CTL::ProjectorExtension::type ( ) const
inlineoverridevirtual

Returns the type-id of the serializable object. Used in deserialization to determine the proper object type.

Add derived classes to the enumeration using the CTL_TYPE_ID macro.

Reimplemented from CTL::AbstractProjector.

Reimplemented in CTL::SpectralEffectsExtension.

◆ use() [1/2]

void CTL::ProjectorExtension::use ( AbstractProjector other)
virtual

Sets the nested projector to other.

This will overwrite any projector object that is already in place by deleting it. If this is unintended, consider retrieving the nested projector first using release(). Note that it takes over the ownership of projector.

◆ use() [2/2]

void CTL::ProjectorExtension::use ( std::unique_ptr< AbstractProjector other)

Overload of use(AbstractProjector* other) that takes a std::unique_ptr of the other projector.

Friends And Related Function Documentation

◆ makeExtension() [1/2]

std::unique_ptr< ProjectorExtensionType > makeExtension ( AbstractProjector projector = nullptr)
related

Global (free) make function that creates a new ProjectorExtension by taking over the ownership of a projector. The projector will be the nested projector of the returned ProjectorExtension. The component is returned as a std::unique_ptr<ProjectorExtensionType>, whereas ProjectorExtensionType is the template argument of this function that needs to be specified.

◆ makeExtension() [2/2]

std::unique_ptr< ProjectorExtensionType > makeExtension ( std::unique_ptr< AbstractProjector projector)
related

Global (free) make function that creates a new ProjectorExtension by taking over the ownership of a projector. The projector will be the nested projector of the returned ProjectorExtension. The component is returned as a std::unique_ptr<ProjectorExtensionType>, whereas ProjectorExtensionType is the template argument of this function that needs to be specified.


The documentation for this class was generated from the following files: