Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for fixed-length vectors in SetInput functions of two-steps spectral filters #688

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion include/rtkSimplexSpectralProjectionsDecompositionImageFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class ITK_TEMPLATE_EXPORT SimplexSpectralProjectionsDecompositionImageFilter
using DetectorResponseType = vnl_matrix<double>;
using MaterialAttenuationsType = vnl_matrix<double>;
using CostFunctionType = ProjectionsDecompositionNegativeLogLikelihood;
using DecomposedProjectionsDataType = typename DecomposedProjectionsType::PixelType::ValueType;
using MeasuredProjectionsDataType = typename MeasuredProjectionsType::PixelType::ValueType;

#ifndef ITK_FUTURE_LEGACY_REMOVE
/** Additional types to overload SetInputIncidentSpectrum */
Expand All @@ -84,15 +86,32 @@ class ITK_TEMPLATE_EXPORT SimplexSpectralProjectionsDecompositionImageFilter
/** Set/Get the input material-decomposed stack of projections (only used for initialization) */
void
SetInputDecomposedProjections(const DecomposedProjectionsType * DecomposedProjections);
void
SetInputDecomposedProjections(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't it work if you keep the original

void  SetInputDecomposedProjections(const DecomposedProjectionsType * DecomposedProjections);

separate for clarity?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should. I'll change it.

const typename itk::ImageBase<DecomposedProjectionsType::ImageDimension> * DecomposedProjections);
template <unsigned int VNumberOfMaterials>
void
SetInputFixedVectorLengthDecomposedProjections(
const itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,
DecomposedProjectionsType::ImageDimension> * DecomposedProjections);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it accessible from the wrapping? I'll check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not have to be: SetInputFixedVectorLengthDecomposedProjections is supposed to be accessed only by SetInputDecomposedProjections, once it has determined which vector length to use. The wrappings should only expose SetInputDecomposedProjections

typename DecomposedProjectionsType::ConstPointer
GetInputDecomposedProjections();

/** Set/Get the input stack of measured projections (to be decomposed in materials) */
void
SetInputMeasuredProjections(const MeasuredProjectionsType * SpectralProjections);
SetInputMeasuredProjections(const MeasuredProjectionsType * MeasuredProjections);
void
SetInputMeasuredProjections(
const typename itk::ImageBase<MeasuredProjectionsType::ImageDimension> * MeasuredProjections);
template <unsigned int VNumberOfSpectralBins>
void
SetInputFixedVectorLengthMeasuredProjections(
const itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,
MeasuredProjectionsType::ImageDimension> * MeasuredProjections);
typename MeasuredProjectionsType::ConstPointer
GetInputMeasuredProjections();


/** Set/Get the detector response as an image */
void
SetDetectorResponse(const DetectorResponseImageType * DetectorResponse);
Expand Down
164 changes: 162 additions & 2 deletions include/rtkSimplexSpectralProjectionsDecompositionImageFilter.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,83 @@ SimplexSpectralProjectionsDecompositionImageFilter<
this->SetNthInput(0, const_cast<DecomposedProjectionsType *>(DecomposedProjections));
}

