From 2a3a2557de5290e3ff39c1f87727c5bdbf805515 Mon Sep 17 00:00:00 2001
From: Kasper Marstal <kaspermarstal@gmail.com>
Date: Thu, 3 Sep 2015 15:54:00 +0200
Subject: [PATCH] ENH: ELASTIX-6 Add ComponentDescriptor and Blueprint classes

---
 CMakeLists.txt                                |  5 ++
 Modules/Core/Blueprints/CMakeLists.txt        |  1 +
 .../Core/Blueprints/include/elxBlueprint.h    | 55 ++++++++++++++++++
 .../include/elxComponentDescriptor.h          | 30 ++++++++++
 Modules/Core/Blueprints/src/elxBlueprint.hxx  | 57 +++++++++++++++++++
 Modules/Core/CMakeLists.txt                   |  2 +-
 SuperBuild/CMakeLists.txt                     | 24 ++++++--
 SuperBuild/Elastix.cmake                      |  4 +-
 Testing/Unit/elxBluePrintTest.cxx             | 28 +++++++++
 9 files changed, 199 insertions(+), 7 deletions(-)
 create mode 100644 Modules/Core/Blueprints/include/elxBlueprint.h
 create mode 100644 Modules/Core/Blueprints/include/elxComponentDescriptor.h
 create mode 100644 Modules/Core/Blueprints/src/elxBlueprint.hxx
 create mode 100644 Testing/Unit/elxBluePrintTest.cxx

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5f8add9d..e07eb5ed 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,6 +23,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/Core/Blueprints/CMakeLists.txt b/Modules/Core/Blueprints/CMakeLists.txt
index e69de29b..b83cfce3 100644
--- a/Modules/Core/Blueprints/CMakeLists.txt
+++ b/Modules/Core/Blueprints/CMakeLists.txt
@@ -0,0 +1 @@
+include_directories( include )
diff --git a/Modules/Core/Blueprints/include/elxBlueprint.h b/Modules/Core/Blueprints/include/elxBlueprint.h
new file mode 100644
index 00000000..02720821
--- /dev/null
+++ b/Modules/Core/Blueprints/include/elxBlueprint.h
@@ -0,0 +1,55 @@
+#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 boost::adjacency_list< boost::listS,      
+                                 boost::listS,      
+                                 boost::directedS,
+                                 ComponentDescriptorType >               GraphType;
+
+  typedef typename boost::graph_traits< GraphType >::vertex_descriptor   ComponentType;
+  typedef typename boost::graph_traits< GraphType >::vertex_iterator     ComponentIterator, ComponentIteratorEnd;
+
+  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;
+
+  void SetGraph( GraphType graph ) { this->m_Graph = graph; };
+  GraphType GetGraph( void ) const { return m_Graph; };
+
+  void AddComponent( ComponentDescriptorType component );
+  void RemoveComponent( ComponentDescriptorType component );
+
+  void AddConnection( ComponentDescriptorType upstream, ComponentDescriptorType downstream );
+  void RemoveConnection( ConnectionDescriptorType connection );
+
+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 00000000..c6ace2d9
--- /dev/null
+++ b/Modules/Core/Blueprints/include/elxComponentDescriptor.h
@@ -0,0 +1,30 @@
+#ifndef __ComponentDescriptor_h
+#define __ComponentDescriptor_h
+
+#include "elxMacro.h"
+#include "itkLightObject.h"
+
+namespace elx {
+
+class ComponentDescriptor : public itk::LightObject
+{
+public:
+
+  elxNewMacro( ComponentDescriptor, itk::LightObject );
+
+  typedef std::string                                         ComponentNameType;
+  typedef std::map< std::string, std::vector< std::string > > ParameterMapType;
+
+  void SetComponentName( ComponentNameType componentName ) { this->m_ComponentName = componentName; };
+  ComponentNameType GetComponentName( void ) { return this->m_ComponentName; };
+
+private:
+
+  ComponentNameType  m_ComponentName;
+  ParameterMapType   m_ParameterMap;
+
+};
+
+}
+
+#endif // __ComponentDescriptor_h
\ No newline at end of file
diff --git a/Modules/Core/Blueprints/src/elxBlueprint.hxx b/Modules/Core/Blueprints/src/elxBlueprint.hxx
new file mode 100644
index 00000000..b37fe4d6
--- /dev/null
+++ b/Modules/Core/Blueprints/src/elxBlueprint.hxx
@@ -0,0 +1,57 @@
+#ifndef __Blueprint_hxx
+#define __Blueprint_hxx
+
+#include <boost/graph/graphviz.hpp>
+
+#include "elxBlueprint.h"
+
+namespace elastix {
+
+void
+Blueprint< ComponentDescriptor >
+::Blueprint( void )
+{
+  this->m_Graph = GraphType;
+}
+
+ComponentDescriptorType
+Blueprint< ComponentDescriptor >
+::AddComponent( ComponentDescriptorType component )
+{
+  this->Modified();
+  return this->m_Graph->add_vertex( component );
+}
+
+void 
+Blueprint< ComponentDescriptor >
+::RemoveComponent( ComponentDescriptorType component )
+{
+  this->Modified();
+  this->m_Graph->remove_vertex( connection );
+}
+
+void
+Blueprint< ComponentDescriptor >
+::AddConnection( ComponentDescriptorType upsteam, ComponentDescriptorType downstream )
+{
+  this->Modified();
+  this->m_Graph->add_edge( upstream, downstream );
+}
+
+void 
+Blueprint< ComponentDescriptor >
+::RemoveConnection( ConnectionType connection )
+{
+  this->Modified();
+  this->m_Graph->remove_edge( connection );
+}
+
+void Blueprint< ComponentDescriptor >
+::PrintSelf( void )
+{
+  boost::write_graphviz(std::cout, this->m_Graph);
+}
+
+}
+
+#endif // __Blueprint_hxx
\ No newline at end of file
diff --git a/Modules/Core/CMakeLists.txt b/Modules/Core/CMakeLists.txt
index 84c12fcb..e8a5c060 100644
--- a/Modules/Core/CMakeLists.txt
+++ b/Modules/Core/CMakeLists.txt
@@ -1,2 +1,2 @@
 add_subdirectory( Common )
