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

The SpectralEffectsExtension class is an extension for forward projectors that provides functionality to consider spectral effects. More...

#include <spectraleffectsextension.h>

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

Public Types

enum  { Type = 104 }
 
- Public Types inherited from CTL::ProjectorExtension
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
 
 SpectralEffectsExtension (float energyBinWidth)
 
ProjectionData projectComposite (const CompositeVolume &volume) override
 
ProjectionData projectSparse (const SparseVoxelVolume &volume) override
 Provides the functionality to forward project SparseVoxelVolume data. More...
 
bool isLinear () const override
 
QVariant toVariant () const override
 Stores the contents of this instance in a QVariant. More...
 
QVariant parameter () const override
 
void setParameter (const QVariant &parameter) override
 Sets the parameters of this instance based on the passed QVariant parameter. Parameters need to follow the naming convention as described in parameter(). More...
 
void setSpectralSamplingResolution (float energyBinWidth)
 
 ProjectorExtension (AbstractProjector *projector=nullptr)
 
 ProjectorExtension (std::unique_ptr< AbstractProjector > projector)
 
- Public Member Functions inherited from CTL::ProjectorExtension
 ProjectorExtension (AbstractProjector *projector=nullptr)
 
 ProjectorExtension (std::unique_ptr< AbstractProjector > projector)
 
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...
 
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 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
 

Private Types

using BinInformation = SpectralInformation::BinInformation
 

Private Member Functions

void updateSpectralInformation ()
 
bool canBypassExtension (const CompositeVolume &volume) const
 
void applyDetectorResponse (ProjectionData &intensity, float energy) const
 
ProjectionData projectLinear (const CompositeVolume &volume)
 
ProjectionData projectNonLinear (const CompositeVolume &volume)
 
ProjectionData singleBinIntensityLinear (const std::vector< ProjectionData > &materialProjs, const std::vector< float > &massAttenCoeffs, const BinInformation &binInfo)
 
ProjectionData singleBinIntensityNonLinear (const CompositeVolume &volume, const BinInformation &binInfo)
 
void addDummyPrepareSteps ()
 
void removeDummyPrepareSteps ()
 
void replaceDummyPrepareSteps (const BinInformation &binInfo, float binWidth)
 

Private Attributes

SpectralInformation _spectralInfo
 
AcquisitionSetup _setup
 A copy of the setup used for acquisition.
 
float _deltaE { 0.0f }
 

Friends

template<class >
struct SerializationHelper::RegisterWithSerializationHelper
 

Additional Inherited Members

- Protected Member Functions inherited from CTL::ProjectorExtension
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
 

Detailed Description

The SpectralEffectsExtension class is an extension for forward projectors that provides functionality to consider spectral effects.

This extension adds the functionality to consider spectral effects within the projections. These effects encompass:

Generally speaking, this extension sub-divides the projection task into multiple subtasks, each representing a single energy bin, for within which monoenergetic behavior (corresponding to the bin energy) is assumed. Depending on whether the nested projector routine is linear or not, the actual performed procedure differs. More detailed information is provided in project() and projectComposite().

Meaningful results are achieved only if this extension is used in combination with volume data that contains full spectral information (see SpectralVolumeData::hasSpectralInformation()). In case volume data without spectral information is used, this extension will be bypassed (Note that the combination of non-spectral volume data with a detector component that has explicitely being assigned a spectral response model is contradictory, and consequently an exception will be thrown).

// define volume as a ball filled with attenuation 0.081/mm (approx. bone @ 50 keV)
auto volume = VoxelVolume<float>::ball(50.0f, 0.5f, 0.081f);
// create a spectral volume using the voxel data from volume and the correct attenuation model (for bone)
auto spectralVol = SpectralVolumeData::fromMuVolume(volume,
database::attenuationModel(database::Composite::Bone_Cortical));
auto system = SimpleCTSystem::fromCTSystem(CTSystemBuilder::createFromBlueprint(blueprints::GenericCarmCT(DetectorBinning::Binning4x4)));
AcquisitionSetup acquisitionSetup(system, 10);
acquisitionSetup.applyPreparationProtocol(protocols::ShortScanTrajectory(750.0));
// Core part
auto simpleProjector = new RayCasterProjector; // our simple projector
// optional parameter settings for the projector
// e.g. simpleProjector->settings().raySampling = 0.1f;
// this is what you do without extension:
// simpleProjector->configure(acquisitionSetup);
// ProjectionData projections = simpleProjector->project(volume);
// Note that we used the 'plain' volume here; instead we could also do:
// ProjectionData projections = simpleProjector->project(*spectralVol.muVolume(50.0f));
// To consider spectral effects, we now do the following:
SpectralEffectsExtension* extension = new SpectralEffectsExtension;
extension->use(simpleProjector); // tell the extension to use the ray caster
extension->setSpectralSamplingResolution(10.0f); // set the energy resolution for spectral effects
extension->configure(acquisitionSetup); // configure the simulation
ProjectionData projections = extension->project(spectralVol); // (compute and) get the final projections
// Note that we must use a 'spectral' volume here for spectral effects to be considered.
// (Passing the 'plain' volume leads to the same result as using the ray caster without extension.)

