Skip to content

Commit

Permalink
ENH: Add ElastixFilter support for initial transform parameter file
Browse files Browse the repository at this point in the history
  • Loading branch information
kaspermarstal committed Feb 3, 2016
1 parent 46f84de commit a6e8f10
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 40 deletions.
12 changes: 8 additions & 4 deletions src/Core/Main/elxElastixFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@
namespace elastix
{

template< typename TFixedImage,
typename TMovingImage >
template< typename TFixedImage, typename TMovingImage >
class ElastixFilter : public itk::ImageSource< TFixedImage >
{
public:
Expand Down Expand Up @@ -92,9 +91,14 @@ class ElastixFilter : public itk::ImageSource< TFixedImage >

void SetParameterObject( ParameterObjectPointer parameterObject );
ParameterObjectPointer GetParameterObject( void );

ParameterObjectPointer GetTransformParameterObject( void );

// TODO: Elastix does not have the option to get initial transform directly,
// but internally reads the file from a path in the ArgumentMap
itkSetMacro( InitialTransformParameterFileName, std::string );
itkGetConstMacro( InitialTransformParameterFileName, std::string );
void RemoveInitialTransformParameterFileName( void ) { this->SetInitialTransformParameterFileName( std::string() ); };

itkSetMacro( FixedPointSetFileName, std::string );
itkGetConstMacro( FixedPointSetFileName, std::string );
void RemoveFixedPointSetFileName( void ) { this->SetFixedPointSetFileName( std::string() ); };
Expand All @@ -111,7 +115,6 @@ class ElastixFilter : public itk::ImageSource< TFixedImage >
{
this->m_LogFileName = logFileName;
this->LogToFileOn();
this->Modified();
}

itkGetConstMacro( LogFileName, std::string );
Expand Down Expand Up @@ -152,6 +155,7 @@ class ElastixFilter : public itk::ImageSource< TFixedImage >
DataObjectContainerPointer m_FixedMaskContainer;
DataObjectContainerPointer m_MovingMaskContainer;

std::string m_InitialTransformParameterFileName;
std::string m_FixedPointSetFileName;
std::string m_MovingPointSetFileName;

Expand Down
79 changes: 44 additions & 35 deletions src/Core/Main/elxElastixFilter.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ ElastixFilter< TFixedImage, TMovingImage >
this->m_FixedImageContainer = DataObjectContainerType::New();
this->m_MovingImageContainer = DataObjectContainerType::New();

this->m_FixedPointSetFileName = std::string();
this->m_MovingPointSetFileName = std::string();
this->m_FixedPointSetFileName = "";
this->m_MovingPointSetFileName = "";

this->m_OutputDirectory = ".";
this->m_LogFileName = std::string();
this->m_LogFileName = "";

this->LogToConsoleOff();
this->LogToFileOff();
Expand All @@ -63,7 +63,7 @@ ElastixFilter< TFixedImage, TMovingImage >
DataObjectContainerPointer fixedMaskContainer = 0;
DataObjectContainerPointer movingMaskContainer = 0;
DataObjectContainerPointer resultImageContainer = 0;
ParameterMapVectorType TransformParameterMapVector;
ParameterMapVectorType transformParameterMapVector;
FlatDirectionCosinesType fixedImageOriginalDirection;

// Split inputs into separate containers
Expand Down Expand Up @@ -108,14 +108,46 @@ ElastixFilter< TFixedImage, TMovingImage >
}
}

// Set ParameterMap
ParameterObjectConstPointer parameterObject = static_cast< const ParameterObject* >( this->GetInput( "ParameterObject" ) );
ParameterMapVectorType parameterMapVector = parameterObject->GetParameterMap();

if( parameterMapVector.size() == 0 )
{
itkExceptionMacro( "Empty parameter map in parameter object." );
}

// Elastix must always write result image to guarantee that the ITK pipeline is in a consistent state
parameterMapVector[ parameterMapVector.size()-1 ][ "WriteResultImage" ] = ParameterValueVectorType( 1, "true" );

ArgumentMapType argumentMap;

// Initial transform
if( !this->m_InitialTransformParameterFileName.empty() )
{
argumentMap.insert( ArgumentMapEntryType( "-t0", this->m_InitialTransformParameterFileName ) );
}

// Fixed mesh
if( !this->m_FixedPointSetFileName.empty() )
{
argumentMap.insert( ArgumentMapEntryType( "-fp", this->m_FixedPointSetFileName ) );
}

// Moving mesh
if( !this->m_MovingPointSetFileName.empty() )
{
argumentMap.insert( ArgumentMapEntryType( "-mp", this->m_MovingPointSetFileName ) );
}

// Logging, disk I/O
if( this->GetOutputDirectory().empty() ) {
if( this->GetLogToFile() )
{
itkExceptionMacro( "LogToFileOn() requires an output directory to be specified.")
}

// There must be an "-out", this is checked later in the code
// There must be an "-out" as this is checked later in the code
argumentMap.insert( ArgumentMapEntryType( "-out", "output_path_not_set" ) );
}
else
Expand All @@ -133,18 +165,6 @@ ElastixFilter< TFixedImage, TMovingImage >
argumentMap.insert( ArgumentMapEntryType( "-out", this->GetOutputDirectory() ) );
}

// Fixed mesh
if( !this->m_FixedPointSetFileName.empty() )
{
argumentMap.insert( ArgumentMapEntryType( "-fp", std::string( this->m_FixedPointSetFileName ) ) );
}