-add_subdirectory( Blueprints )
+add_subdirectory( BluePrints )
diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt
index cff7bb5a..8ba451e1 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,18 @@ 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" ON )
+if( USE_SYSTEM_BOOST )
+  find_package( BOOST REQUIRED graph )
+else()
+  message( FATAL_ERROR "BOOST is not yet integrated with the SuperBuild. Install BOOST on your system, set USE_SYSTEM_BOOST to ON and re-run CMake." )
+endif()
+
+# ---------------------------------------------------------------------
 # Build Elastix
 
 include( Elastix )
diff --git a/SuperBuild/Elastix.cmake b/SuperBuild/Elastix.cmake
index d6bf5517..1f1d7393 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/Testing/Unit/elxBluePrintTest.cxx b/Testing/Unit/elxBluePrintTest.cxx
new file mode 100644
index 00000000..d3cc27fe
--- /dev/null
+++ b/Testing/Unit/elxBluePrintTest.cxx
@@ -0,0 +1,28 @@
+#include "elxBlueprint.h"
+#include "elxComponentDescriptor.h"
+#include "gtest/gtest.h"
+
+namespace elx {
+
+TEST( Blueprint, Instantiation )
+{
+  typedef Blueprint< ComponentDescriptor >  BlueprintType;
+  BlueprintType::Pointer blueprint = BlueprintType::New();
+
+  typedef BlueprintType::ComponentDescriptorType ComponentDescriptorType;
+  ComponentDescriptorType::Pointer componentDescriptor = ComponentDescriptorType::New();
+
+  typedef ComponentDescriptorType::ComponentNameType ComponentNameType;
+  ComponentNameType componentName = ComponentNameType("Metric");
+  componentDescriptor->SetComponentName( componentName );
+
+  // We would like to save all data in the graph itself, but the following is 
+  // not possible because the component (of type itk::LightObject has private copy 
+  // constructor. How do we save data in graph and make this as itk-like as possible?
+  // Ideally when a component descriptor is changed the blueprint calls Modified() on itself
+  // blueprint->AddComponent( (*componentDescriptor) );
+
+  ASSERT_TRUE( true );
+}
+
+} // namespace elx
\ No newline at end of file
-- 
GitLab