Commit 5da4a145 authored by Floris Berendsen's avatar Floris Berendsen
Browse files

BUG: ENH: added ReconnectInterface since Itk TransformOutput does not

comply with pipeline functionality
parent d7229b42
......@@ -53,12 +53,14 @@ namespace selx
typedef typename itk::ImageFileWriter<DeformationFieldImageType> DeformationFieldImageWriterType;
typedef FileWriterDecorator<DeformationFieldImageWriterType> DecoratedWriterType;
//Accepting Interfaces:
virtual int Set(AcceptingDisplacementFieldInterfaceType*) override;
virtual void SetMiniPipelineOutput(itk::DataObject::Pointer) override;
virtual itk::DataObject::Pointer GetMiniPipelineOutput(void) override;
virtual AnyFileWriter::Pointer GetOutputFileWriter(void) override;
virtual itk::DataObject::Pointer GetInitializedOutput(void) override;
//Providing Interfaces:
virtual void AfterRegistration() override;
virtual bool MeetsCriterion(const ComponentBase::CriterionType &criterion) override;
......
......@@ -208,6 +208,7 @@ void ItkImageRegistrationMethodv4Component< Dimensionality, TPixel>::RunRegistra
auto optimizer = dynamic_cast<itk::GradientDescentOptimizerv4 *>(this->m_theItkFilter->GetModifiableOptimizer());
//auto optimizer = dynamic_cast<itk::ObjectToObjectOptimizerBaseTemplate< InternalComputationValueType > *>(this->m_theItkFilter->GetModifiableOptimizer());
auto transform = this->m_theItkFilter->GetModifiableTransform();
if (msdMetric)
{
......
......@@ -44,7 +44,8 @@ namespace selx
itkImageFixedInterface<Dimensionality, TPixel>, //TODO should be FixedImageDomainInterface, we do not require intensities
itkImageMovingInterface<Dimensionality, TPixel>
>,
Providing< itkImageInterface<Dimensionality, TPixel>
Providing< itkImageInterface<Dimensionality, TPixel>,
ReconnectTransformInterface
>
>
{
......@@ -72,6 +73,7 @@ namespace selx
//Providing Interfaces:
virtual typename ResultImageType::Pointer GetItkImage() override;
virtual void ReconnectTransform() override;
//BaseClass methods
virtual bool MeetsCriterion(const ComponentBase::CriterionType &criterion) override;
......@@ -80,6 +82,7 @@ namespace selx
private:
typename ResampleFilterType::Pointer m_ResampleFilter;
itkTransformInterface<TInternalComputationValue, Dimensionality>* m_TransformComponent;
protected:
/* The following struct returns the string name of computation type */
/* default implementation */
......
......@@ -65,9 +65,12 @@ template <int Dimensionality, class TPixel, class TInternalComputationValue>
int ItkResampleFilterComponent< Dimensionality, TPixel, TInternalComputationValue>
::Set(itkTransformInterface<TInternalComputationValue, Dimensionality >* component)
{
//Store interface for later use
this->m_TransformComponent = component;
auto transform = component->GetItkTransform();
// connect the itk pipeline
this->m_ResampleFilter->SetTransform(transform.GetPointer());
this->m_ResampleFilter->SetTransform(transform);
return 0;
}
......@@ -82,6 +85,14 @@ ItkResampleFilterComponent< Dimensionality, TPixel, TInternalComputationValue>
return this->m_ResampleFilter->GetOutput();
}
template <int Dimensionality, class TPixel, class TInternalComputationValue>
void ItkResampleFilterComponent< Dimensionality, TPixel, TInternalComputationValue>
::ReconnectTransform()
{
auto transform = this->m_TransformComponent->GetItkTransform();
// reconnect the tranform, since it does not comply with the itk pipeline
this->m_ResampleFilter->SetTransform(transform);
}
template <int Dimensionality, class TPixel, class TInternalComputationValue>
bool
......
......@@ -41,9 +41,10 @@ namespace selx
class ItkTransformDisplacementFilterComponent :
public Implements<
Accepting< itkTransformInterface<TInternalComputationValue, Dimensionality>,
itkImageFixedInterface<Dimensionality, TPixel> //TODO should be FixedImageDomainInterface, we do not require intensities
itkImageDomainFixedInterface<Dimensionality>
>,
Providing< DisplacementFieldItkImageSourceInterface<Dimensionality, TPixel>
Providing< DisplacementFieldItkImageSourceInterface<Dimensionality, TPixel>,
ReconnectTransformInterface
>
>
{
......@@ -58,19 +59,18 @@ namespace selx
typedef TPixel PixelType;
// Get the type definitions from the interfaces
typedef typename itkImageFixedInterface<Dimensionality, TPixel>::ItkImageType FixedImageType;
typedef typename DisplacementFieldItkImageSourceInterface<Dimensionality, TPixel>::ItkImageType DisplacementFieldImageType;
using itkImageDomainFixedType = typename itkImageDomainFixedInterface<Dimensionality>::ItkImageDomainType;
using DisplacementFieldImageType = typename DisplacementFieldItkImageSourceInterface<Dimensionality, TPixel>::ItkImageType;
// TODO for now we hard code the transform to be a stationary velocity field. See Set(*MetricInterface) for implementation
typedef itk::TransformToDisplacementFieldFilter<DisplacementFieldImageType> DisplacementFieldFilterType;
using DisplacementFieldFilterType = itk::TransformToDisplacementFieldFilter<DisplacementFieldImageType>;
//Accepting Interfaces:
virtual int Set(itkImageFixedInterface<Dimensionality, TPixel>*) override;
virtual int Set(itkImageDomainFixedInterface<Dimensionality>*) override;
virtual int Set(itkTransformInterface<TInternalComputationValue, Dimensionality>*) override;
//Providing Interfaces:
virtual typename DisplacementFieldImageType::Pointer GetDisplacementFieldItkImage() override;
virtual void ReconnectTransform() override;
//BaseClass methods
virtual bool MeetsCriterion(const ComponentBase::CriterionType &criterion) override;
......@@ -79,6 +79,7 @@ namespace selx
private:
typename DisplacementFieldFilterType::Pointer m_DisplacementFieldFilter;
itkTransformInterface<TInternalComputationValue, Dimensionality>* m_TransformComponent;
protected:
/* The following struct returns the string name of computation type */
/* default implementation */
......
......@@ -37,15 +37,15 @@ namespace selx
template <int Dimensionality, class TPixel, class TInternalComputationValue>
int ItkTransformDisplacementFilterComponent< Dimensionality, TPixel, TInternalComputationValue>
::Set(itkImageFixedInterface<Dimensionality, TPixel>* component)
::Set(itkImageDomainFixedInterface<Dimensionality>* component)
{
auto fixedImage = component->GetItkImageFixed();
auto fixedImageDomain = component->GetItkImageDomainFixed();
// connect the itk pipeline
//this->m_DisplacementFieldFilter->SetSize(fixedImage->GetBufferedRegion().GetSize()); //should be virtual image...
this->m_DisplacementFieldFilter->SetSize(fixedImage->GetLargestPossibleRegion().GetSize()); //should be virtual image...
this->m_DisplacementFieldFilter->SetOutputOrigin(fixedImage->GetOrigin());
this->m_DisplacementFieldFilter->SetOutputSpacing(fixedImage->GetSpacing());
this->m_DisplacementFieldFilter->SetOutputDirection(fixedImage->GetDirection());
this->m_DisplacementFieldFilter->SetSize(fixedImageDomain->GetLargestPossibleRegion().GetSize()); //should be virtual image...
this->m_DisplacementFieldFilter->SetOutputOrigin(fixedImageDomain->GetOrigin());
this->m_DisplacementFieldFilter->SetOutputSpacing(fixedImageDomain->GetSpacing());
this->m_DisplacementFieldFilter->SetOutputDirection(fixedImageDomain->GetDirection());
this->m_DisplacementFieldFilter->UpdateOutputInformation();
return 0;
......@@ -55,9 +55,12 @@ template <int Dimensionality, class TPixel, class TInternalComputationValue>
int ItkTransformDisplacementFilterComponent< Dimensionality, TPixel, TInternalComputationValue>
::Set(itkTransformInterface<TInternalComputationValue, Dimensionality >* component)
{
//Store interface for later use
this->m_TransformComponent = component;
auto transform = component->GetItkTransform();
// connect the itk pipeline
this->m_DisplacementFieldFilter->SetTransform(transform.GetPointer());
this->m_DisplacementFieldFilter->SetTransform(transform);
return 0;
}
......@@ -73,6 +76,15 @@ ItkTransformDisplacementFilterComponent< Dimensionality, TPixel, TInternalComput
}
template <int Dimensionality, class TPixel, class TInternalComputationValue>
void ItkTransformDisplacementFilterComponent< Dimensionality, TPixel, TInternalComputationValue>
::ReconnectTransform()
{
auto transform = this->m_TransformComponent->GetItkTransform();
// reconnect the tranform, since it does not comply with the itk pipeline
this->m_DisplacementFieldFilter->SetTransform(transform);
}
template <int Dimensionality, class TPixel, class TInternalComputationValue>
bool
ItkTransformDisplacementFilterComponent< Dimensionality, TPixel, TInternalComputationValue>
......
......@@ -121,7 +121,7 @@ TEST_F(WBIRDemoTest, itkv4_SVF_ANTSCC)
blueprint->AddComponent("Metric", { { "NameOfClass", { "ItkANTSNeighborhoodCorrelationImageToImageMetricv4Component" } } });
blueprint->AddComponent("Optimizer", { { "NameOfClass", { "ItkGradientDescentOptimizerv4Component" } },
{ "NumberOfIterations", { "100" } },
{ "LearningRate", { "0.001" } } });
{ "LearningRate", { "100" } } });
blueprint->AddComponent("Transform", { { "NameOfClass", { "ItkGaussianExponentialDiffeomorphicTransformComponent" } } });
blueprint->AddComponent("ResampleFilter", { { "NameOfClass", { "ItkResampleFilterComponent" } } });
......
......@@ -217,6 +217,16 @@ struct InterfaceName < AfterRegistrationInterface >
}
};
template <>
struct InterfaceName < ReconnectTransformInterface >
{
static const char* Get()
{
return "ReconnectTransformInterface";
}
};
// partial specialization of InterfaceName
// InterfaceName<T>::Get() should return the same name no matter whether T is an acceptor or provider interface.
template<typename T1>
......
......@@ -101,6 +101,7 @@ namespace selx
typedef typename itk::Image<TPixel, Dimensionality> ItkImageType;
virtual typename ItkImageType::Pointer GetItkImageMoving() = 0;
};
template<int Dimensionality, class TPixel>
class DisplacementFieldItkImageSourceInterface {
// An interface that passes the pointer of an output image
......@@ -157,6 +158,13 @@ namespace selx
virtual bool RunResolution() = 0;
};
class ReconnectTransformInterface {
// A special interface: the Overlord checks components for this type of interface.
// This interface is for to control the execution of the network
public:
virtual void ReconnectTransform() = 0;
};
template<int Dimensionality, class TPixel>
class itkMetricv4Interface {
public:
......
......@@ -101,7 +101,7 @@ namespace selx
bool ConnectSinks();
bool RunRegistrations();
bool AfterRegistrations();
bool ReconnectTransforms();
//TODO make const correct
//Blueprint::ConstPointer m_Blueprint;
BlueprintType::Pointer m_Blueprint;
......
......@@ -300,6 +300,35 @@ namespace selx
}
return true;
}
bool Overlord::ReconnectTransforms()
{
/** Scans all Components to find those with ReconnectTransform capability and call them */
const CriterionType criterion = CriterionType("HasProvidingInterface", { "ReconnectTransformInterface" });
// TODO redesign ComponentBase class to accept a single criterion instead of a criteria mapping.
CriteriaType criteria;
criteria.insert(criterion);
for (auto const & componentSelector : (this->m_ComponentSelectorContainer))
{
ComponentBase::Pointer component = componentSelector.second->GetComponent();
if (component->MeetsCriteria(criteria)) // TODO MeetsCriterion
{
ReconnectTransformInterface* providingInterface = dynamic_cast<ReconnectTransformInterface*> (component.GetPointer());
if (providingInterface == nullptr) // is actually a double-check for sanity: based on criterion cast should be successful
{
itkExceptionMacro("dynamic_cast<ReconnectTransformInterface*> fails, but based on component criterion it shouldn't")
}
// For testing purposes, all Sources are connected to an ImageWriter
providingInterface->ReconnectTransform();
}
}
return true;
}
bool Overlord::Execute()
{
......@@ -314,6 +343,7 @@ namespace selx
// TODO: see if signals-and-slots paradigm is appropriate here.
this->RunRegistrations();
this->ReconnectTransforms();
this->AfterRegistrations();
//update all writers...
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment