From 3e04a27942dd38b669c11c94339734b69f39022a Mon Sep 17 00:00:00 2001
From: Kasper Marstal <kaspermarstal@gmail.com>
Date: Tue, 19 May 2015 17:38:45 +0200
Subject: [PATCH] COMP: ELASTIX-1 Add readthedocs.org documentation system and
 benchmarking system

---
 CMakeLists.txt                                |   1 +
 SuperBuild/CMakeLists.txt                     |   3 +-
 SuperBuild/Elastix.cmake                      |   2 +-
 Testing/Benchmark/BSplineRegistration.cxx     | 137 ++++++++++++++++++
 Testing/Benchmark/CMakeLists.txt              |  37 +++++
 Testing/CMakeLists.txt                        |  36 +----
 .../Input/BrainProtonDensitySlice.png.md5     |   1 +
 Testing/Unit/CMakeLists.txt                   |  31 ++++
 .../elxExampleUnitTest.cxx}                   |   0
 9 files changed, 215 insertions(+), 33 deletions(-)
 create mode 100644 Testing/Benchmark/BSplineRegistration.cxx
 create mode 100644 Testing/Benchmark/CMakeLists.txt
 create mode 100644 Testing/Data/Input/BrainProtonDensitySlice.png.md5
 create mode 100644 Testing/Unit/CMakeLists.txt
 rename Testing/{elxExampleTest.cxx => Unit/elxExampleUnitTest.cxx} (100%)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ec355d9a..a50193ad 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,6 +23,7 @@ include( "${CMAKE_CURRENT_SOURCE_DIR}/CMake/elxRequiredITKModules.cmake" )
 option( ELASTIX_BUILD_TESTING "Enable building tests." OFF )
 
 if( ELASTIX_BUILD_TESTING )
+  option( ELASTIX_BUILD_BENCHMARKING "Enable building benchmarks." OFF )
   enable_testing()
   add_subdirectory( Testing )
 endif()
diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt
index 12a9ed5a..15dd3d89 100644
--- a/SuperBuild/CMakeLists.txt
+++ b/SuperBuild/CMakeLists.txt
@@ -29,8 +29,7 @@ option( ELASTIX_BUILD_EXAMPLES "Enable building examples." ON )
 option( ELASTIX_BUILD_TESTING "Enable building tests." ON )
 
 if( ELASTIX_BUILD_TESTING )
-  mark_as_advanced( ELASTIX_BUILD_CTESTS )
-  option( ELASTIX_BUILD_CTESTS "Enable CTests." OFF )
+  option( ELASTIX_BUILD_BENCHMARKING "Enable building benchmarks." ON )
 endif()
 
 #---------------------------------------------------------------------
