diff --git a/CMake/elxComponent.cmake b/CMake/elxComponent.cmake new file mode 100644 index 0000000000000000000000000000000000000000..4fd04dfb6e043411fce6ac20509b97a215444347 --- /dev/null +++ b/CMake/elxComponent.cmake @@ -0,0 +1,10 @@ +macro( ElastixComponent COMPONENT ) + ElastixModuleCheckName( ${COMPONENT} ) + set( ELASTIX_COMPONENT_{$COMPONENT}_DEFINED TRUE ) +endmacro() + +macro( ElastixComponentCheckName COMPONENT ) + if( NOT "${_name}" MATCHES "^[a-zA-Z][a-zA-Z0-9]*$" ) + message( FATAL_ERROR "Invalid component name: ${COMPONENT}" ) + endif() +endmacro() \ No newline at end of file diff --git a/CMake/elxModules.cmake b/CMake/elxModules.cmake new file mode 100644 index 0000000000000000000000000000000000000000..1e4955cb693e7a071a8eb10779ca64149ea8ecba --- /dev/null +++ b/CMake/elxModules.cmake @@ -0,0 +1,82 @@ +# --------------------------------------------------------------------- +# Private helper macros + +macro( _elxmodule_check_name MODULE ) + if( NOT "${_name}" MATCHES "^[a-zA-Z_]*$" ) + message( FATAL_ERROR "Invalid module name: ${MODULE}" ) + endif() + + list( FIND ELXMODULE_ALL "${MODULE}" MODULE_FOUND ) + if( ${MODULE_FOUND} EQUAL -1 ) + message( FATAL_ERROR "Module not found: ${MODULE}") + endif() +endmacro() + +macro( _elxmodule_enable MODULE ) + _elxmodule_check_name( ${MODULE} ) + + if( NOT ${MODULE}_ENABLED ) + set( "${MODULE}_ENABLED" ON ) + + add_subdirectory( "${${MODULE}_SOURCE_DIR}" ) + + if( ${MODULE}_INCLUDE_DIRS ) + include_directories( ${${MODULE}_INCLUDE_DIRS} ) + endif() + + if( ${MODULE}_LIBRARIES ) + link_directories( ${${MODULE}_LIBRARY_DIR} ) + endif() + + if( ${${MODULE}_LIBRARIES} ) + list( APPEND ELASTIX_LIBRARIES + ${${MODULE}_LIBRARIES} + ) + endif() + + # TODO: Add recursive dependency walk + # foreach( DEPENDENCY IN LISTS ${MODULE}_DEPENDS ) + # _elxmodule_enable( ${DEPENDENCY} ) + # endforeach() + endif() +endmacro() + +macro( _elxmodule_disable MODULE ) + # TODO +endmacro() + +macro( _elxmodules_initialize ) + set( ELXMODULE_ALL ) + + file( GLOB MODULE_FILES RELATIVE "${CMAKE_SOURCE_DIR}" + "${CMAKE_SOURCE_DIR}/Modules/*/ELXMODULE_*.cmake" + ) + + message( STATUS "Found the following elastix modules:") + foreach( MODULE_FILE ${MODULE_FILES}) + get_filename_component( MODULE_PATH ${MODULE_FILE} PATH ) + get_filename_component( MODULE ${MODULE_FILE} NAME_WE ) + message( STATUS " ${MODULE}" ) + + option( "USE_${MODULE}" OFF ) + set( "${MODULE}_ENABLED" OFF ) + + set( ${MODULE}_SOURCE_DIR ${CMAKE_SOURCE_DIR}/${MODULE_PATH} ) + set( ${MODULE}_BINARY_DIR ${CMAKE_BINARY_DIR}/${MODULE_PATH} ) + set( ${MODULE}_LIBRARIES ) + + list(APPEND ELXMODULE_ALL ${MODULE} ) + endforeach() +endmacro() + +_elxmodules_initialize() + +# --------------------------------------------------------------------- +# Public interface + +macro( elxmodule_enable MODULE ) + option( USE_${MODULE} ON ) + _elxmodule_enable( ${MODULE} ) +endmacro() + + diff --git a/CMakeLists.txt b/CMakeLists.txt index 8214d5aa7d313d5cc58e23b26ebf25f88919cdcb..96e2f9c876f751b4dda3f391569ab098f688721f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,11 @@ find_package( ITK REQUIRED ) include( ${ITK_USE_FILE} ) include( "${CMAKE_CURRENT_SOURCE_DIR}/CMake/elxITKRequiredModules.cmake" ) +# --------------------------------------------------------------------- +# Boost Graph Library +find_package( Boost REQUIRED graph ) +include_directories(${Boost_INCLUDE_DIRS}) + # --------------------------------------------------------------------- # Build Elastix diff --git a/Modules/CMakeLists.txt b/Modules/CMakeLists.txt deleted file mode 100644 index 3c6212d3542a67000d0091ff33a596e2e739a74c..0000000000000000000000000000000000000000 --- a/Modules/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_subdirectory( - Core -) diff --git a/Modules/Core/Blueprints/CMakeLists.txt b/Modules/Core/Blueprints/CMakeLists.txt index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..88e196eb772e989b05c104ac6e047e24e6d0a09d 100644 --- a/Modules/Core/Blueprints/CMakeLists.txt +++ b/Modules/Core/Blueprints/CMakeLists.txt @@ -0,0 +1,2 @@ +include_directories( include ) +add_subdirectory( src ) diff --git a/Modules/Core/Blueprints/include/elxBlueprint.h b/Modules/Core/Blueprints/include/elxBlueprint.h new file mode 100644 index 0000000000000000000000000000000000000000..8b42694b8227d2e0881a67b086f7af79147c2090 --- /dev/null +++ b/Modules/Core/Blueprints/include/elxBlueprint.h @@ -0,0 +1,62 @@ +#ifndef __Blueprint_h +#define __Blueprint_h + +#include "itkObjectFactory.h" +#include "itkDataObject.h" + +#include "elxMacro.h" +#include "elxComponentDescriptor.h" + +#include "boost/graph/graph_traits.hpp" +#include "boost/graph/directed_graph.hpp" + +namespace elx { + +template< class TComponentDescriptor > +class Blueprint : public itk::DataObject +{ +public: + + elxNewMacro( Blueprint, itk::DataObject ); + + typedef TComponentDescriptor ComponentDescriptorType; + typedef typename TComponentDescriptor::ComponentNameType ComponentNameType; + + typedef boost::adjacency_list< boost::vecS, + boost::vecS, + boost::directedS, + ComponentDescriptorType > GraphType; + + typedef typename boost::graph_traits< GraphType >::vertex_descriptor ComponentType; + typedef typename boost::graph_traits< GraphType >::vertex_iterator ComponentIterator, ComponentIteratorEnd; + + typedef boost::vertex_index_t ComponentIndexType; + typedef typename boost::property_map< GraphType, ComponentIndexType >::type ComponentIndexMapType; + + typedef typename boost::graph_traits< GraphType >::edge_descriptor ConnectionDescriptorType; + typedef typename boost::graph_traits< GraphType >::edge_iterator ConnectionIterator, ConnectionIteratorEnd; + + typedef typename boost::graph_traits< GraphType >::in_edge_iterator InputIterator, InputIteratorEnd; + typedef typename boost::graph_traits< GraphType >::out_edge_iterator OutputIterator, OutputIteratorEnd; + + int TestFunction( void ); + bool AddComponent( ComponentDescriptorType component ); + bool SetComponent( ComponentIndexType componentIndex, ComponentDescriptorType component ); + ComponentDescriptorType GetComponent( ComponentIndexType componentIndex ); + bool RemoveComponent( ComponentDescriptorType component ); + + bool SetConnection( ComponentIndexType upstream, ComponentIndexType downstream ); + ConnectionDescriptorType GetConnection( ConnectionDescriptorType Connection ); + bool RemoveConnection( ConnectionDescriptorType connection ); + + void PrintGraph( void ); + +private: + + GraphType m_Graph; + +}; + +} + +#endif // #define __Blueprint_h \ No newline at end of file diff --git a/Modules/Core/Blueprints/include/elxComponentDescriptor.h b/Modules/Core/Blueprints/include/elxComponentDescriptor.h new file mode 100644 index 0000000000000000000000000000000000000000..8cfcde65694a513cbf50750ab4bcfbce076f0d84 --- /dev/null +++ b/Modules/Core/Blueprints/include/elxComponentDescriptor.h @@ -0,0 +1,30 @@ +#ifndef __ComponentDescriptor_h +#define __ComponentDescriptor_h + +#include "elxMacro.h" +#include "itkDataObject.h" + +namespace elx { + +class ComponentDescriptor : public itk::DataObject +{ +public: + + elxNewMacro( ComponentDescriptor, itk::DataObject ); + + // Identifier to find component in the component database + typedef std::string ComponentNameType; + + // TODO: Setter should validate ComponentName exists in ComponentDatabase + itkSetMacro( ComponentName, ComponentNameType ); + itkGetMacro( ComponentName, ComponentNameType ); + +private: + + ComponentNameType m_ComponentName; + +}; + +} + +#endif // __ComponentDescriptor_h diff --git a/Modules/Core/Blueprints/src/CMakeLists.txt b/Modules/Core/Blueprints/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..28d535fe78ba61e547940c35eb07c7cc6469cad5 --- /dev/null +++ b/Modules/Core/Blueprints/src/CMakeLists.txt @@ -0,0 +1,6 @@ +message( STATUS "In directory ${CMAKE_CURRENT_LIST_DIR}" ) + +add_library( Blueprints + elxComponentDescriptor.cxx + elxBlueprint.cxx +) \ No newline at end of file diff --git a/Modules/Core/Blueprints/src/elxBlueprint.cxx b/Modules/Core/Blueprints/src/elxBlueprint.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2c7e3d32aa93832d805aceb3937d4e82b1971ead --- /dev/null +++ b/Modules/Core/Blueprints/src/elxBlueprint.cxx @@ -0,0 +1,80 @@ +#ifndef __Blueprint_hxx +#define __Blueprint_hxx + +#include <boost/graph/graphviz.hpp> + +#include "elxBlueprint.h" + +namespace elastix { + +void +Blueprint< ComponentDescriptor > +::Blueprint( void ) +{ + this->SetGraph( GraphType ); +} + +ComponentDescriptorType +Blueprint< ComponentDescriptor > +::AddComponent( ComponentDescriptorType component ) +{ + // TODO: Check that the component is in the ComponentDatabase + this->Modified(); + return this->m_Graph->add_vertex( component ); +} + +bool +Blueprint< ComponentDescriptor > +::SetComponent( ComponentDescriptorType component ) +{ + this->Modified(); + return this->m_Graph->remove_vertex( connection ); +} + +bool +Blueprint< ComponentDescriptor > +::RemoveComponent( ComponentDescriptorType component ) +{ + this->Modified(); + return this->m_Graph->remove_vertex( connection ); +} + +bool +Blueprint< ComponentDescriptor > +::AddConnection( ComponentDescriptorType upsteam, ComponentDescriptorType downstream ) +{ + this->Modified(); + return this->m_Graph->add_edge( upstream, downstream ); +} + +ConnectionDescriptorType +Blueprint< ComponentDescriptor > +::GetConnection( ConnectionDescriptorType Connection ) +{ + this->Modified(); +} + +void +Blueprint< ComponentDescriptor > +::RemoveConnection( ConnectionType connection ) +{ + this->Modified(); + this->m_Graph->remove_edge( connection ); +} + +void +Blueprint< ComponentDescriptor > +::PrintGraph( void ) +{ + // TODO: Link to graphviz library + // boost::write_graphviz(std::cout, this->m_Graph); + std::cout << "Printed graph" << std::endl; +} +void +Blueprint< ComponentDescriptor > +::TestFunction( void ) +{ return 0; } + +} + +#endif // __Blueprint_hxx \ No newline at end of file diff --git a/Modules/Core/Blueprints/src/elxComponentDescriptor.cxx b/Modules/Core/Blueprints/src/elxComponentDescriptor.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b37f5f3fbf8bfbac685ad6eb3a43f88a59903827 --- /dev/null +++ b/Modules/Core/Blueprints/src/elxComponentDescriptor.cxx @@ -0,0 +1,46 @@ +#ifndef __ComponentDescriptor_hxx +#define __ComponentDescriptor_hxx + +#include "elxComponentDescriptor.h" + +// TODO: Need enum for component name? + +namespace elx { + +ComponentDescriptor +::ComponentDescriptor( const ComponentNameType componentName ) +{ + this->SetComponentName( componentName ); + this->SetComponentUniqueId( this->GenerateUniqueId() ); + this->SetParameterMap( this->ParameterMapType() ); +} + +ComponentDescriptor +::ComponentDescriptor( const ComponentNameType componentName, + const ComponentUniqueIdType componentUniqueId ) +{ + this->SetComponentName( componentName ); + this->SetComponentUniqueId( componentUniqueId ); + this->SetParameterMap( this->ParameterMapType() ); +} + +ComponentDescriptor +::ComponentDescriptor( const ComponentNameType componentName, + const ComponentIdType componentUniqueId, + const ParameterMapType parameterMap ) +{ + this->SetComponentName( componentName ); + this->SetComponentUniqueId( componentUniqueId ); + this->SetParameterMap( parameterMap ); +} + +ComponentDescriptor::ComponentIdType +ComponentDescriptor +::GenerateUniqueId() +{ + +} + +} // namespace elx + +#endif // __ComponentDescriptor_hxx \ No newline at end of file diff --git a/Modules/Core/CMakeLists.txt b/Modules/Core/CMakeLists.txt index 84c12fcb3aba7189c16706bc6a7affdded2175ca..d45d6001371a6a233a3ec2fb1941853f422a27a6 100644 --- a/Modules/Core/CMakeLists.txt +++ b/Modules/Core/CMakeLists.txt @@ -1,2 +1,15 @@ +project( ELXMODULE_CORE ) + +# TODO: Include directures using the module API +include_directories( + Common/include + Blueprints/include +) + add_subdirectory( Common ) add_subdirectory( Blueprints ) + +set( "${PROJECT_NAME}_LIBRARIES" + Blueprints +) + diff --git a/Modules/Core/ELXMODULE_CORE.cmake b/Modules/Core/ELXMODULE_CORE.cmake new file mode 100644 index 0000000000000000000000000000000000000000..f0ed9132d95b47c2c4528d98e9feb6a24d8aee7b --- /dev/null +++ b/Modules/Core/ELXMODULE_CORE.cmake @@ -0,0 +1,10 @@ +set( DOCUMENTATION + "This module contains the core components of elastix library such as the component database and component pipeline instantiation functionality." +) + +elxmodule_enable( ELXMODULE_CORE + DEPENDS + ELXMODULE_COMMON + DESCRIPTION + "${DOCUMENTATION}" +) diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt index cff7bb5aec197b58bc119bf198014d2991bd6f36..0eb91de3a6f2cccb4fd546af8fb89ce8ff0777aa 100644 --- a/SuperBuild/CMakeLists.txt +++ b/SuperBuild/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required( VERSION 2.8 ) -#--------------------------------------------------------------------- +# --------------------------------------------------------------------- project( ElastixSuperBuild ) find_package( Git REQUIRED ) @@ -15,7 +15,7 @@ set( CMAKE_MODULE_PATH set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH "SuperBuild install directory" FORCE) -#--------------------------------------------------------------------- +# --------------------------------------------------------------------- # Elastix SuperBuild configuration # Build release by default @@ -29,13 +29,16 @@ option( ELASTIX_BUILD_EXAMPLES "Enable building examples." ON ) # Build tests by default option( ELASTIX_BUILD_TESTING "Enable building tests." ON ) - if( ELASTIX_BUILD_TESTING ) option( ELASTIX_BUILD_BENCHMARKING "Enable building benchmarks." ON ) option( ELASTIX_BUILD_DASHBOARD "Enable building benchmarks." ON ) endif() -#--------------------------------------------------------------------- +# Do not build dashboard by default +option( ELASTIX_BUILD_DASHBOARD "Enable building dashboard." OFF ) + + +# --------------------------------------------------------------------- # Build ITK set( ITK_VERSION_MAJOR "4" ) @@ -54,7 +57,19 @@ else() list( APPEND ELASTIX_DEPENDENCIES ITK ) endif() -#--------------------------------------------------------------------- +# --------------------------------------------------------------------- +# Boost Graph Library + +mark_as_advanced( USE_SYSTEM_BOOST ) +option( USE_SYSTEM_BOOST "Use an installed version of BOOST" OFF ) +if( USE_SYSTEM_BOOST ) + find_package( BOOST REQUIRED graph ) +else() + include( ExternalBoost ) + list( APPEND ELASTIX_DEPENDENCIES BOOST ) +endif() + +# --------------------------------------------------------------------- # Build Elastix include( Elastix ) diff --git a/SuperBuild/Elastix.cmake b/SuperBuild/Elastix.cmake index d6bf55178d1d5674f14c9a5bd3f3fc7a93dcb3bd..1f1d739399df9111afa2df1d2577b2b4e6e91472 100644 --- a/SuperBuild/Elastix.cmake +++ b/SuperBuild/Elastix.cmake @@ -6,10 +6,12 @@ ExternalProject_Add( ${proj} BINARY_DIR ${proj}-build CMAKE_ARGS --no-warn-unused-cli + -DELASTIX_BUILD_EXAMPLES:BOOL=${ELASTIX_BUILD_EXAMPLES} -DELASTIX_BUILD_TESTING:BOOL=${ELASTIX_BUILD_TESTING} -DELASTIX_BUILD_BENCHMARKING:BOOL=${ELASTIX_BUILD_BENCHMARKING} -DELASTIX_BUILD_DASHBOARD:BOOL=${ELASTIX_BUILD_DASHBOARD} -DITK_DIR:PATH=${ITK_DIR} + -DBOOST_ROOT:PATH=${BOOST_ROOT} DEPENDS ${ELASTIX_DEPENDENCIES} INSTALL_COMMAND "" -) \ No newline at end of file +) diff --git a/SuperBuild/ExternalBoost.cmake b/SuperBuild/ExternalBoost.cmake new file mode 100644 index 0000000000000000000000000000000000000000..e1f1286e9995efa98dce2649cc9aa79a41bebdbf --- /dev/null +++ b/SuperBuild/ExternalBoost.cmake @@ -0,0 +1,39 @@ +set( PROJECT BOOST ) + +# Note: It IS important to download different files on different OS's: +# on Unix-like systems, we need the file persmissions (only available in the .tar.gz), +# while on Windows, we need CR/LF line feeds (only available in the .zip) + +set( BOOST_CONFIGURE_COMMAND ) +if( UNIX ) + set( BOOST_URL "http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.tar.gz") + set( BOOST_MD5 51528a0e3b33d9e10aaa311d9eb451e3 ) + set( BOOST_CONFIGURE_COMMAND ./bootstrap.sh ) + set( BOOST_BUILD_COMMAND ./b2 ) +else() + if( WIN32 ) + set( BOOST_URL "http://sourceforge.net/projects/boost/files/boost/1.59.0/boost_1_59_0.zip") + set( BOOST_MD5 08d29a2d85db3ebc8c6fdfa3a1f2b83c ) + set( BOOST_CONFIGURE_COMMAND cmd /C bootstrap.bat msvc ) + set( BOOST_BUILD_COMMAND b2.exe ) + endif() +endif() + +set( BOOST_BUILD_DIR "${CMAKE_INSTALL_PREFIX}/${PROJECT}-build/" ) + +ExternalProject_Add( BOOST + BUILD_IN_SOURCE 1 + URL "${BOOST_URL}" + URL_MD5 ${BOOST_MD5} + UPDATE_COMMAND "" + CONFIGURE_COMMAND ${BOOST_CONFIGURE_COMMAND} + --prefix=${BOOST_BUILD_DIR}/lib + BUILD_COMMAND ${BOOST_BUILD_COMMAND} install + --prefix=${BOOST_BUILD_DIR} + --with-graph + --variant=release + --jobs=4 + INSTALL_COMMAND "" +) + +set( BOOST_ROOT ${BOOST_BUILD_DIR} ) diff --git a/SuperBuild/ExternalITK.cmake b/SuperBuild/ExternalITK.cmake index 206e83a60c330e8a067a4dffc9ea3d4f030c0b7f..0ee77affea1569d7f946b128e1a7de2756189959 100644 --- a/SuperBuild/ExternalITK.cmake +++ b/SuperBuild/ExternalITK.cmake @@ -1,13 +1,13 @@ -set( proj ITK ) +set( PROJECT ITK ) set( ITK_REPOSITORY https://github.com/InsightSoftwareConsortium/ITK.git ) set( ITK_TAG "v${ITK_VERSION_STRING}") -ExternalProject_Add( ${proj} +ExternalProject_Add( ${PROJECT} GIT_REPOSITORY ${ITK_REPOSITORY} GIT_TAG ${ITK_TAG} UPDATE_COMMAND "" - SOURCE_DIR ${proj} - BINARY_DIR ${proj}-build + SOURCE_DIR ${PROJECT} + BINARY_DIR ${PROJECT}-build CMAKE_ARGS --no-warn-unused-cli -DBUILD_EXAMPLES:BOOL=OFF @@ -21,4 +21,4 @@ ExternalProject_Add( ${proj} ) ExternalProject_Get_Property( ITK install_dir ) -set( ITK_DIR "${install_dir}/lib/cmake/ITK-${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}" ) \ No newline at end of file +set( ITK_DIR "${install_dir}/lib/cmake/ITK-${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}" ) diff --git a/Testing/Unit/CMakeLists.txt b/Testing/Unit/CMakeLists.txt index 152463661b386eebef9985f5071fa38a1f427f9e..1ed2189daf32f2fab2f429e3bdb080dd276c3e77 100644 --- a/Testing/Unit/CMakeLists.txt +++ b/Testing/Unit/CMakeLists.txt @@ -5,6 +5,7 @@ set( ElastixUnitTestFilenames elxExampleUnitTest.cxx + elxBluePrintTest.cxx itkRegistration.cxx ) @@ -33,7 +34,6 @@ configure_file( ) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) - add_library( DataManager elxDataManager.cxx ) list( APPEND TEST_LIBRARIES diff --git a/Testing/Unit/elxBluePrintTest.cxx b/Testing/Unit/elxBluePrintTest.cxx new file mode 100644 index 0000000000000000000000000000000000000000..31dc1d8eb25d5af8536a9b3bca11568a22d16ae2 --- /dev/null +++ b/Testing/Unit/elxBluePrintTest.cxx @@ -0,0 +1,27 @@ +#include "elxBlueprint.h" +#include "elxComponentDescriptor.h" +#include "gtest/gtest.h" + +namespace elx { + +TEST( Blueprint, Instantiation ) +{ + typedef Blueprint< ComponentDescriptor > BlueprintType; + BlueprintType::Pointer blueprint; + EXPECT_NO_THROW( blueprint = BlueprintType::New() ); + + typedef BlueprintType::ComponentDescriptorType ComponentDescriptorType; + ComponentDescriptorType::Pointer componentDescriptor; + EXPECT_NO_THROW( componentDescriptor = ComponentDescriptorType::New() ); + + typedef ComponentDescriptorType::ComponentNameType ComponentNameType; + ComponentNameType componentName; + EXPECT_NO_THROW( componentName = ComponentNameType("Metric") ); + EXPECT_NO_THROW( componentDescriptor->SetComponentName( componentName ) ); + + EXPECT_NO_THROW( blueprint->TestFunction() ); + + ASSERT_TRUE( true ); +} + +} // namespace elx \ No newline at end of file