// Moving mesh
if( !this->m_MovingPointSetFileName.empty() )
{
argumentMap.insert( ArgumentMapEntryType( "-mp", std::string( this->m_MovingPointSetFileName ) ) );
}

// Setup xout
std::string logFileName;
if( this->GetLogToFile() )
Expand All @@ -164,18 +184,6 @@ ElastixFilter< TFixedImage, TMovingImage >
itkExceptionMacro( "Error while setting up xout" );
}

// Get ParameterMap
ParameterObjectConstPointer parameterObject = static_cast< const ParameterObject* >( this->GetInput( "ParameterObject" ) );
ParameterMapVectorType parameterMapVector = parameterObject->GetParameterMap();

if( parameterMapVector.size() == 0 )
{
itkExceptionMacro( "Empty parameter map in parameter object." );
}

// Elastix must always write result image to guarantee that the ITK pipeline is in a consistent state
parameterMapVector[ parameterMapVector.size()-1 ][ "WriteResultImage" ] = ParameterValueVectorType( 1, "true" );

// Run the (possibly multiple) registration(s)
for( unsigned int i = 0; i < parameterMapVector.size(); ++i )
{
Expand Down Expand Up @@ -229,14 +237,14 @@ ElastixFilter< TFixedImage, TMovingImage >
resultImageContainer = elastix->GetResultImageContainer();
fixedImageOriginalDirection = elastix->GetOriginalFixedImageDirectionFlat();

TransformParameterMapVector.push_back( elastix->GetTransformParametersMap() );
transformParameterMapVector.push_back( elastix->GetTransformParametersMap() );

// Set initial transform to an index number instead of a parameter filename
if( i > 0 )
{
std::stringstream index;
index << ( i - 1 );
TransformParameterMapVector[ i ][ "InitialTransformParametersFileName" ][ 0 ] = index.str();
transformParameterMapVector[ i ][ "InitialTransformParametersFileName" ][ 0 ] = index.str();
}
} // End loop over registrations

Expand All @@ -247,22 +255,23 @@ ElastixFilter< TFixedImage, TMovingImage >
}

// Save parameter map
ParameterObject::Pointer TransformParameterObject = ParameterObject::New();
TransformParameterObject->SetParameterMap( TransformParameterMapVector );
this->SetOutput( "TransformParameterObject", static_cast< itk::DataObject* >( TransformParameterObject ) );
ParameterObject::Pointer transformParameterObject = ParameterObject::New();
transformParameterObject->SetParameterMap( transformParameterMapVector );
this->SetOutput( "TransformParameterObject", static_cast< itk::DataObject* >( transformParameterObject ) );

// Close the modules
ElastixMainType::UnloadComponents();
}

// TODO: We should not have to overwrite the ProcessObject's GetOutput()
// but upstream the filter is not updated without it. This is a bug.
// but the upstream filter is not updated without it. This is a bug.
template< typename TFixedImage, typename TMovingImage >
typename ElastixFilter< TFixedImage, TMovingImage >::FixedImagePointer
ElastixFilter< TFixedImage, TMovingImage >
::GetOutput( void )
{
this->Update();

return static_cast< TFixedImage* >( itk::ProcessObject::GetPrimaryOutput() );
}

Expand Down
30 changes: 30 additions & 0 deletions src/Core/Main/elxParameterObject.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,33 @@ ::GetParameterMap( const std::string transformName, const unsigned int numberOfR
} // namespace elastix

#endif // elxParameterObject_cxx

// http://stackoverflow.com/questions/9670396/exception-handling-and-opening-a-file
// TODO: Implement exception handling for parameter file reader/writer, rethrow itk exception
// int main () {
// ifstream file;
// file.exceptions ( ifstream::failbit | ifstream::badbit );
// try {
// file.open ("test.txt");
// while (!file.eof()) file.get();
// }
// catch ( ifstream::failure e ) {
// cout << "Exception opening/reading file";
// }
// file.close();
// return 0;
// }

// int main () {
// ofstream file;
// file.exceptions ( ofstream::failbit | ofstream::badbit | ofstream::failure );
// try {
// file.open ("test.txt");
// while (!file.eof()) file.get();
// }
// catch (ifstream::failure e) {
// cout << "Exception opening/reading file";
// }
// file.close();
// return 0;
// }
1 change: 1 addition & 0 deletions src/Core/Main/elxParameterObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class ParameterObject : public itk::DataObject
typedef std::string ParameterKeyType;
typedef std::string ParameterValueType;
typedef std::vector< ParameterValueType > ParameterValueVectorType;
typedef ParameterValueVectorType::iterator ParameterValueVectorIterator;
typedef std::map< ParameterKeyType, ParameterValueVectorType > ParameterMapType;
typedef ParameterMapType::iterator ParameterMapIterator;
typedef ParameterMapType::const_iterator ParameterMapConstIterator;
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Main/elxTransformixFilter.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ template< typename TInputImage >
TransformixFilter< TInputImage >
::TransformixFilter( void )
{
this->AddRequiredInputName( "TransformParameterObject");
this->AddRequiredInputName( "TransformParameterObject" );

this->SetPrimaryInputName( "InputImage" );
this->SetPrimaryOutputName( "ResultImage" );
Expand Down

0 comments on commit a6e8f10

Please sign in to comment.