diff --git a/SuperBuild/Elastix.cmake b/SuperBuild/Elastix.cmake
index 130f5595..6afad940 100644
--- a/SuperBuild/Elastix.cmake
+++ b/SuperBuild/Elastix.cmake
@@ -8,7 +8,7 @@ ExternalProject_Add( ${proj}
   CMAKE_ARGS
     --no-warn-unused-cli
     -DELASTIX_BUILD_TESTING:BOOL=${ELASTIX_BUILD_TESTING}
-    -DELASTIX_BUILD_CTESTS:BOOL=${ELASTIX_BUILD_CTESTS}
+    -DELASTIX_BUILD_BENCHMARKING:BOOL=${ELASTIX_BUILD_BENCHMARKING}
     -DITK_DIR:PATH=${ITK_DIR}
   DEPENDS ${ELASTIX_DEPENDENCIES}
   INSTALL_COMMAND ""
diff --git a/Testing/Benchmark/BSplineRegistration.cxx b/Testing/Benchmark/BSplineRegistration.cxx
new file mode 100644
index 00000000..8a8a73b4
--- /dev/null
+++ b/Testing/Benchmark/BSplineRegistration.cxx
@@ -0,0 +1,137 @@
+/**
+ * Benchmarking multi-resolution non-rigid b-spline registration 
+ * with mutual information in ITK, Elastix and ANTs
+ */
+
+#include "itkImage.h"
+#include "itkImageFileReader.h"
+#include "itkImageFileWriter.h"
+
+// DeformableRegistration1
+#include "itkRescaleIntensityImageFilter.h"
+#include "itkHistogramMatchingImageFilter.h"
+#include "itkFEMRegistrationFilter.h"
+
+#include "gtest/gtest.h"
+
+class itkExamples : public ::testing::Test
+{
+protected:
+
+    virtual void SetUp()
+    {
+        const char *fixedImageName, *movingImageName;
+        if ( argc < 2 )
+        {
+          std::cout << "Image filenames missing." << std::endl;
+          std::cout << "Usage: " << argv[0] << " fixedImageFilename movingImageFilename"
+                    << std::endl;
+          return EXIT_FAILURE;
+        }
+        else
+        {
+          fixedImageFilename = argv[1];
+          movingImageFilename = argv[2];
+        }
+    }
+
+};
+
+TEST_F( BSplineRegistration, ITK ) {
+
+  const unsigned int ImageDimension = 2;
+  typedef unsigned char PixelType;
+  typedef itk::Image< PixelType, ImageDimension > ImageType;
+
+  const unsigned int SplineOrder = 3;
+  typedef double CoordinateRepType;
+  
+  // Transform
+  typedef itk::BSplineDeformableTransform< CoordinateRepType,
+                                           SpaceDimension,
+                                           SplineOrder > TransformType;
+
+  typedef TransformType::RegionType RegionType;
+  RegionType bsplineRegion;
+  RegionType::SizeType  gridSizeOnImage;
+  RegionType::SizeType  gridBorderSize;
+  RegionType::SizeType  totalGridSize;
+ 
+  gridSizeOnImage.Fill( 5 );
+  gridBorderSize.Fill( 3 ); // Border for spline order = 3 ( 1 lower, 2 upper )
+  totalGridSize = gridSizeOnImage + gridBorderSize;
+ 
+  bsplineRegion.SetSize( totalGridSize );
+ 
+  typedef TransformType::SpacingType SpacingType;
+  SpacingType spacing = fixedImage->GetSpacing();
+ 
+  typedef TransformType::OriginType OriginType;
+  OriginType origin = fixedImage->GetOrigin();
+ 
+  ImageType::SizeType fixedImageSize = fixedRegion.GetSize();
+ 
+  for(unsigned int r=0; r<ImageDimension; r++)
+  {
+    spacing[r] *= static_cast<double>(fixedImageSize[r] - 1)  /
+                  static_cast<double>(gridSizeOnImage[r] - 1);
+  }
+ 
+  ImageType::DirectionType gridDirection = fixedImage->GetDirection();
+  SpacingType gridOriginOffset = gridDirection * spacing;
+ 
+  OriginType gridOrigin = origin - gridOriginOffset;
+ 
+  transform->SetGridSpacing( spacing );
+  transform->SetGridOrigin( gridOrigin );
+  transform->SetGridRegion( bsplineRegion );
+  transform->SetGridDirection( gridDirection );
+
+  typedef TransformType::ParametersType ParametersType;
+  const unsigned int numberOfParameters = transform->GetNumberOfParameters();
+  ParametersType parameters( numberOfParameters );
+  parameters.Fill( 0.0 );
+  transform->SetParameters( parameters );
+
+  // Optimizer
+  typedef itk::LBFGSOptimizer OptimizerType;
+
+  optimizer->SetGradientConvergenceTolerance( 0.05 );
+  optimizer->SetLineSearchAccuracy( 0.9 );
+  optimizer->SetDefaultStepLength( .5 );
+  optimizer->TraceOn();
+  optimizer->SetMaximumNumberOfFunctionEvaluations( 1024 );
+ 
+  // Metric
+  typedef itk::MeanSquaresImageToImageMetric< ImageType,
+                                              ImageType > MetricType;
+
+  // Interpolator
+  typedef itk:: LinearInterpolateImageFunction< ImageType,
+                                                double >  InterpolatorType;
+
+  // Setup the registration
+  typedef itk::ImageRegistrationMethod< ImageType,
+                                        ImageType > RegistrationType;
+
+  RegistrationType::Pointer registration  = RegistrationType::New();
+  registration->SetNumberOfThreads( 1 );
+  registration->SetMetric( MetricType::New() );
+  registration->SetOptimizer( OptimizerType::New() );
+  registration->SetInterpolator( InterpolatorType::New() );
+ 
+  TransformType::Pointer transform = TransformType::New();
+  registration->SetTransform( transform );
+
+  registration->SetFixedImage( fixedImage  );
+  registration->SetMovingImage(  movingImage );
+ 
+  ImageType::RegionType fixedRegion = fixedImage->GetBufferedRegion();
+  registration->SetFixedImageRegion( fixedRegion );
+ 
+  registration->SetInitialTransformParameters( transform->GetParameters() );
+
+  // Execute
+  EXPECT_NO_THROW( registration->Update() );
+
+}
\ No newline at end of file
diff --git a/Testing/Benchmark/CMakeLists.txt b/Testing/Benchmark/CMakeLists.txt
new file mode 100644
index 00000000..3004ccdf
--- /dev/null
+++ b/Testing/Benchmark/CMakeLists.txt
@@ -0,0 +1,37 @@
+#
+set( GTEST_OPTIONS
+  -gtest_output
+)
+
+#---------------------------------------------------------------------
+# To add a benchmark to the build system, append it to the list below. 
+# Any GoogleTests in these files are automatically added to CTest.
+
+set( ElastixBenchmarkSource
+  elxExampleBenchmark.cxx
+)
+
+#---------------------------------------------------------------------
+# To add data to a benchmark, create a list "${filename}Data" (without
+# the filename extension) and add data to this list.
+
+set( elxExampleBenchmarkData
+  DATA{Testing/Data/Input/BrainProtonDensitySlice.png}
+  DATA{Testing/Data/Input/BrainProtonDensitySliceR10X13Y17.png}
+)
+
+#---------------------------------------------------------------------
+# Build executables
+
+foreach( ElastixBenchmarkFilename ${ElastixBenchmarkSource} )
+  string( REPLACE ".cxx" "" ElastixBenchmark ${ElastixBenchmarkFilename} )
+  add_executable( ${ElastixBenchmark} ${ElastixBenchmarkFilename} )
+  target_link_libraries( ${ElastixBenchmark} ${ELASTIX_LIBRARIES} ${ITK_LIBRARIES} ${TEST_LIBRARIES} )
+
+  ExternalData_Add_Test( "${ElastixBenchmark}ExternalDataTarget"
+    NAME ${ElastixBenchmark}
+    COMMAND "${ElastixBenchmark} ${${ElastixBenchmarkTest}Data} ${GTEST_OPTIONS}"
+  )
+
+  ExternalData_Add_Target( "${ElastixBenchmark}ExternalDataTarget"} )
+endforeach()
diff --git a/Testing/CMakeLists.txt b/Testing/CMakeLists.txt
index 7343cdc1..30ddd1ec 100644
--- a/Testing/CMakeLists.txt
+++ b/Testing/CMakeLists.txt
@@ -20,14 +20,6 @@ set( TEST_LIBRARIES
   gtest_main
 )
 