template <typename DecomposedProjectionsType,
typename MeasuredProjectionsType,
typename IncidentSpectrumImageType,
typename DetectorResponseImageType,
typename MaterialAttenuationsImageType>
void
SimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,
MeasuredProjectionsType,
IncidentSpectrumImageType,
DetectorResponseImageType,
MaterialAttenuationsImageType>::
SetInputDecomposedProjections(
const typename itk::ImageBase<DecomposedProjectionsType::ImageDimension> * DecomposedProjections)
{
// Attempt to dynamic_cast DecomposedProjections into one of the supported types
typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 1>, DecomposedProjectionsType::ImageDimension> Type1;
typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 2>, DecomposedProjectionsType::ImageDimension> Type2;
typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 3>, DecomposedProjectionsType::ImageDimension> Type3;
typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 4>, DecomposedProjectionsType::ImageDimension> Type4;
typedef itk::Image<itk::Vector<DecomposedProjectionsDataType, 5>, DecomposedProjectionsType::ImageDimension> Type5;
const Type1 * ptr1 = dynamic_cast<const Type1 *>(DecomposedProjections);
const Type2 * ptr2 = dynamic_cast<const Type2 *>(DecomposedProjections);
const Type3 * ptr3 = dynamic_cast<const Type3 *>(DecomposedProjections);
const Type4 * ptr4 = dynamic_cast<const Type4 *>(DecomposedProjections);
const Type5 * ptr5 = dynamic_cast<const Type5 *>(DecomposedProjections);

if (ptr1)
{
this->SetInputFixedVectorLengthDecomposedProjections<1>(ptr1);
}
else if (ptr2)
{
this->SetInputFixedVectorLengthDecomposedProjections<2>(ptr2);
}
else if (ptr3)
{
this->SetInputFixedVectorLengthDecomposedProjections<3>(ptr3);
}
else if (ptr4)
{
this->SetInputFixedVectorLengthDecomposedProjections<4>(ptr4);
}
else if (ptr5)
{
this->SetInputFixedVectorLengthDecomposedProjections<5>(ptr5);
}
else
{
itkWarningMacro("The input does not match any of the supported types, and has been ignored");
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe a warning if we don't do anything?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

template <typename DecomposedProjectionsType,
typename MeasuredProjectionsType,
typename IncidentSpectrumImageType,
typename DetectorResponseImageType,
typename MaterialAttenuationsImageType>
template <unsigned int VNumberOfMaterials>
void
SimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,
MeasuredProjectionsType,
IncidentSpectrumImageType,
DetectorResponseImageType,
MaterialAttenuationsImageType>::
SetInputFixedVectorLengthDecomposedProjections(
const itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,
DecomposedProjectionsType::ImageDimension> * DecomposedProjections)
{
using ActualInputType = itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,
DecomposedProjectionsType::ImageDimension>;
using CastFilterType = itk::CastImageFilter<ActualInputType, DecomposedProjectionsType>;
typename CastFilterType::Pointer castPointer = CastFilterType::New();
castPointer->SetInput(DecomposedProjections);
castPointer->Update();
this->SetNthInput(0, const_cast<DecomposedProjectionsType *>(castPointer->GetOutput()));
}

template <typename DecomposedProjectionsType,
typename MeasuredProjectionsType,
typename IncidentSpectrumImageType,
Expand All @@ -103,9 +180,92 @@ SimplexSpectralProjectionsDecompositionImageFilter<
MeasuredProjectionsType,
IncidentSpectrumImageType,
DetectorResponseImageType,
MaterialAttenuationsImageType>::SetInputMeasuredProjections(const MeasuredProjectionsType * SpectralProjections)
MaterialAttenuationsImageType>::SetInputMeasuredProjections(const MeasuredProjectionsType * MeasuredProjections)
{
this->SetInput("MeasuredProjections", const_cast<MeasuredProjectionsType *>(MeasuredProjections));
}

template <typename DecomposedProjectionsType,
typename MeasuredProjectionsType,
typename IncidentSpectrumImageType,
typename DetectorResponseImageType,
typename MaterialAttenuationsImageType>
void
SimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,
MeasuredProjectionsType,
IncidentSpectrumImageType,
DetectorResponseImageType,
MaterialAttenuationsImageType>::
SetInputMeasuredProjections(
const typename itk::ImageBase<MeasuredProjectionsType::ImageDimension> * MeasuredProjections)
{
// Attempt to dynamic_cast MeasuredProjections into one of the supported types
typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 1>, MeasuredProjectionsType::ImageDimension> Type1;
typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 2>, MeasuredProjectionsType::ImageDimension> Type2;
typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 3>, MeasuredProjectionsType::ImageDimension> Type3;
typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 4>, MeasuredProjectionsType::ImageDimension> Type4;
typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 5>, MeasuredProjectionsType::ImageDimension> Type5;
typedef itk::Image<itk::Vector<MeasuredProjectionsDataType, 6>, MeasuredProjectionsType::ImageDimension> Type6;
const Type1 * ptr1 = dynamic_cast<const Type1 *>(MeasuredProjections);
const Type2 * ptr2 = dynamic_cast<const Type2 *>(MeasuredProjections);
const Type3 * ptr3 = dynamic_cast<const Type3 *>(MeasuredProjections);
const Type4 * ptr4 = dynamic_cast<const Type4 *>(MeasuredProjections);
const Type5 * ptr5 = dynamic_cast<const Type5 *>(MeasuredProjections);
const Type6 * ptr6 = dynamic_cast<const Type6 *>(MeasuredProjections);

if (ptr1)
{
this->SetInputFixedVectorLengthMeasuredProjections<1>(ptr1);
}
else if (ptr2)
{
this->SetInputFixedVectorLengthMeasuredProjections<2>(ptr2);
}
else if (ptr3)
{
this->SetInputFixedVectorLengthMeasuredProjections<3>(ptr3);
}
else if (ptr4)
{
this->SetInputFixedVectorLengthMeasuredProjections<4>(ptr4);
}
else if (ptr5)
{
this->SetInputFixedVectorLengthMeasuredProjections<5>(ptr5);
}
else if (ptr6)
{
this->SetInputFixedVectorLengthMeasuredProjections<6>(ptr6);
}
else
{
itkWarningMacro("The input does not match any of the supported types, and has been ignored");
}
}

template <typename DecomposedProjectionsType,
typename MeasuredProjectionsType,
typename IncidentSpectrumImageType,
typename DetectorResponseImageType,
typename MaterialAttenuationsImageType>
template <unsigned int VNumberOfSpectralBins>
void
SimplexSpectralProjectionsDecompositionImageFilter<DecomposedProjectionsType,
MeasuredProjectionsType,
IncidentSpectrumImageType,
DetectorResponseImageType,
MaterialAttenuationsImageType>::
SetInputFixedVectorLengthMeasuredProjections(
const itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,
MeasuredProjectionsType::ImageDimension> * MeasuredProjections)
{
this->SetInput("MeasuredProjections", const_cast<MeasuredProjectionsType *>(SpectralProjections));
using ActualInputType = itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,
MeasuredProjectionsType::ImageDimension>;
using CastFilterType = itk::CastImageFilter<ActualInputType, MeasuredProjectionsType>;
typename CastFilterType::Pointer castPointer = CastFilterType::New();
castPointer->SetInput(MeasuredProjections);
castPointer->UpdateLargestPossibleRegion();
this->SetInput("MeasuredProjections", const_cast<MeasuredProjectionsType *>(castPointer->GetOutput()));
}

template <typename DecomposedProjectionsType,
Expand Down
21 changes: 20 additions & 1 deletion include/rtkSpectralForwardModelImageFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

#include <itkPermuteAxesImageFilter.h>
#include <itkInPlaceImageFilter.h>
#include <itkCastImageFilter.h>

namespace rtk
{
Expand Down Expand Up @@ -66,6 +67,8 @@ class ITK_TEMPLATE_EXPORT SpectralForwardModelImageFilter
using ThresholdsType = itk::VariableLengthVector<double>;
using DetectorResponseType = vnl_matrix<double>;
using MaterialAttenuationsType = vnl_matrix<double>;
using DecomposedProjectionsDataType = typename DecomposedProjectionsType::PixelType::ValueType;
using MeasuredProjectionsDataType = typename MeasuredProjectionsType::PixelType::ValueType;

#ifndef ITK_FUTURE_LEGACY_REMOVE
/** Additional types to overload SetInputIncidentSpectrum */
Expand Down Expand Up @@ -99,12 +102,28 @@ class ITK_TEMPLATE_EXPORT SpectralForwardModelImageFilter
/** Set/Get the input material-decomposed stack of projections (only used for initialization) */
void
SetInputDecomposedProjections(const DecomposedProjectionsType * DecomposedProjections);
void
SetInputDecomposedProjections(
const typename itk::ImageBase<DecomposedProjectionsType::ImageDimension> * DecomposedProjections);
template <unsigned int VNumberOfMaterials>
void
SetInputFixedVectorLengthDecomposedProjections(
const itk::Image<itk::Vector<DecomposedProjectionsDataType, VNumberOfMaterials>,
DecomposedProjectionsType::ImageDimension> * DecomposedProjections);
typename DecomposedProjectionsType::ConstPointer
GetInputDecomposedProjections();

/** Set/Get the input stack of measured projections (to be decomposed in materials) */
void
SetInputMeasuredProjections(const MeasuredProjectionsType * SpectralProjections);
SetInputMeasuredProjections(const MeasuredProjectionsType * MeasuredProjections);
void
SetInputMeasuredProjections(
const typename itk::ImageBase<MeasuredProjectionsType::ImageDimension> * MeasuredProjections);
template <unsigned int VNumberOfSpectralBins>
void
SetInputFixedVectorLengthMeasuredProjections(
const itk::Image<itk::Vector<MeasuredProjectionsDataType, VNumberOfSpectralBins>,
MeasuredProjectionsType::ImageDimension> * MeasuredProjections);
typename MeasuredProjectionsType::ConstPointer
GetInputMeasuredProjections();

Expand Down
Loading
Loading