The difference between projections with and without spectral effects in the example above is shown here:

Simulated projections of a homogeneous bone ball without (left) and with spectral effects (right) considered.

The following plot shows a comparison of the normalized absorption profiles shown in the figures above.

Normalized absorption profiles without (red) and with spectral effects (black) considered.

Constructor & Destructor Documentation

◆ SpectralEffectsExtension()

CTL::SpectralEffectsExtension::SpectralEffectsExtension ( float  energyBinWidth)
explicit

Constructs a SpectralEffectsExtension and sets the bin width for sub-sampling of the spectral range to energyBinWidth (in keV). If energyBinWidth = 0, the energy bin width will be determined using the information received from AbstractSource::spectrumDiscretizationHint() of the source component in the setup provided to configure().

Member Function Documentation

◆ addDummyPrepareSteps()

void CTL::SpectralEffectsExtension::addDummyPrepareSteps ( )
private

Adds dummy prepare steps (of type prepare::SourceParam) to the setup. Those are later used to adjust the energy range and the flux of the system for the currently processed energy bin.

See also
replaceDummyPrepareSteps().

◆ applyDetectorResponse()

void CTL::SpectralEffectsExtension::applyDetectorResponse ( ProjectionData intensity,
float  energy 
) const
private

Processes projection data in intensity (corresponding to the radiation energy energy) to account for spectral detector response. For that, each intensity value is multiplied by the detector response for energy energy.

◆ canBypassExtension()

bool CTL::SpectralEffectsExtension::canBypassExtension ( const CompositeVolume volume) const
private

Returns true if no spectral effects need to be considered, i.e. neither the detector nor any of the subvolumes in volume have spectral information. This function throws an exception if the detector has a spectral response model and not all the subvolumes in volume have spectral information. In any other case than the aforementioned, false is returned.

◆ configure()

void CTL::SpectralEffectsExtension::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.

Reimplemented from CTL::ProjectorExtension.

◆ isLinear()

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

Returns false, because spectral effects are non-linear (summation in intensity domain).

Reimplemented from CTL::ProjectorExtension.

◆ parameter()

QVariant CTL::SpectralEffectsExtension::parameter ( ) const
overridevirtual

Returns the parameters of this instance as QVariant.

This returns a QVariantMap with one key-value-pair: ("Sampling resolution", _deltaE), which represents the energy resolution (in keV per bin) used for sampling of spectral effects:

This method is used within toVariant() to serialize the object's settings.

Reimplemented from CTL::AbstractProjector.

◆ project()

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

Computes projections of volume considering spectral effects, by means of creating individual projections for a number of energy bins and averaging the results in intensity domain.

For a specific pixel, computation of the extinction value can be expressed as:

\( \begin{align*} \epsilon & =\ln\frac{I_{0}}{\sum_{E}i_{0}(E) \exp\left[-m(E)\mathcal{F}_{\textrm{linear}}(\rho)\right]}\\ \epsilon & =\ln\frac{I_{0}}{\sum_{E}i_{0}(E) \exp\left[-\mathcal{F}_{\textrm{non-linear}}(m(E)\cdot\rho)\right]}, \end{align*} \)

depending on whether the nested projector of this instance is linear ( \(\mathcal{F}_{\textrm{linear}}\), upper row) or not ( \(\mathcal{F}_{\textrm{non-linear}}\), bottom row). Here, \(i_{0}(E)\) denotes the initial intensity of energy \(E\), \(m(E)\) is the energy-dependent mass attenuation coefficient of the material, and \(\rho\) is the material density (3D voxelized data); \(I_{0}\) denotes the total intensity. As can be seen from the equations, in case of a linear nested projector, it is sufficient to forward project the material density, thus only a single projection operation is required.

Reimplemented from CTL::ProjectorExtension.

◆ projectComposite()

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

Computes projections of the composite volume volume considering spectral effects, by means of creating individual projections for a number of energy bins and averaging the results in intensity domain.

For a specific pixel, computation of the extinction value can be expressed as:

\( \begin{align*} \epsilon & =\ln\frac{I_{0}}{\sum_{E}i_{0}(E) \exp\left[-\sum_{k}m_{k}(E)\mathcal{F}_{\textrm{linear}}(\rho_{k})\right]}\\ \epsilon & =\ln\frac{I_{0}}{\sum_{E}i_{0}(E) \exp\left[-\sum_{k}\mathcal{F}_{\textrm{non-linear}}(m_{k}(E)\cdot\rho_{k})\right]}\\ \end{align*} \)