-#---------------------------------------------------------------------
-# To add a test to the build system, append it to the list below. 
-# Any GoogleTests in these files are automatically added to CTest.
-
-set( ElastixUnitTestSource
-  elxExampleTest.cxx
-)
-
 #---------------------------------------------------------------------
 # Setup ExternalData
 
@@ -42,26 +34,10 @@ list( APPEND ExternalData_URL_TEMPLATES
 )
 
 #---------------------------------------------------------------------
-# To add data to a tests, create a list "${filename}Data" (without
-# the filename extension) and add data to this list.
-
-set( elxExampleTestData
-  DATA{Data/Input/BrainProtonDensitySliceR10X13Y17.png}
-)
-
-#---------------------------------------------------------------------
-# Build test executables
-
-foreach( ElastixUnitTestFilename ${ElastixUnitTestSource} )
-  string( REPLACE ".cxx" "" ElastixUnitTest ${ElastixUnitTestFilename} )
-  add_executable( ${ElastixUnitTest} ${ElastixUnitTestFilename} )
-  target_link_libraries( ${ElastixUnitTest} ${ELASTIX_LIBRARIES} ${ITK_LIBRARIES} ${TEST_LIBRARIES} )
-
-  ExternalData_Add_Test( "${ElastixUnitTest}ExternalDataTarget"
-    NAME ${ElastixUnitTest}
-    COMMAND ${ElastixUnitTest} ${${ElastixUnitTest}Data}
-  )
-
-  ExternalData_Add_Target( "${ElastixUnitTest}ExternalDataTarget"} )
-endforeach()
+# Include tests
+add_subdirectory( Unit )
 
