Commit fc99630c authored by Floris Berendsen's avatar Floris Berendsen
Browse files

ENH: SuperElastix\SuperElastix#25 refactored NetworkBuilder into a Base

class and derived templated class to have static/typed control over the
Components to be registered. Aim: remove the use of the global itk object
factory
parent dd6fe8ee
......@@ -20,6 +20,7 @@
#ifndef NetworkBuilder_h
#define NetworkBuilder_h
#include "selxNetworkBuilderBase.h"
#include "selxAnyFileReader.h"
#include "selxAnyFileWriter.h"
......@@ -40,11 +41,16 @@
namespace selx
{
class NetworkBuilder
template<class ComponentList>
class NetworkBuilder : public NetworkBuilderBase
{
// TODO: Its output should be a (light weight) ComponentContainer with 1 Execute button. All other data such as graphs and selectors can be deleted.
// The NetworkBuilder takes care of the at run time realization of the algorithm network that is described by the Blueprint.
// The output, GetRealizedNetwork(), is a (light weight) ComponentContainer with 1 Execute button that is self-contained to run the registration algorithm.
// After obtaining the RealizedNetwork(), the NetworkBuilder object can be deleted in order to free memory, releasing all internal/intermediate data of the configuration process.
public:
typedef Blueprint::ComponentNameType ComponentNameType;
typedef std::map<
std::string, SourceInterface * > SourceInterfaceMapType;
......@@ -56,51 +62,49 @@ public:
NetworkBuilder( std::shared_ptr< Blueprint > blueprint );
NetworkBuilder( Blueprint * blueprint );
~NetworkBuilder() {}
NetworkBuilder();
virtual ~NetworkBuilder() = default;
/** Read configuration at the blueprints nodes and edges and return true if all components could be uniquely selected*/
bool Configure();
virtual bool Configure();
/** if all components are uniquely selected, they can be connected */
bool ConnectComponents();
virtual bool ConnectComponents();
NetworkContainer GetRealizedNetwork();
virtual NetworkContainer GetRealizedNetwork();
SourceInterfaceMapType GetSourceInterfaces();
virtual SourceInterfaceMapType GetSourceInterfaces();
SinkInterfaceMapType GetSinkInterfaces();
virtual SinkInterfaceMapType GetSinkInterfaces();
AnyFileReader::Pointer GetInputFileReader( const ComponentNameType & );
virtual AnyFileReader::Pointer GetInputFileReader(const ComponentNameType &);
AnyFileWriter::Pointer GetOutputFileWriter( const ComponentNameType & );
virtual AnyFileWriter::Pointer GetOutputFileWriter(const ComponentNameType &);
SinkInterface::DataObjectPointer GetInitializedOutput( const NetworkBuilder::ComponentNameType & );
virtual SinkInterface::DataObjectPointer GetInitializedOutput(const NetworkBuilderBase::ComponentNameType &);
protected:
private:
typedef ComponentBase::CriteriaType CriteriaType;
typedef ComponentBase::CriterionType CriterionType;
typedef ComponentBase::ParameterValueType ParameterValueType;
typedef ComponentSelector::Pointer ComponentSelectorPointer;
typedef Blueprint::ComponentNamesType ComponentNamesType;
typedef std::map< ComponentNameType, ComponentSelectorPointer > ComponentSelectorContainerType;
typedef ComponentSelectorContainerType::iterator ComponentSelectorIteratorType;
/** Read configuration at the blueprints nodes and try to find instantiated components */
void ApplyComponentConfiguration();
virtual void ApplyComponentConfiguration();
/** Read configuration at the blueprints edges and try to find instantiated components */
void ApplyConnectionConfiguration();
virtual void ApplyConnectionConfiguration();
/** For all uniquely selected components test handshake to non-uniquely selected components */
void PropagateConnectionsWithUniqueComponents();
virtual void PropagateConnectionsWithUniqueComponents();
/** See which components need more configuration criteria */
ComponentNamesType GetNonUniqueComponentNames();
virtual ComponentNamesType GetNonUniqueComponentNames();
//TODO make const correct
//NetworkBuilder should be constructed with a blueprint.
......@@ -111,7 +115,14 @@ private:
// A selector for each node, that each can hold multiple instantiated components. Ultimately is should be 1 component each.
ComponentSelectorContainerType m_ComponentSelectorContainer;
bool m_isConfigured;
private:
};
} // end namespace selx
#ifndef ITK_MANUAL_INSTANTIATION
#include "selxNetworkBuilder.hxx"
#endif
#endif // NetworkBuilder_h
......@@ -23,16 +23,19 @@
namespace selx
{
NetworkBuilder::NetworkBuilder( std::shared_ptr< Blueprint > blueprint ) : m_Blueprint( blueprint ), m_isConfigured(false )
template< typename ComponentList >
NetworkBuilder<ComponentList>::NetworkBuilder(std::shared_ptr< Blueprint > blueprint) : m_Blueprint(blueprint), m_isConfigured(false)
{
}
NetworkBuilder::NetworkBuilder( Blueprint * blueprint ) : m_Blueprint( blueprint ), m_isConfigured( false )
template< typename ComponentList >
NetworkBuilder<ComponentList>::NetworkBuilder(Blueprint * blueprint) : m_Blueprint(blueprint), m_isConfigured(false)
{
}
template< typename ComponentList >
bool
NetworkBuilder::Configure()
NetworkBuilder<ComponentList>::Configure()
{
// Instantiates all the components as described in the blueprint. Returns true
// if all components could be uniquely selected.
......@@ -91,9 +94,9 @@ NetworkBuilder::Configure()
return true;
}
NetworkBuilder::ComponentNamesType
NetworkBuilder::GetNonUniqueComponentNames()
template< typename ComponentList >
NetworkBuilderBase::ComponentNamesType
NetworkBuilder<ComponentList>::GetNonUniqueComponentNames()
{
ComponentNamesType nonUniqueComponentNames;
const Blueprint::ComponentNamesType componentNames = m_Blueprint->GetComponentNames();
......@@ -113,9 +116,9 @@ NetworkBuilder::GetNonUniqueComponentNames()
return nonUniqueComponentNames;
}
template< typename ComponentList >
void
NetworkBuilder::ApplyComponentConfiguration()
NetworkBuilder<ComponentList>::ApplyComponentConfiguration()
{
// Creates a ComponentSelector for each node of the graph and apply
// the criteria/properties at each node to narrow the Component selection.
......@@ -179,9 +182,9 @@ NetworkBuilder::ApplyComponentConfiguration()
return;
}
template< typename ComponentList >
void
NetworkBuilder::ApplyConnectionConfiguration()
NetworkBuilder<ComponentList>::ApplyConnectionConfiguration()
{
// Read the criteria/properties at each Connection and narrow the selection of
// components.
......@@ -239,9 +242,9 @@ NetworkBuilder::ApplyConnectionConfiguration()
return;
}
template< typename ComponentList >
void
NetworkBuilder::PropagateConnectionsWithUniqueComponents()
NetworkBuilder<ComponentList>::PropagateConnectionsWithUniqueComponents()
{
// Narrow down the selection of non-uniquely selected components by finding all
// connections to a component that is uniquely selected and verifying the matching interface types.
......@@ -322,8 +325,9 @@ NetworkBuilder::PropagateConnectionsWithUniqueComponents()
}
}
template< typename ComponentList >
bool
NetworkBuilder::ConnectComponents()
NetworkBuilder<ComponentList>::ConnectComponents()
{
bool isAllSuccess = true;
......@@ -365,9 +369,9 @@ NetworkBuilder::ConnectComponents()
return isAllSuccess;
}
NetworkBuilder::SourceInterfaceMapType
NetworkBuilder::GetSourceInterfaces()
template< typename ComponentList >
NetworkBuilderBase::SourceInterfaceMapType
NetworkBuilder<ComponentList>::GetSourceInterfaces()
{
/** Scans all Components to find those with Sourcing capability and store them in SourceComponents list */
......@@ -389,9 +393,9 @@ NetworkBuilder::GetSourceInterfaces()
return sourceInterfaceMap;
}
NetworkBuilder::SinkInterfaceMapType
NetworkBuilder::GetSinkInterfaces()
template< typename ComponentList >
NetworkBuilderBase::SinkInterfaceMapType
NetworkBuilder<ComponentList>::GetSinkInterfaces()
{
/** Scans all Components to find those with Sinking capability and store them in SinkComponents list */
......@@ -412,8 +416,9 @@ NetworkBuilder::GetSinkInterfaces()
return sinkInterfaceMap;
}
template< typename ComponentList >
AnyFileReader::Pointer
NetworkBuilder::GetInputFileReader( const NetworkBuilder::ComponentNameType & inputName )
NetworkBuilder<ComponentList>::GetInputFileReader(const NetworkBuilderBase::ComponentNameType & inputName)
{
SourceInterfaceMapType sources = this->GetSourceInterfaces();
if( sources.count( inputName ) != 1 )
......@@ -426,9 +431,9 @@ NetworkBuilder::GetInputFileReader( const NetworkBuilder::ComponentNameType & in
return sources[ inputName ]->GetInputFileReader();
}
template< typename ComponentList >
AnyFileWriter::Pointer
NetworkBuilder::GetOutputFileWriter( const NetworkBuilder::ComponentNameType & outputName )
NetworkBuilder<ComponentList>::GetOutputFileWriter(const NetworkBuilderBase::ComponentNameType & outputName)
{
SinkInterfaceMapType sinks = this->GetSinkInterfaces();
if( sinks.count( outputName ) != 1 )
......@@ -441,9 +446,9 @@ NetworkBuilder::GetOutputFileWriter( const NetworkBuilder::ComponentNameType & o
return sinks[ outputName ]->GetOutputFileWriter();
}
template< typename ComponentList >
SinkInterface::DataObjectPointer
NetworkBuilder::GetInitializedOutput( const NetworkBuilder::ComponentNameType & outputName )
NetworkBuilder<ComponentList>::GetInitializedOutput(const NetworkBuilderBase::ComponentNameType & outputName)
{
SinkInterfaceMapType sinks = this->GetSinkInterfaces();
if( sinks.count( outputName ) != 1 )
......@@ -456,8 +461,9 @@ NetworkBuilder::GetInitializedOutput( const NetworkBuilder::ComponentNameType &
return sinks[ outputName ]->GetInitializedOutput();
}
template< typename ComponentList >
NetworkContainer
NetworkBuilder::GetRealizedNetwork()
NetworkBuilder<ComponentList>::GetRealizedNetwork()
{
// vector that stores all components
std::vector<ComponentBase::Pointer> components;
......
/*=========================================================================
*
* 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 NetworkBuilderBase_h
#define NetworkBuilderBase_h
#include "selxAnyFileReader.h"
#include "selxAnyFileWriter.h"
#include <list>
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <map>
#include "selxMacro.h"
#include "selxBlueprint.h"
#include "selxNetworkContainer.h"
#include "selxComponentFactory.h"
#include "selxInterfaces.h"
#include "selxInterfaceTraits.h"
namespace selx
{
class NetworkBuilderBase
{
// The NetworkBuilderBase takes care of the at run time realization of the algorithm network that is described by the Blueprint.
// The output, GetRealizedNetwork(), is a (light weight) ComponentContainer with 1 Execute button that is self-contained to run the registration algorithm.
// After obtaining the RealizedNetwork(), the NetworkBuilderBase object can be deleted in order to free memory, releasing all internal/intermediate data of the configuration process.
public:
typedef Blueprint::ComponentNameType ComponentNameType;
typedef Blueprint::ComponentNamesType ComponentNamesType;
typedef std::map<
std::string, SourceInterface * > SourceInterfaceMapType;
typedef std::map<
std::string, SinkInterface * > SinkInterfaceMapType;
typedef std::map<
std::string, RegistrationControllerStartInterface * > RegistrationControllerStartInterfaceMapType;
typedef Blueprint::ComponentNamesType ComponentNamesType;
virtual ~NetworkBuilderBase() = default;
/** Read configuration at the blueprints nodes and edges and return true if all components could be uniquely selected*/
virtual bool Configure() = 0;
/** if all components are uniquely selected, they can be connected */
virtual bool ConnectComponents() = 0;
virtual NetworkContainer GetRealizedNetwork() = 0;
virtual SourceInterfaceMapType GetSourceInterfaces() = 0;
virtual SinkInterfaceMapType GetSinkInterfaces() = 0;
virtual AnyFileReader::Pointer GetInputFileReader(const ComponentNameType &) = 0;
virtual AnyFileWriter::Pointer GetOutputFileWriter(const ComponentNameType &) = 0;
virtual SinkInterface::DataObjectPointer GetInitializedOutput(const NetworkBuilderBase::ComponentNameType &) = 0;
private:
};
} // end namespace selx
#endif // NetworkBuilderBase_h
......@@ -39,7 +39,7 @@ class NetworkBuilderTest : public ::testing::Test
{
public:
typedef std::unique_ptr< NetworkBuilder > NetworkBuilderPointer;
typedef std::unique_ptr< NetworkBuilderBase > NetworkBuilderPointer;
typedef std::shared_ptr< Blueprint > BlueprintPointer;
typedef Blueprint::ParameterMapType ParameterMapType;
typedef Blueprint::ParameterValueType ParameterValueType;
......@@ -83,12 +83,12 @@ public:
TEST_F( NetworkBuilderTest, Create )
{
NetworkBuilderPointer networkBuilder = NetworkBuilderPointer( new NetworkBuilder( new Blueprint() ) );
NetworkBuilderPointer networkBuilder = NetworkBuilderPointer( new NetworkBuilder<TypeList<>>( new Blueprint() ) );
}
TEST_F( NetworkBuilderTest, Configure )
{
NetworkBuilderPointer networkBuilder = NetworkBuilderPointer( new NetworkBuilder( blueprint ) );
NetworkBuilderPointer networkBuilder = NetworkBuilderPointer(new NetworkBuilder<TypeList<>>(blueprint));
bool allUniqueComponents;
EXPECT_NO_THROW( allUniqueComponents = networkBuilder->Configure() );
EXPECT_TRUE( allUniqueComponents );
......@@ -96,7 +96,7 @@ TEST_F( NetworkBuilderTest, Configure )
TEST_F( NetworkBuilderTest, Connect )
{
std::unique_ptr< NetworkBuilder > networkBuilder( new NetworkBuilder( blueprint ) );
std::unique_ptr< NetworkBuilderBase > networkBuilder(new NetworkBuilder<TypeList<>>(blueprint));
EXPECT_NO_THROW( bool allUniqueComponents = networkBuilder->Configure() );
bool success;
EXPECT_NO_THROW(success = networkBuilder->ConnectComponents());
......@@ -217,7 +217,7 @@ TEST_F( NetworkBuilderTest, DeduceComponentsFromConnections )
blueprint->SetConnection( "ResampleFilter", "Controller", { {} } ); //ReconnectTransformInterface
blueprint->SetConnection( "TransformDisplacementFilter", "Controller", { {} } ); //ReconnectTransformInterface
std::unique_ptr< NetworkBuilder > networkBuilder(new NetworkBuilder(blueprint));
std::unique_ptr< NetworkBuilderBase > networkBuilder(new NetworkBuilder<CustomRegisterComponents>(blueprint));
bool allUniqueComponents;
EXPECT_NO_THROW(allUniqueComponents = networkBuilder->Configure());
EXPECT_TRUE( allUniqueComponents );
......
......@@ -34,7 +34,7 @@
namespace selx
{
class NetworkBuilder; // forward declaration, hiding implementation details and speeding up compilation time (PIMPL idiom)
class NetworkBuilderBase; // forward declaration, hiding implementation details and speeding up compilation time (PIMPL idiom)
class SuperElastixFilter : public itk::ProcessObject
{
......@@ -116,7 +116,7 @@ private:
//TODO make const correct
BlueprintType::Pointer m_Blueprint;
std::unique_ptr< NetworkBuilder > m_NetworkBuilder;
std::unique_ptr< NetworkBuilderBase > m_NetworkBuilder;
bool m_InputConnectionModified;
bool m_OutputConnectionModified;
bool m_BlueprintConnectionModified;
......
......@@ -84,7 +84,7 @@ SuperElastixFilter
itkExceptionMacro(<< "Setting a Blueprint is required first.")
}
this->m_NetworkBuilder = std::unique_ptr< NetworkBuilder >(new NetworkBuilder(this->m_Blueprint->Get()));
this->m_NetworkBuilder = std::unique_ptr< NetworkBuilder<DefaultComponents> >(new NetworkBuilder<DefaultComponents>(this->m_Blueprint->Get()));
this->m_AllUniqueComponents = this->m_NetworkBuilder->Configure();
}
else if (this->m_BlueprintConnectionModified == true)
......@@ -95,7 +95,7 @@ SuperElastixFilter
if( ( m_InputConnectionModified == true ) || ( this->m_BlueprintConnectionModified == true ) )
{
auto usedInputs = this->GetInputNames();
NetworkBuilder::SourceInterfaceMapType sources = this->m_NetworkBuilder->GetSourceInterfaces();
NetworkBuilderBase::SourceInterfaceMapType sources = this->m_NetworkBuilder->GetSourceInterfaces();
for( const auto & nameAndInterface : sources )
{
auto foundIndex = std::find( usedInputs.begin(), usedInputs.end(), nameAndInterface.first );
......@@ -124,7 +124,7 @@ SuperElastixFilter
if( ( m_OutputConnectionModified == true ) || ( this->m_BlueprintConnectionModified == true ) )
{
auto usedOutputs = this->GetOutputNames();
NetworkBuilder::SinkInterfaceMapType sinks = this->m_NetworkBuilder->GetSinkInterfaces();
NetworkBuilderBase::SinkInterfaceMapType sinks = this->m_NetworkBuilder->GetSinkInterfaces();
for( const auto & nameAndInterface : sinks )
{
auto foundIndex = std::find( usedOutputs.begin(), usedOutputs.end(), nameAndInterface.first );
......@@ -162,7 +162,7 @@ SuperElastixFilter
if( ( m_OutputConnectionModified == true ) || ( this->m_BlueprintConnectionModified == true ) )
{
NetworkBuilder::SinkInterfaceMapType sinks = this->m_NetworkBuilder->GetSinkInterfaces();
NetworkBuilderBase::SinkInterfaceMapType sinks = this->m_NetworkBuilder->GetSinkInterfaces();
for( const auto & nameAndInterface : sinks )
{
// Update information: ask the mini pipeline what the size of the data will be
......@@ -220,7 +220,7 @@ SuperElastixFilter
{
itkExceptionMacro(<< "Setting a Blueprint is required first.")
}
this->m_NetworkBuilder = std::unique_ptr< NetworkBuilder >(new NetworkBuilder(this->m_Blueprint->Get()));
this->m_NetworkBuilder = std::unique_ptr< NetworkBuilder<DefaultComponents> >(new NetworkBuilder<DefaultComponents>(this->m_Blueprint->Get()));
this->m_AllUniqueComponents = this->m_NetworkBuilder->Configure();
}
if (!this->m_AllUniqueComponents)
......@@ -244,7 +244,7 @@ SuperElastixFilter
itkExceptionMacro(<< "Setting a Blueprint is required first.")
}
this->m_NetworkBuilder = std::unique_ptr< NetworkBuilder >(new NetworkBuilder(this->m_Blueprint->Get()));
this->m_NetworkBuilder = std::unique_ptr< NetworkBuilder<DefaultComponents> >(new NetworkBuilder<DefaultComponents>(this->m_Blueprint->Get()));
this->m_AllUniqueComponents = this->m_NetworkBuilder->Configure();
}
if (!this->m_AllUniqueComponents)
......@@ -283,7 +283,7 @@ SuperElastixFilter::OutputDataType
itkExceptionMacro(<< "Setting a Blueprint is required first.")
}
this->m_NetworkBuilder = std::unique_ptr< NetworkBuilder >(new NetworkBuilder(this->m_Blueprint->Get()));
this->m_NetworkBuilder = std::unique_ptr< NetworkBuilder<DefaultComponents> >(new NetworkBuilder<DefaultComponents>(this->m_Blueprint->Get()));
this->m_AllUniqueComponents = this->m_NetworkBuilder->Configure();
this->m_BlueprintConnectionModified = false;
}
......
......@@ -38,7 +38,6 @@ set( ${MODULE}_SOURCE_FILES
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/selxComponentBase.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/selxCheckTemplateProperties.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/selxNetworkContainer.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/selxNetworkBuilder.cxx
${${MODULE}_SOURCE_DIR}/ComponentInterface/src/selxComponentSelector.cxx
${${MODULE}_SOURCE_DIR}/ConfigurationReader/src/selxConfigurationReader.cxx
${${MODULE}_SOURCE_DIR}/Filter/src/selxSuperElastixFilter.cxx
......
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