depending on whether the nested projector of this instance is linear ( \(\mathcal{F}_{\textrm{linear}}\), upper row) or not ( \(\mathcal{F}_{\textrm{non-linear}}\), bottom row). Here, \(i_{0}(E)\) denotes the initial intensity of energy \(E\), \(m_{k}(E)\) is the energy-dependent mass attenuation coefficient of material \(k\), and \(\rho_{k}\) its material density (3D voxelized data); \(I_{0}\) denotes the total intensity. As can be seen from the equations, in case of a linear nested projector, it is sufficient to forward project the material densities of all materials, thus only a single projection operation per sub-volume in volume is required. Note that this might result in substantial memory requirement.

Reimplemented from CTL::ProjectorExtension.

◆ projectLinear()

ProjectionData CTL::SpectralEffectsExtension::projectLinear ( const CompositeVolume volume)
private

Computes the projections from volume with a linear nested projector.

The internal workflow is as follows:

  1. Compute forward projections of the material density of all subvolumes in volume.
  2. For each energy bin: compute intensity using singleBinIntensityLinear() and add result to total sum.
  3. Transform final result to extinction domain.

◆ projectNonLinear()

ProjectionData CTL::SpectralEffectsExtension::projectNonLinear ( const CompositeVolume volume)
private

Computes the projections from volume with a non-linear nested projector.

The internal workflow is as follows:

  1. Add dummy prepare steps to the setup (later used to adjust system for the energy bin).
  2. For each energy bin: compute intensity using singleBinIntensityNonLinear() and add result to total sum.
  3. Transform final result to extinction domain.
  4. Remove dummy prepare steps to restore original setup.

◆ ProjectorExtension() [1/2]

CTL::ProjectorExtension::ProjectorExtension
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
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.

◆ projectSparse()

ProjectionData CTL::SpectralEffectsExtension::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::ProjectorExtension.

◆ removeDummyPrepareSteps()

void CTL::SpectralEffectsExtension::removeDummyPrepareSteps ( )
private

Removes all dummy prepare steps added by addDummyPrepareSteps(). Must not be called if addDummyPrepareSteps() has not been called earlier.

◆ replaceDummyPrepareSteps()

void CTL::SpectralEffectsExtension::replaceDummyPrepareSteps ( const BinInformation binInfo,
float  binWidth 
)
private

Replaces the dummy prepare steps (see addDummyPrepareSteps()) in the setup to adjust the energy range and the flux of the system for the currently processed energy bin (as specified by binInfo).

◆ setParameter()

void CTL::SpectralEffectsExtension::setParameter ( const QVariant &  parameter)
overridevirtual

Sets the parameters of this instance based on the passed QVariant parameter. Parameters need to follow the naming convention as described in parameter().

This method is used within fromVariant() to deserialize the object's settings. Direct use of this method is discouraged; consider using dedicated setter methods instead.

Reimplemented from CTL::AbstractProjector.

◆ setSpectralSamplingResolution()

void CTL::SpectralEffectsExtension::setSpectralSamplingResolution ( float  energyBinWidth)

Sets the energy resolution for sampling of spectral effects to energyBinWidth (in keV). This represents the bin width used for (spectrally) sub-sampling the projections. If energyBinWidth = 0, the energy bin width will be determined using the information received from AbstractSource::spectrumDiscretizationHint() of the source component in the setup provided to configure().

◆ singleBinIntensityLinear()

ProjectionData CTL::SpectralEffectsExtension::singleBinIntensityLinear ( const std::vector< ProjectionData > &  materialProjs,
const std::vector< float > &  massAttenCoeffs,
const BinInformation binInfo 
)
private

Computes the intensity image for a specific energy bin (as specified by binInfo) based on the precomputed forward projections of material densities (materialProjs) and the specific mass attenuation coefficients massAttenCoeffs for the particular energy bin (one value for each material, i.e. materialProjs.size() == massAttenCoeffs.size()).

The internal workflow is as follows:

  1. For each material: compute product of projection and corresponding attenuation coefficient and sum up results
  2. Transform final sum to intensity domain (based on intensity data from binInfo).
  3. Apply (spectral) detector response (see applyDetectorResponse()).

In case the total intensity of the energy bin is zero, the bin will be skipped and a zero image is returned.

◆ singleBinIntensityNonLinear()

ProjectionData CTL::SpectralEffectsExtension::singleBinIntensityNonLinear ( const CompositeVolume volume,
const BinInformation binInfo 
)
private

Computes the projection intensity image of the volume data in volume for a specific energy bin (as specified by binInfo).

The internal workflow is as follows:

  1. For each material: compute forward projection of the attenuation data for the specific energy bin (see SpectralVolumeData::muVolume()) and sum up results.
  2. Transform final sum to intensity domain (based on intensity data from binInfo).
  3. Apply (spectral) detector response (see applyDetectorResponse()).

In case the total intensity of the energy bin is zero, the bin will be skipped and a zero image is returned.

◆ toVariant()

QVariant CTL::SpectralEffectsExtension::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::ProjectorExtension.

◆ type()

int CTL::SpectralEffectsExtension::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::ProjectorExtension.

◆ updateSpectralInformation()

void CTL::SpectralEffectsExtension::updateSpectralInformation ( )
private

Causes an update of the spectral information to take place.

See also
RadiationEncoder::spectralInformation().

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