+# Include benchmarks
+if( ${ELASTIX_BUILD_BENCHMARKING} )
+  add_subdirectory( Benchmark )
+endif()
diff --git a/Testing/Data/Input/BrainProtonDensitySlice.png.md5 b/Testing/Data/Input/BrainProtonDensitySlice.png.md5
new file mode 100644
index 00000000..317f8a12
--- /dev/null
+++ b/Testing/Data/Input/BrainProtonDensitySlice.png.md5
@@ -0,0 +1 @@
+073df8eb397d1746d2343c78dd4bd964
\ No newline at end of file
diff --git a/Testing/Unit/CMakeLists.txt b/Testing/Unit/CMakeLists.txt
new file mode 100644
index 00000000..964055b2
--- /dev/null
+++ b/Testing/Unit/CMakeLists.txt
@@ -0,0 +1,31 @@
+#---------------------------------------------------------------------
+# To add a test to the build system, append it to the list below. 
+# Any GoogleTests in these files are automatically added to CTest.
+
+set( ElastixUnitTestSource
+  elxExampleUnitTest.cxx
+)
+
+#---------------------------------------------------------------------
+# To add data to a tests, create a list "${filename}Data" (without
+# the filename extension) and add data to this list.
+
+set( elxExampleTestData
+  DATA{${CMAKE_BINARY_DIR}/Testing/Data/Input/BrainProtonDensitySliceR10X13Y17.png}
+)
+
+#---------------------------------------------------------------------
+# Build test executables
+
+foreach( ElastixUnitTestFilename ${ElastixUnitTestSource} )
+  string( REPLACE ".cxx" "" ElastixUnitTest ${ElastixUnitTestFilename} )
+  add_executable( ${ElastixUnitTest} ${ElastixUnitTestFilename} )
+  target_link_libraries( ${ElastixUnitTest} ${ELASTIX_LIBRARIES} ${ITK_LIBRARIES} ${TEST_LIBRARIES} )
+
+  ExternalData_Add_Test( "${ElastixUnitTest}ExternalDataTarget"
+    NAME ${ElastixUnitTest}
+    COMMAND ${ElastixUnitTest} ${${ElastixUnitTest}Data}
+  )
+
+  ExternalData_Add_Target( "${ElastixUnitTest}ExternalDataTarget"} )
+endforeach() 
\ No newline at end of file
diff --git a/Testing/elxExampleTest.cxx b/Testing/Unit/elxExampleUnitTest.cxx
similarity index 100%
rename from Testing/elxExampleTest.cxx
rename to Testing/Unit/elxExampleUnitTest.cxx
-- 
GitLab