Commit 0f01d58d authored by Floris Berendsen's avatar Floris Berendsen
Browse files

ENH: WIP: split into Monolithic Elastix and Monolithic Transformix

parent 73121b3b
......@@ -92,7 +92,7 @@ selxmodule_enable( ModuleExamples )
selxmodule_enable( ModuleSinksAndSources )
selxmodule_enable( ModuleItkSmoothingRecursiveGaussianImageFilter )
selxmodule_enable( ModuleItkImageRegistrationMethodv4 )
selxmodule_enable( ModuleElastixComponent )
selxmodule_enable( ModuleElastix )
selxmodule_enable( ModuleController )
#selxmodule_enable( ModuleCommandLine )
include(${CMAKE_SOURCE_DIR}/Modules/CommandLine/CommandLine.cmake)
......
......@@ -17,7 +17,7 @@
#
#=========================================================================
set( MODULE ModuleElastixComponent )
set( MODULE ModuleElastix )
# If OpenMP is supported by this machine, elastix will be compiled with
# OpenMP flags, and we need to add them here as well
......@@ -63,6 +63,8 @@ set( ${MODULE}_TESTS
# Module source files
set( ${MODULE}_SOURCE_FILES
${${MODULE}_SOURCE_DIR}/src/selxElastixComponent.cxx
${${MODULE}_SOURCE_DIR}/src/selxMonolithicElastix.cxx
${${MODULE}_SOURCE_DIR}/src/selxMonolithicTransformix.cxx
)
# Compile library
......
/*=========================================================================
*
* Copyright Leiden University Medical Center, Erasmus University Medical
* Center and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#ifndef selxMonolithicElastixComponent_h
#define selxMonolithicElastixComponent_h
#include "ComponentBase.h"
#include "Interfaces.h"
#include "itkImageSource.h"
#include "elxElastixFilter.h"
#include "elxParameterObject.h"
#include "elxTransformixFilter.h"
#include <string.h>
#include "selxMacro.h"
namespace selx
{
template <int Dimensionality, class TPixel>
class MonolithicElastixComponent :
public Implements<
Accepting<
itkImageFixedInterface<Dimensionality, TPixel>,
itkImageMovingInterface<Dimensionality, TPixel>
>,
Providing<
elastixTransformParameterObjectInterface<itk::Image<TPixel, Dimensionality>, itk::Image<TPixel, Dimensionality>>,
itkImageInterface<Dimensionality, TPixel>,
RunRegistrationInterface
>
>
{
public:
selxNewMacro(MonolithicElastixComponent, ComponentBase);
//itkStaticConstMacro(Dimensionality, unsigned int, Dimensionality);
MonolithicElastixComponent();
virtual ~MonolithicElastixComponent();
typedef typename ComponentBase::CriterionType CriterionType;
typedef TPixel PixelType;
// the in and output image type of the component are chosen to be the same
typedef itk::Image<PixelType, Dimensionality> ConnectionImageType;
// fixed and moving image types are all the same, these aliases can be used to be explicit.
typedef itk::Image<PixelType, Dimensionality> FixedImageType;
typedef itk::Image<PixelType, Dimensionality> MovingImageType;
typedef typename ConnectionImageType::Pointer ItkImagePointer;
typedef elastix::ElastixFilter< FixedImageType, MovingImageType > ElastixFilterType;
typedef elastix::ParameterObject elxParameterObjectType;
typedef elxParameterObjectType::Pointer elxParameterObjectPointer;
typedef typename elastixTransformParameterObjectInterface::elastixTransformParameterObject elastixTransformParameterObject;
// Accepting Interfaces:
virtual int Set(itkImageFixedInterface<Dimensionality, TPixel>*) override;
virtual int Set(itkImageMovingInterface<Dimensionality, TPixel>*) override;
// Providing Interfaces:
virtual elastixTransformParameterObject* GetTransformParameterObject() override;
virtual ItkImagePointer GetItkImage() override;
virtual void RunRegistration() override;
virtual bool MeetsCriterion(const CriterionType &criterion) override;
static const char * GetDescription() { return "MonolithicElastix Component"; };
private:
typename ElastixFilterType::Pointer m_elastixFilter;
protected:
/* The following struct returns the string name of computation type */
/* default implementation */
static inline const std::string GetTypeNameString()
{
itkGenericExceptionMacro(<< "Unknown ScalarType" << typeid(TPixel).name());
// TODO: provide the user instructions how to enable the compilation of the component with the required template types (if desired)
// We might define an exception object that can communicate various error messages: for simple user, for developer user, etc
}
static inline const std::string GetPixelTypeNameString()
{
itkGenericExceptionMacro(<< "Unknown PixelType" << typeid(TPixel).name());
// TODO: provide the user instructions how to enable the compilation of the component with the required template types (if desired)
// We might define an exception object that can communicate various error messages: for simple user, for developer user, etc
}
};
// unfortunately partial specialization of member functions is not allowed, without partially specializing the entire class.
/*
template <int Dimensionality>
class MonolithicElastixComponent < Dimensionality, double >
{
static inline const std::string GetPixelTypeNameString();
};
template <int Dimensionality>
inline const std::string
MonolithicElastixComponent<Dimensionality, double>
::GetPixelTypeNameString()
{
return std::string("double");
}
*/
template <>
inline const std::string
MonolithicElastixComponent<2, float>
::GetPixelTypeNameString()
{
return std::string("float");
}
template <>
inline const std::string
MonolithicElastixComponent<2, double>
::GetPixelTypeNameString()
{
return std::string("double");
}
template <>
inline const std::string
MonolithicElastixComponent<3, float>
::GetPixelTypeNameString()
{
return std::string("float");
}
template <>
inline const std::string
MonolithicElastixComponent<3, double>
::GetPixelTypeNameString()
{
return std::string("double");
}
template <>
inline const std::string
MonolithicElastixComponent<2, float>
::GetTypeNameString()
{
return std::string("2_float");
}
template <>
inline const std::string
MonolithicElastixComponent<2, double>
::GetTypeNameString()
{
return std::string("2_double");
}
template <>
inline const std::string
MonolithicElastixComponent<3,float>
::GetTypeNameString()
{
return std::string("3_float");
}
template <>
inline const std::string
MonolithicElastixComponent<3,double>
::GetTypeNameString()
{
return std::string("3_double");
}
} //end namespace selx
#ifndef ITK_MANUAL_INSTANTIATION
#include "selxMonolithicElastix.hxx"
#endif
#endif // #define selxMonolithicElastix_h
\ No newline at end of file
/*=========================================================================
*
* Copyright Leiden University Medical Center, Erasmus University Medical
* Center and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#include "selxMonolithicElastix.h"
namespace selx
{
template<int Dimensionality, class TPixel>
MonolithicElastixComponent< Dimensionality, TPixel>::MonolithicElastixComponent()
{
m_elastixFilter = ElastixFilterType::New();
// TODO: Due to some issues with Criteria being propagated as elastix settings, I need to empty the selxparameterObject.
elxParameterObjectPointer elxParameterObject = elxParameterObjectType::New();
typename elxParameterObjectType::ParameterMapType defaultParameters = elxParameterObject->GetDefaultParameterMap("rigid");
elxParameterObject->SetParameterMap(defaultParameters);
m_elastixFilter->SetParameterObject(elxParameterObject);
m_elastixFilter->LogToConsoleOn();
m_elastixFilter->LogToFileOff();
m_elastixFilter->SetOutputDirectory(".");
}
template<int Dimensionality, class TPixel>
MonolithicElastixComponent< Dimensionality, TPixel>::~MonolithicElastixComponent()
{
}
template<int Dimensionality, class TPixel>
int MonolithicElastixComponent< Dimensionality, TPixel>::Set(itkImageFixedInterface<Dimensionality, TPixel>* component)
{
auto fixedImage = component->GetItkImageFixed();
// connect the itk pipeline
this->m_elastixFilter->SetFixedImage(fixedImage);
return 0;
}
template<int Dimensionality, class TPixel>
int MonolithicElastixComponent< Dimensionality, TPixel>::Set(itkImageMovingInterface<Dimensionality, TPixel>* component)
{
auto movingImage = component->GetItkImageMoving();
// connect the itk pipeline
this->m_elastixFilter->SetMovingImage(movingImage);
return 0;
}
template<int Dimensionality, class TPixel>
typename MonolithicElastixComponent< Dimensionality, TPixel>::ItkImagePointer MonolithicElastixComponent< Dimensionality, TPixel>::GetItkImage()
{
return this->m_elastixFilter->GetOutput();
}
template<int Dimensionality, class TPixel>
typename MonolithicElastixComponent< Dimensionality, TPixel>::elastixTransformParameterObject* MonolithicElastixComponent< Dimensionality, TPixel>::GetTransformParameterObject()
{
return this->m_elastixFilter->GetTransformParameterObject();
}
template<int Dimensionality, class TPixel>
void MonolithicElastixComponent< Dimensionality, TPixel>::RunRegistration(void)
{
this->m_elastixFilter->Update();
}
template<int Dimensionality, class TPixel>
bool
MonolithicElastixComponent< Dimensionality, TPixel>
::MeetsCriterion(const CriterionType &criterion)
{
bool hasUndefinedCriteria(false);
bool meetsCriteria(false);
if (criterion.first == "ComponentProperty")
{
meetsCriteria = true;
for (auto const & criterionValue : criterion.second) // auto&& preferred?
{
if (criterionValue != "SomeProperty") // e.g. "GradientDescent", "SupportsSparseSamples
{
meetsCriteria = false;
}
}
}
else if (criterion.first == "Dimensionality") //Supports this?
{
meetsCriteria = true;
for (auto const & criterionValue : criterion.second) // auto&& preferred?
{
if (std::stoi(criterionValue) != Dimensionality)
{
meetsCriteria = false;
}
}
}
else if (criterion.first == "PixelType") //Supports this?
{
meetsCriteria = true;
for (auto const & criterionValue : criterion.second) // auto&& preferred?
{
if (criterionValue != Self::GetPixelTypeNameString())
{
meetsCriteria = false;
}
}
}
else if (criterion.first == "RegistrationPreset") //Supports this?
{
// Temporary solution: RegistrationPreset: rigid, nonrigid, etc overwrite the current selxparameterObject.
// Warning: the order of Criteria matters, since selxparameterObject may be overwritten
// Warning: this probably fails because the Criteria map entries are processed in arbitrary order.
elxParameterObjectPointer elxParameterObject = elxParameterObjectType::New();
meetsCriteria = true;
for (auto const & presetName : criterion.second) // auto&& preferred?
{
typename elxParameterObjectType::ParameterMapType presetParameters = elxParameterObject->GetDefaultParameterMap(presetName);
elxParameterObject->SetParameterMap(presetParameters);
try
{
this->m_elastixFilter->SetParameterObject(elxParameterObject);
}
catch (itk::ExceptionObject & err)
{
std::cout << err;
//TODO log the error message?
meetsCriteria = false;
}
}
}
else
{
// temporary solution: pass all SuperMonolithicElastixComponent parameters as is to elastix. This should be defined in deeper hierarchy of the criteria, but for now we have a flat mapping only.
elxParameterObjectPointer elxParameterObject = this->m_elastixFilter->GetParameterObject();
typename elxParameterObjectType::ParameterMapType newParameterMap = elxParameterObject->GetParameterMap(0); //copy const paramtermap to a non const map
newParameterMap[criterion.first] = criterion.second; //overwrite element
elxParameterObjectPointer newParameterObject = elxParameterObjectType::New();
newParameterObject->SetParameterMap(newParameterMap);
this->m_elastixFilter->SetParameterObject(newParameterObject);
meetsCriteria = true;
}
return meetsCriteria;
}
} //end namespace selx
/*=========================================================================
*
* Copyright Leiden University Medical Center, Erasmus University Medical
* Center and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*=========================================================================*/
#ifndef selxMonolithicTransformixComponent_h
#define selxMonolithicTransformixComponent_h
#include "ComponentBase.h"
#include "Interfaces.h"
#include "itkImageSource.h"
#include "elxElastixFilter.h"
#include "elxParameterObject.h"
#include "elxTransformixFilter.h"
#include <string.h>
#include "selxMacro.h"
namespace selx
{
template <int Dimensionality, class TPixel>
class MonolithicTransformixComponent :
public Implements<
Accepting<
itkImageDomainFixedInterface<Dimensionality>,
itkImageMovingInterface<Dimensionality, TPixel>,
elastixTransformParameterObjectInterface<itk::Image<TPixel, Dimensionality>, itk::Image<TPixel, Dimensionality>>
>,
Providing<
itkImageInterface<Dimensionality, TPixel>,
ReconnectTransformInterface
>
>
{
public:
selxNewMacro(MonolithicTransformixComponent, ComponentBase);
//itkStaticConstMacro(Dimensionality, unsigned int, Dimensionality);
MonolithicTransformixComponent();
virtual ~MonolithicTransformixComponent();
typedef typename ComponentBase::CriterionType CriterionType;
typedef TPixel PixelType;
// fixed and moving image types are all the same, these aliases can be used to be explicit.
typedef typename itkImageMovingInterface<Dimensionality, TPixel>::ItkImageType MovingImageType;
typedef typename itkImageInterface<Dimensionality, TPixel>::ItkImageType ResultImageType;
typedef elastix::ParameterObject elxParameterObjectType;
typedef elxParameterObjectType::Pointer elxParameterObjectPointer;
typedef elastix::TransformixFilter<MovingImageType> TransformixFilterType;
typedef elastixTransformParameterObjectInterface<itk::Image<TPixel, Dimensionality>, itk::Image<TPixel, Dimensionality>> elastixTransformParameterObjectInterfaceType;
// Accepting Interfaces:
virtual int Set(itkImageDomainFixedInterface<Dimensionality>*) override;
virtual int Set(itkImageMovingInterface<Dimensionality, TPixel>*) override;
virtual int Set(elastixTransformParameterObjectInterfaceType*) override;
// Providing Interfaces:
virtual typename ResultImageType::Pointer GetItkImage() override;
virtual void ReconnectTransform() override;
virtual bool MeetsCriterion(const CriterionType &criterion) override;
static const char * GetDescription() { return "MonolithicTransformix Component"; };
private:
typename TransformixFilterType::Pointer m_transformixFilter;
elastixTransformParameterObjectInterfaceType* m_TransformParameterObjectInterface;
protected:
/* The following struct returns the string name of computation type */
/* default implementation */
static inline const std::string GetTypeNameString()
{
itkGenericExceptionMacro(<< "Unknown ScalarType" << typeid(TPixel).name());
// TODO: provide the user instructions how to enable the compilation of the component with the required template types (if desired)
// We might define an exception object that can communicate various error messages: for simple user, for developer user, etc
}
static inline const std::string GetPixelTypeNameString()
{
itkGenericExceptionMacro(<< "Unknown PixelType" << typeid(TPixel).name());
// TODO: provide the user instructions how to enable the compilation of the component with the required template types (if desired)
// We might define an exception object that can communicate various error messages: for simple user, for developer user, etc
}
};
// unfortunately partial specialization of member functions is not allowed, without partially specializing the entire class.
/*
template <int Dimensionality>
class MonolithicTransformixComponent < Dimensionality, double >
{
static inline const std::string GetPixelTypeNameString();
};
template <int Dimensionality>
inline const std::string
MonolithicTransformixComponent<Dimensionality, double>
::GetPixelTypeNameString()
{
return std::string("double");
}
*/
template <>
inline const std::string
MonolithicTransformixComponent<2, float>
::GetPixelTypeNameString()
{
return std::string("float");
}
template <>
inline const std::string
MonolithicTransformixComponent<2, double>
::GetPixelTypeNameString()
{
return std::string("double");
}
template <>
inline const std::string
MonolithicTransformixComponent<3, float>
::GetPixelTypeNameString()
{
return std::string("float");
}
template <>
inline const std::string
MonolithicTransformixComponent<3, double>
::GetPixelTypeNameString()
{
return std::string("double");
}
template <>
inline const std::string
MonolithicTransformixComponent<2, float>
::GetTypeNameString()
{
return std::string("2_float");
}
template <>
inline const std::string
MonolithicTransformixComponent<2, double>
::GetTypeNameString()
{
return std::string("2_double");
}
template <>
inline const std::string
MonolithicTransformixComponent<3,float>
::GetTypeNameString()
{
return std::string("3_float");
}
template <>
inline const std::string
MonolithicTransformixComponent<3,double>
::GetTypeNameString()
{
return std::string("3_double");
}
} //end namespace selx
#ifndef ITK_MANUAL_INSTANTIATION
#include "selxMonolithicTransformix.hxx"
#endif
#endif // #define GDOptimizer3rdPartyComponent_h
\ No newline at end of file
/*=========================================================================
*
* Copyright Leiden University Medical Center, Erasmus University Medical
* Center and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0.txt
*
* Unless required by applicable law or agreed to in writing, software