]> Creatis software - clitk.git/commitdiff
*** empty log message ***
authorjef <jef>
Thu, 22 Jul 2010 14:36:11 +0000 (14:36 +0000)
committerjef <jef>
Thu, 22 Jul 2010 14:36:11 +0000 (14:36 +0000)
107 files changed:
registration/CMakeLists.txt
registration/clitkAffineRegistration.ggo
registration/clitkBLUTDIR.cxx [new file with mode: 0755]
registration/clitkBLUTDIR.ggo [new file with mode: 0755]
registration/clitkBLUTDIRGenericFilter.cxx [new file with mode: 0755]
registration/clitkBLUTDIRGenericFilter.h [new file with mode: 0755]
registration/clitkBLUTDIRGenericFilter.txx [new file with mode: 0755]
registration/clitkBSplineDeformableRegistration.cxx [new file with mode: 0755]
registration/clitkBSplineDeformableRegistration.ggo [new file with mode: 0755]
registration/clitkBSplineDeformableRegistrationGenericFilter.cxx [new file with mode: 0755]
registration/clitkBSplineDeformableRegistrationGenericFilter.h [new file with mode: 0755]
registration/clitkBSplineDeformableRegistrationGenericFilter.txx [new file with mode: 0755]
registration/clitkBSplineDeformableTransform.h [new file with mode: 0644]
registration/clitkBSplineDeformableTransform.txx [new file with mode: 0644]
registration/clitkBSplineDeformableTransformInitializer.h [new file with mode: 0644]
registration/clitkBSplineDeformableTransformInitializer.txx [new file with mode: 0644]
registration/clitkBSplinePyramid.cxx [new file with mode: 0644]
registration/clitkBSplinePyramid.ggo [new file with mode: 0644]
registration/clitkBSplinePyramidGenericFilter.cxx [new file with mode: 0644]
registration/clitkBSplinePyramidGenericFilter.h [new file with mode: 0644]
registration/clitkBSplinePyramidGenericFilter.txx [new file with mode: 0644]
registration/clitkCalculateTRE.cxx [new file with mode: 0755]
registration/clitkCalculateTRE.ggo [new file with mode: 0755]
registration/clitkCalculateTREGenericFilter.cxx [new file with mode: 0755]
registration/clitkCalculateTREGenericFilter.h [new file with mode: 0755]
registration/clitkCalculateTREGenericFilter.txx [new file with mode: 0755]
registration/clitkConvertBSplineDeformableTransformToVF.cxx [new file with mode: 0755]
registration/clitkConvertBSplineDeformableTransformToVF.ggo [new file with mode: 0755]
registration/clitkConvertBSplineDeformableTransformToVFGenericFilter.cxx [new file with mode: 0755]
registration/clitkConvertBSplineDeformableTransformToVFGenericFilter.h [new file with mode: 0755]
registration/clitkConvertPointList.cxx [new file with mode: 0755]
registration/clitkConvertPointList.ggo [new file with mode: 0755]
registration/clitkDeformationFieldTransform.h [new file with mode: 0644]
registration/clitkDeformationFieldTransform.txx [new file with mode: 0644]
registration/clitkDeformationListStatisticsFilter.h [new file with mode: 0644]
registration/clitkDeformationListStatisticsFilter.txx [new file with mode: 0644]
registration/clitkDemonsDeformableRegistration.cxx [new file with mode: 0755]
registration/clitkDemonsDeformableRegistration.ggo [new file with mode: 0755]
registration/clitkDemonsDeformableRegistrationGenericFilter.cxx [new file with mode: 0755]
registration/clitkDemonsDeformableRegistrationGenericFilter.h [new file with mode: 0755]
registration/clitkDemonsDeformableRegistrationGenericFilter.txx [new file with mode: 0755]
registration/clitkDifferenceImageFilter.h [new file with mode: 0755]
registration/clitkDifferenceImageFilter.txx [new file with mode: 0755]
registration/clitkExtractImageFilter.h [new file with mode: 0644]
registration/clitkExtractImageFilter.txx [new file with mode: 0644]
registration/clitkGenericVectorInterpolator.h [new file with mode: 0755]
registration/clitkGenericVectorInterpolator.txx [new file with mode: 0755]
registration/clitkLBFGSBOptimizer.cxx
registration/clitkLBFGSBOptimizer.h
registration/clitkLinearCombinationImageFilter.h [new file with mode: 0644]
registration/clitkLinearCombinationImageFilter.txx [new file with mode: 0644]
registration/clitkList.h [new file with mode: 0644]
registration/clitkList.txx [new file with mode: 0644]
registration/clitkLists.h [new file with mode: 0644]
registration/clitkLists.txx [new file with mode: 0644]
registration/clitkMatrixTransformToVF.cxx [new file with mode: 0755]
registration/clitkMatrixTransformToVF.ggo [new file with mode: 0755]
registration/clitkMatrixTransformToVFGenericFilter.cxx [new file with mode: 0755]
registration/clitkMatrixTransformToVFGenericFilter.h [new file with mode: 0755]
registration/clitkMatrixTransformToVFGenericFilter.txx [new file with mode: 0755]
registration/clitkMultiResolutionPDEDeformableRegistration.h [new file with mode: 0755]
registration/clitkMultiResolutionPDEDeformableRegistration.txx [new file with mode: 0755]
registration/clitkMultiResolutionPyramid.cxx [new file with mode: 0644]
registration/clitkMultiResolutionPyramid.ggo [new file with mode: 0644]
registration/clitkMultiResolutionPyramidGenericFilter.cxx [new file with mode: 0644]
registration/clitkMultiResolutionPyramidGenericFilter.h [new file with mode: 0644]
registration/clitkMultiResolutionPyramidGenericFilter.txx [new file with mode: 0644]
registration/clitkMultiResolutionPyramidRegionFilter.h [new file with mode: 0644]
registration/clitkMultiResolutionPyramidRegionFilter.txx [new file with mode: 0644]
registration/clitkPointListReader.h [new file with mode: 0644]
registration/clitkPointListReader.txx [new file with mode: 0644]
registration/clitkPointListTransform.h [new file with mode: 0644]
registration/clitkPointListTransform.txx [new file with mode: 0644]
registration/clitkPointListWriter.h [new file with mode: 0644]
registration/clitkPointListWriter.txx [new file with mode: 0644]
registration/clitkPointTrajectory.cxx [new file with mode: 0755]
registration/clitkPointTrajectory.ggo [new file with mode: 0755]
registration/clitkPointTrajectoryGenericFilter.cxx [new file with mode: 0755]
registration/clitkPointTrajectoryGenericFilter.h [new file with mode: 0755]
registration/clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.h [new file with mode: 0644]
registration/clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.txx [new file with mode: 0644]
registration/clitkResampleBSplineDeformableTransform.cxx [new file with mode: 0644]
registration/clitkResampleBSplineDeformableTransform.ggo [new file with mode: 0644]
registration/clitkResampleBSplineDeformableTransformGenericFilter.cxx [new file with mode: 0644]
registration/clitkResampleBSplineDeformableTransformGenericFilter.h [new file with mode: 0644]
registration/clitkResampleBSplineDeformableTransformGenericFilter.txx [new file with mode: 0644]
registration/clitkResampleBSplineDeformableTransformImageFilter.h [new file with mode: 0644]
registration/clitkResampleBSplineDeformableTransformImageFilter.txx [new file with mode: 0644]
registration/clitkSelectPoints.cxx [new file with mode: 0755]
registration/clitkSelectPoints.ggo [new file with mode: 0755]
registration/clitkSelectPointsGenericFilter.cxx [new file with mode: 0755]
registration/clitkSelectPointsGenericFilter.h [new file with mode: 0755]
registration/clitkShapedBLUTSpatioTemporalDIR.cxx [new file with mode: 0755]
registration/clitkShapedBLUTSpatioTemporalDIR.ggo [new file with mode: 0755]
registration/clitkShapedBLUTSpatioTemporalDIRGenericFilter.cxx [new file with mode: 0755]
registration/clitkShapedBLUTSpatioTemporalDIRGenericFilter.h [new file with mode: 0755]
registration/clitkShapedBLUTSpatioTemporalDIRGenericFilter.txx [new file with mode: 0755]
registration/clitkShapedBLUTSpatioTemporalDeformableTransform.h [new file with mode: 0755]
registration/clitkShapedBLUTSpatioTemporalDeformableTransform.txx [new file with mode: 0755]
registration/clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.h [new file with mode: 0755]
registration/clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.txx [new file with mode: 0755]
registration/clitkSpatioTemporalMultiResolutionImageRegistrationMethod.h [new file with mode: 0644]
registration/clitkSpatioTemporalMultiResolutionImageRegistrationMethod.txx [new file with mode: 0644]
registration/clitkSpatioTemporalMultiResolutionPyramidImageFilter.h [new file with mode: 0644]
registration/clitkSpatioTemporalMultiResolutionPyramidImageFilter.txx [new file with mode: 0644]
registration/clitkTransformToDeformationFieldSource.h [new file with mode: 0644]
registration/clitkTransformToDeformationFieldSource.txx [new file with mode: 0644]

index 5963898d4c61f3dd4bb2298ca5009b5094ec31df..ebefbd874efc5d643ff1d8754ffc9632be3ba3f8 100644 (file)
@@ -1,4 +1,59 @@
+############################## registration algorithms
+
 WRAP_GGO(clitkAffineRegistration_GGO_C clitkAffineRegistration.ggo)
 ADD_EXECUTABLE(clitkAffineRegistration clitkAffineRegistration.cxx clitkAffineRegistrationGenericFilter.cxx ${clitkAffineRegistration_GGO_C} clitkLBFGSBOptimizer.cxx clitkGenericAffineTransform.cxx)
 TARGET_LINK_LIBRARIES(clitkAffineRegistration clitkCommon ITKIO clitkFilters ITKNumerics ITKStatistics)
 
+WRAP_GGO(clitkDemonsDeformableRegistration_GGO_C clitkDemonsDeformableRegistration.ggo)
+ADD_EXECUTABLE(clitkDemonsDeformableRegistration clitkDemonsDeformableRegistration.cxx ${clitkDemonsDeformableRegistration_GGO_C} clitkDemonsDeformableRegistrationGenericFilter.cxx)
+TARGET_LINK_LIBRARIES(clitkDemonsDeformableRegistration ITKNumerics ITKIO clitkCommon)
+
+WRAP_GGO(clitkBLUTDIR_GGO_C clitkBLUTDIR.ggo)
+ADD_EXECUTABLE(clitkBLUTDIR  clitkBLUTDIR.cxx clitkBLUTDIRGenericFilter.cxx ${clitkBLUTDIR_GGO_C} clitkLBFGSBOptimizer.cxx )
+TARGET_LINK_LIBRARIES(clitkBLUTDIR clitkCommon ITKIO ITKNumerics ITKStatistics)
+
+WRAP_GGO(clitkShapedBLUTSpatioTemporalDIR_GGO_C clitkShapedBLUTSpatioTemporalDIR.ggo)
+ADD_EXECUTABLE(clitkShapedBLUTSpatioTemporalDIR  clitkShapedBLUTSpatioTemporalDIR.cxx clitkShapedBLUTSpatioTemporalDIRGenericFilter.cxx  ${clitkShapedBLUTSpatioTemporalDIR_GGO_C} clitkLBFGSBOptimizer.cxx)
+TARGET_LINK_LIBRARIES(clitkShapedBLUTSpatioTemporalDIR clitkCommon ITKNumerics ITKStatistics ITKIO)
+
+WRAP_GGO(clitkBSplineDeformableRegistration_GGO_C clitkBSplineDeformableRegistration.ggo)
+ADD_EXECUTABLE(clitkBSplineDeformableRegistration clitkBSplineDeformableRegistration.cxx clitkBSplineDeformableRegistrationGenericFilter.cxx  ${clitkBSplineDeformableRegistration_GGO_C} clitkLBFGSBOptimizer.cxx)
+TARGET_LINK_LIBRARIES(clitkBSplineDeformableRegistration  clitkCommon ITKNumerics ITKStatistics ITKIO)
+
+
+############################## registration-related tools to process points, bsplines, vf and image pyramids
+WRAP_GGO(clitkConvertPointList_GGO_C clitkConvertPointList.ggo)
+ADD_EXECUTABLE(clitkConvertPointList clitkConvertPointList.cxx  ${clitkConvertPointList_GGO_C})
+TARGET_LINK_LIBRARIES(clitkConvertPointList ITKIO clitkCommon )
+
+WRAP_GGO(clitkSelectPoints_GGO_C clitkSelectPoints.ggo)
+ADD_EXECUTABLE(clitkSelectPoints clitkSelectPoints.cxx clitkSelectPointsGenericFilter.cxx  ${clitkSelectPoints_GGO_C})
+TARGET_LINK_LIBRARIES(clitkSelectPoints clitkCommon ITKIO)
+
+WRAP_GGO(clitkPointTrajectory_GGO_C clitkPointTrajectory.ggo)
+ADD_EXECUTABLE(clitkPointTrajectory  clitkPointTrajectory.cxx clitkPointTrajectoryGenericFilter.cxx  ${clitkPointTrajectory_GGO_C})
+TARGET_LINK_LIBRARIES(clitkPointTrajectory clitkCommon ITKIO)
+
+WRAP_GGO(clitkCalculateTRE_GGO_C clitkCalculateTRE.ggo)
+ADD_EXECUTABLE(clitkCalculateTRE clitkCalculateTRE.cxx clitkCalculateTREGenericFilter.cxx ${clitkCalculateTRE_GGO_C})
+TARGET_LINK_LIBRARIES(clitkCalculateTRE clitkCommon ITKIO )
+
+WRAP_GGO(clitkMatrixTransformToVF_GGO_C clitkMatrixTransformToVF.ggo)
+ADD_EXECUTABLE(clitkMatrixTransformToVF clitkMatrixTransformToVF.cxx clitkMatrixTransformToVFGenericFilter.cxx  ${clitkMatrixTransformToVF_GGO_C})
+TARGET_LINK_LIBRARIES(clitkMatrixTransformToVF ITKIO clitkCommon)
+
+WRAP_GGO(clitkConvertBSplineDeformableTransformToVF_GGO_C clitkConvertBSplineDeformableTransformToVF.ggo)
+ADD_EXECUTABLE(clitkConvertBSplineDeformableTransformToVF  clitkConvertBSplineDeformableTransformToVF.cxx clitkConvertBSplineDeformableTransformToVFGenericFilter.cxx  ${clitkConvertBSplineDeformableTransformToVF_GGO_C})
+TARGET_LINK_LIBRARIES(clitkConvertBSplineDeformableTransformToVF clitkCommon  ITKIO)
+
+WRAP_GGO(clitkMultiResolutionPyramid_GGO_C clitkMultiResolutionPyramid.ggo)
+ADD_EXECUTABLE(clitkMultiResolutionPyramid  clitkMultiResolutionPyramid.cxx clitkMultiResolutionPyramidGenericFilter.cxx ${clitkMultiResolutionPyramid_GGO_C})
+TARGET_LINK_LIBRARIES(clitkMultiResolutionPyramid clitkCommon  ITKIO)
+
+WRAP_GGO(clitkBSplinePyramid_GGO_C clitkBSplinePyramid.ggo)
+ADD_EXECUTABLE(clitkBSplinePyramid  clitkBSplinePyramid.cxx clitkBSplinePyramidGenericFilter.cxx ${clitkBSplinePyramid_GGO_C})
+TARGET_LINK_LIBRARIES(clitkBSplinePyramid  clitkCommon  ITKIO)
+
+WRAP_GGO(clitkResampleBSplineDeformableTransform_GGO_C clitkResampleBSplineDeformableTransform.ggo)
+ADD_EXECUTABLE(clitkResampleBSplineDeformableTransform  clitkResampleBSplineDeformableTransform.cxx clitkResampleBSplineDeformableTransformGenericFilter.cxx ${clitkResampleBSplineDeformableTransform_GGO_C})
+TARGET_LINK_LIBRARIES(clitkResampleBSplineDeformableTransform clitkCommon ITKIO)
index 6c268785eec01c9a80102f343c6f01e9077de23d..a5d03855baeda66222ffa60e0692d69b62b6d867 100644 (file)
@@ -1,7 +1,7 @@
 # file clitkAffineRegistration.ggo
 package "clitk"
 version "1.0"
-purpose "Compute an affine registration between two images." 
+purpose "Perform an affine registration between two images." 
 
 option "config"                -       "Config file"                   string          no
 
@@ -12,7 +12,7 @@ option "gradient"     -       "If verbose, show gradient at each iteration"   flag    off
 option "threads"       -       "Number of threads to use  (default=min(#cores,8))"     int      no
 
 
-section "Input (Both images have to be of the same dimension (2 or 3D). For 2D-3D registrations, give the 2D image a third dimension of 1 and set it to the reference image.)"
+section "Input (Both images have to be of the same dimension (2 or 3D). For 2D-3D (non-projective) registrations, give the 2D image a third dimension of 1 and set it to the reference image.)"
 
 option "reference"     i       "Reference or fixed image filename"             string  yes
 option "target"        j       "Target or moving image filename"               string  yes
@@ -54,7 +54,7 @@ option "subtractMean" -       "1: Subtract mean for NCC calculation (narrows opt
 option "bins"          -       "2,5-8: Number of histogram bins"                                                                       int     no      default="50"
 option "random"        -       "4,6: Samples should be taken randomly, otherwise uniformly"                                            flag    off     
 option "stdDev"                -       "4: specify the standard deviation in mm of the gaussian kernels for both PDF estimations"              float   no      default="0.4"   
-option "explicitPDFDerivatives"        -       "6: Calculate PDF derivatives explicitly (rigid=true; FFD=false)"                               flag    on
+option "explicitPDFDerivatives"        -       "6: Calculate PDF derivatives explicitly (affine=true; FFD=false)"                              flag    on
 
 
 section "Preprocessing"
@@ -82,7 +82,7 @@ option "selectBound"  -       "7: Select the type of bound: 0=none, 1=u, 2=u&l, 3=l"
 option "lowerBound"    -       "7: The lower bound"                                                    double  no      
 option "upperBound"    -       "7: The upper bound"                                                    double  no      
 
-option "rWeight"       -       "Weight of 1° of rotation during optimisation (high weight, less change)"            float   no      default="50.0"
+option "rWeight"       -       "Weight of 1° of rotation during optimisation (high weight, less change)"              float   no      default="50.0"
 option "tWeight"       -       "Weight of 1mm of translation  during optimisation (high weight, less change)"          float   no      default="1.0"
 option "levels"                -       "Number of resolution levels"                                                           int     no      default="1"                                             
 option "inc"           -       "Increment factor (x)  previous step/tol = new step/tol at next resolution level"       float   no      default="1.2"
diff --git a/registration/clitkBLUTDIR.cxx b/registration/clitkBLUTDIR.cxx
new file mode 100755 (executable)
index 0000000..2570b7b
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkBLUTDIR.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkBLUTDIR_ggo.h"
+#include "clitkIO.h"
+#include "clitkBLUTDIRGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkBLUTDIR, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::BLUTDIRGenericFilter::Pointer genericFilter=clitk::BLUTDIRGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkBLUTDIR.ggo b/registration/clitkBLUTDIR.ggo
new file mode 100755 (executable)
index 0000000..152c67f
--- /dev/null
@@ -0,0 +1,87 @@
+#File clitkBLUTDIR.ggo
+#Author: Jef Vandemeulebroucke <jefvdmb@gmail.com>
+#Date : Tue 11 Jan 2009 10.35 
+
+Package "clitk"
+Version "Register 2 images using optimized BLUT FFD..."
+
+option "config"                -       "Config file"                   string          no
+
+
+section "Run Time"
+
+option "verbose"       v       "Verbose"                       flag            off
+option "threads"       -       "Number of threads to use (default=min(#cores,8))"      int      no
+
+
+section "Input"
+
+option "reference"             r       "Input reference 3D image (float)"      string          yes
+option "target"                        t       "Input target    2D image (float)"      string          yes
+option "referenceMask"                 m       "Mask to placed over the reference image"                 string                no
+option "targetMask"            -       "Mask to placed over the target image"            string                no
+
+section "Output"
+
+option "vf"                    -       "Result DVF"                            string          yes
+option "coeff"                 -       "Result coefficient images"             string          no      
+option "output"                        o       "Deformed target image"                 string          yes
+option "before"                        -       "Difference image before (but after rigid transform)"           string          no
+option "after"                 -       "Difference image after "               string          no
+
+
+section "Transform (Note that only one of --control, --spacing is required. The other will be adjusted to fit the region and allow exact representation. SamplingFactor will be set accordingly"
+
+option "initMatrix"            -       "Prior rigid/affine transform matrix from reference to target space"    string          no      
+option "initCoeff"             -       "Initial coefficient image"                                             string          no
+option "order"                 -       "Spline Order FFD"                                              int       no    multiple        default="3"
+option "control"               -       "Internal control points for each dimension"                    int       no    multiple        
+option "spacing"               -       "Control point spacing for each dimension (mm)"                 double    no    multiple        
+option "samplingFactor"                -       "LUT sampling factor"                                           int       no    multiple        
+
+
+section "Interpolator"
+
+option "interp"                -       "Interpolation: 0=NN, 1=Linear, 2=BSpline, 3=BLUT"      int     no  default="1"
+option "interpOrder"   -       "Order if BLUT or BSpline (0-5)"                        int     no  default="3"
+option "interpSF"      -       "Sampling factor if BLUT"                               int     no  default="20"
+
+
+
+section "Metric (optimized, threaded versions are available for *, compile ITK with REVIEW and OPT_REGISTRATION enabled. Further optimized versions ** for  BLUT FFD optimizing a !3D! vector field)"
+
+option "metric"        -       "Type: 0=SSD*, 1=Normalized CC*, 2=Histogram CC, 3=Gradient-Difference, 4=Viola-Wells MI, 5=Histogram MI, 6=Mattes' MI*, 7=Normalized MI, 8=CR, 9=SSD for BLUT FFD**, 10=CC for BLUT FFD**, 11=Mattes' MI for BLUT FFD**"       int     no      default="0"
+option "samples"       -       "Specify fraction [0, 1] of samples of the reference image used for the metric (* only). Use high fraction for detailed images (eg. 0.2, 0.5), for smooth images 0.01 might be enough." float   no      default="1"
+option "intThreshold"  -       "Fixed image samples intensity threshold (* only)"                                                      float   no              
+option "subtractMean"  -       "1: Subtract mean for NCC calculation (narrows optimal)"                                                flag    on      
+option "bins"          -       "2,5-8: Number of histogram bins"                                                                       int     no      default="50"
+option "random"        -       "4,6: Samples should be taken randomly, otherwise uniformly"                                            flag    off     
+option "stdDev"                -       "4: specify the standard deviation in mm of the gaussian kernels for both PDF estimations"              float   no      default="0.4"   
+option "explicitPDFDerivatives"        -       "6: Calculate PDF derivatives explicitly (rigid=true; FFD=false)"                               flag    off
+
+
+section "Optimizer"
+
+option "optimizer"     -       "0=Simplex, 1=Powell, 2=FRPR, 3=Regular Step GD, 4=VersorRigid3D, 5=Conjugated Gradient, 6=L-BFGS, 7=L-BFGS-B" int no default="7" 
+option "delta"         -       "0: Initial delta, otherwise automatic"                                                 double  no                      
+option "step"          -       "1,2,3,4: Initial stepsize (to be multiplied with the gradient)"                        double  no      default="2.0"   
+option "relax"                 -       "3,4: Relaxation of the stepsize (multiplied each time the gradient changes sign)"      double  no      default="0.7"
+option "valueTol"      -       "0,1,2: Tolerance on the function"                                                      double  no      default="0.01"
+option "stepTol"       -       "0,1,3,4: Tolerance on the step size"                                                   double  no      default="0.1"
+option "gradTol"       -       "3,4,6,7: Tolerance on the (projected) gradient magnitude (7: 1=low->1e-10=high precision)"     double  no      default="1e-5"                  
+option "lineAcc"       -       "6: Line accuracy (eg: high=0.1, low=0.9)"      double  no      default="0.9"
+option "convFactor"    -       "7: Convergence factor: terminate if factor*machine_precision>reduction in cost (1e+12 low -> 1e+1 high precision) "    double          no      default="1e+7"
+option "maxIt"         -       "0-7: Maximum number of iterations"                                     int     no      default="500"
+option "maxLineIt"     -       "1,2: Maximum number of line iterations"                                        int     no      default="50"    
+option "maxEval"       -       "6,7: Maximum number of evaluations"                                            int     no      default="500"
+option "maxCorr"       -       "7: Maximum number of corrections"                                              int     no      default="5"
+option "selectBound"   -       "7: Select the type of bound: 0=none, 1=u, 2=u&l, 3=l"                  int     no      default="0"
+option "lowerBound"    -       "7: The lower bound"                                                    double  no      default="0.0"
+option "upperBound"    -       "7: The upper bound"                                                    double  no      default="0.0"
+
+
+Section "Registration"
+
+option "levels"                -       "Number of resolution levels"                                   int     no      default="1"                                             
+option "intermediate"          -       "Write the coefficient image of the intermediate levels (provide levels filenames)"                                     string  no      multiple                                                
+
diff --git a/registration/clitkBLUTDIRGenericFilter.cxx b/registration/clitkBLUTDIRGenericFilter.cxx
new file mode 100755 (executable)
index 0000000..c728fcd
--- /dev/null
@@ -0,0 +1,73 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkBLUTDIRGenericFilter_cxx
+#define clitkBLUTDIRGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkBLUTDIRGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkBLUTDIRGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  BLUTDIRGenericFilter::BLUTDIRGenericFilter()
+  {
+    m_Verbose=false;
+    m_ReferenceFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void BLUTDIRGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_ReferenceFileName, Dimension, PixelType);
+
+    
+    // Call UpdateWithDim
+    //if(Dimension==2) UpdateWithDim<2>(PixelType);
+    //else 
+    if(Dimension==3) UpdateWithDim<3>(PixelType);
+    // else if (Dimension==4)UpdateWithDim<4>(PixelType); 
+    else 
+      {
+       std::cout<<"Error, Only for 2 or 3  Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkBLUTDIRGenericFilter_cxx
diff --git a/registration/clitkBLUTDIRGenericFilter.h b/registration/clitkBLUTDIRGenericFilter.h
new file mode 100755 (executable)
index 0000000..af0efe8
--- /dev/null
@@ -0,0 +1,139 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkBLUTDIRGenericFilter_h
+#define clitkBLUTDIRGenericFilter_h
+
+/* =================================================
+ * @file   clitkBLUTDIRGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkBLUTDIR_ggo.h"
+#include "clitkIO.h"
+#include "clitkImageCommon.h"
+#include "clitkDifferenceImageFilter.h"
+#include "clitkTransformUtilities.h"
+#include "clitkLBFGSBOptimizer.h"
+#include "clitkBSplineDeformableTransform.h"
+#include "clitkGenericOptimizer.h"
+#include "clitkGenericInterpolator.h"
+#include "clitkGenericMetric.h"
+#include "clitkBSplineDeformableTransformInitializer.h"
+#include "clitkMultiResolutionPyramidRegionFilter.h"
+
+// itk include
+#include "itkMultiResolutionImageRegistrationMethod.h"
+#include "itkMultiResolutionPyramidImageFilter.h"
+#include "itkImage.h"
+#include "itkImageFileReader.h"
+#include "itkImageFileWriter.h"
+#include "itkResampleImageFilter.h"
+#include "itkCommand.h"
+#include "itkImageMaskSpatialObject.h"
+#include "itkEuler3DTransform.h"
+#include "itkWarpImageFilter.h"
+#include "itkLightObject.h"
+#include "itkImageToImageMetric.h"
+#include "itkInterpolateImageFunction.h"
+#include "itkLabelStatisticsImageFilter.h"
+#include "itkImageDuplicator.h"
+#include "itkExtractImageFilter.h"
+#include "itkTransformToDeformationFieldSource.h"
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT BLUTDIRGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef BLUTDIRGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( BLUTDIRGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkBLUTDIR & a)
+    {
+      m_ArgsInfo=a;
+      m_ReferenceFileName=m_ArgsInfo.reference_arg;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    BLUTDIRGenericFilter();
+    ~BLUTDIRGenericFilter() {};
+
+    
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <unsigned int Dimension>  void UpdateWithDim(std::string PixelType);
+    template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkBLUTDIR m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_ReferenceFileName;
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkBLUTDIRGenericFilter.txx"
+#endif
+
+#endif // #define clitkBLUTDIRGenericFilter_h
diff --git a/registration/clitkBLUTDIRGenericFilter.txx b/registration/clitkBLUTDIRGenericFilter.txx
new file mode 100755 (executable)
index 0000000..08f0d74
--- /dev/null
@@ -0,0 +1,848 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkBLUTDIRGenericFilter_txx
+#define clitkBLUTDIRGenericFilter_txx
+
+/* =================================================
+ * @file   clitkBLUTDIRGenericFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkBLUTDIRGenericFilter.h"
+
+namespace clitk
+{
+
+  //==============================================================================
+  // Creating an observer class that allows output at each iteration
+  //==============================================================================
+  class CommandIterationUpdate : public itk::Command 
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<Self>  Pointer;
+    itkNewMacro( Self );
+  protected:
+    CommandIterationUpdate() {};
+  public:
+    typedef   clitk::GenericOptimizer<args_info_clitkBLUTDIR>     OptimizerType;
+    typedef   const OptimizerType   *           OptimizerPointer;
+  
+    // Set the generic optimizer
+    void SetOptimizer(OptimizerPointer o){m_Optimizer=o;}
+    
+    // Execute
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+    {
+      Execute( (const itk::Object *)caller, event);
+    }
+  
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+    {  
+      if( !(itk::IterationEvent().CheckEvent( &event )) )
+       {
+         return;
+       }
+      
+      m_Optimizer->OutputIterationInfo();
+    }
+
+    OptimizerPointer m_Optimizer;
+  };
+
+
+  //==============================================================================
+  //Creating an observer class that allows us to change parameters at subsequent levels
+  //==============================================================================
+  template <typename TRegistration, class args_info_clitkBLUTDIR>
+  class RegistrationInterfaceCommand : public itk::Command 
+  {
+  public:
+    typedef RegistrationInterfaceCommand   Self;
+    typedef itk::Command             Superclass;
+    typedef itk::SmartPointer<Self>  Pointer;
+    itkNewMacro( Self );
+  protected:
+    RegistrationInterfaceCommand() {};
+  public:
+
+    // Registration
+    typedef   TRegistration                              RegistrationType;
+    typedef   RegistrationType *                         RegistrationPointer;
+
+    // Transform
+    typedef typename RegistrationType::FixedImageType FixedImageType;
+    typedef typename FixedImageType::RegionType RegionType;
+    itkStaticConstMacro(ImageDimension, unsigned int,FixedImageType::ImageDimension); 
+    typedef clitk::BSplineDeformableTransform<double, ImageDimension, ImageDimension> TransformType;
+    typedef clitk::BSplineDeformableTransformInitializer<TransformType, FixedImageType> InitializerType;
+    typedef typename InitializerType::CoefficientImageType CoefficientImageType;
+    typedef itk::CastImageFilter<CoefficientImageType, CoefficientImageType> CastImageFilterType;
+    typedef typename TransformType::ParametersType ParametersType;
+    typedef typename InitializerType::Pointer InitializerPointer;
+    typedef   CommandIterationUpdate::Pointer CommandIterationUpdatePointer;
+
+    // Optimizer
+    typedef clitk::GenericOptimizer<args_info_clitkBLUTDIR> GenericOptimizerType;
+    typedef typename GenericOptimizerType::Pointer GenericOptimizerPointer;
+
+    // Metric
+    typedef typename RegistrationType::FixedImageType    InternalImageType;
+    typedef clitk::GenericMetric<args_info_clitkBLUTDIR, InternalImageType, InternalImageType> GenericMetricType;
+    typedef typename GenericMetricType::Pointer GenericMetricPointer;
+
+    // Two arguments are passed to the Execute() method: the first
+    // is the pointer to the object which invoked the event and the 
+    // second is the event that was invoked.
+    void Execute(itk::Object * object, const itk::EventObject & event)
+    {
+      if( !(itk::IterationEvent().CheckEvent( &event )) )
+       {
+         return;
+       }
+
+      // Get the levels
+      RegistrationPointer registration = dynamic_cast<RegistrationPointer>( object );
+      unsigned int numberOfLevels=registration->GetNumberOfLevels();
+      unsigned int currentLevel=registration->GetCurrentLevel()+1;
+
+      // Output the levels
+      std::cout<<std::endl;
+      std::cout<<"========================================"<<std::endl;
+      std::cout<<"Starting resolution level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
+      std::cout<<"========================================"<<std::endl;        
+      std::cout<<std::endl;
+
+      // Higher level?
+      if (currentLevel>1)
+       {
+         // fixed image region pyramid
+         typedef clitk::MultiResolutionPyramidRegionFilter<InternalImageType> FixedImageRegionPyramidType;
+         typename FixedImageRegionPyramidType::Pointer fixedImageRegionPyramid=FixedImageRegionPyramidType::New();
+         fixedImageRegionPyramid->SetRegion(m_MetricRegion);
+         fixedImageRegionPyramid->SetSchedule(registration->GetFixedImagePyramid()->GetSchedule());
+
+         // Reinitialize the metric (!= number of samples)
+         m_GenericMetric= GenericMetricType::New();
+         m_GenericMetric->SetArgsInfo(m_ArgsInfo);
+         m_GenericMetric->SetFixedImage(registration->GetFixedImagePyramid()->GetOutput(registration->GetCurrentLevel()));
+         if (m_ArgsInfo.referenceMask_given)  m_GenericMetric->SetFixedImageMask(registration->GetMetric()->GetFixedImageMask());
+         m_GenericMetric->SetFixedImageRegion(fixedImageRegionPyramid->GetOutput(registration->GetCurrentLevel()));
+         typedef itk::ImageToImageMetric< InternalImageType, InternalImageType >  MetricType;
+         typename  MetricType::Pointer metric=m_GenericMetric->GetMetricPointer();
+         registration->SetMetric(metric);      
+
+         // Get the current coefficient image and make a COPY
+         typename itk::ImageDuplicator<CoefficientImageType>::Pointer caster=itk::ImageDuplicator<CoefficientImageType>::New();
+         caster->SetInputImage(m_Initializer->GetTransform()->GetCoefficientImage());
+         caster->Update();
+         typename CoefficientImageType::Pointer currentCoefficientImage=caster->GetOutput();
+
+         // Write the intermediate result?
+         if (m_ArgsInfo.intermediate_given>=numberOfLevels)
+           writeImage<CoefficientImageType>(currentCoefficientImage, m_ArgsInfo.intermediate_arg[currentLevel-2], m_ArgsInfo.verbose_flag);
+         
+         // Set the new transform properties
+         m_Initializer->SetImage(registration->GetFixedImagePyramid()->GetOutput(currentLevel-1));
+         if( m_Initializer->m_ControlPointSpacingIsGiven) 
+           m_Initializer->SetControlPointSpacing(m_Initializer->m_ControlPointSpacingArray[registration->GetCurrentLevel()]);
+         if( m_Initializer->m_NumberOfControlPointsIsGiven) 
+           m_Initializer->SetNumberOfControlPointsInsideTheImage(m_Initializer->m_NumberOfControlPointsInsideTheImageArray[registration->GetCurrentLevel()]);
+  
+         // Reinitialize the transform
+         if (m_ArgsInfo.verbose_flag) std::cout<<"Initializing transform for level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
+         m_Initializer->InitializeTransform();
+         ParametersType* newParameters= new typename TransformType::ParametersType(m_Initializer->GetTransform()->GetNumberOfParameters());
+
+         // Reinitialize an Optimizer (!= number of parameters)
+         m_GenericOptimizer = GenericOptimizerType::New();
+         m_GenericOptimizer->SetArgsInfo(m_ArgsInfo);
+         m_GenericOptimizer->SetMaximize(m_Maximize);
+         m_GenericOptimizer->SetNumberOfParameters(m_Initializer->GetTransform()->GetNumberOfParameters());
+         typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
+         OptimizerType::Pointer optimizer = m_GenericOptimizer->GetOptimizerPointer();
+         optimizer->AddObserver( itk::IterationEvent(), m_CommandIterationUpdate);
+         registration->SetOptimizer(optimizer);                                                  
+         m_CommandIterationUpdate->SetOptimizer(m_GenericOptimizer);
+         
+         // Set the previous transform parameters to the registration
+         // if(m_Initializer->m_Parameters!=NULL )delete m_Initializer->m_Parameters;
+         m_Initializer->SetInitialParameters(currentCoefficientImage,*newParameters); 
+         registration->SetInitialTransformParametersOfNextLevel(*newParameters);  
+       }
+    }
+
+    void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+
+
+    // Members
+    void SetInitializer(InitializerPointer i){m_Initializer=i;}
+    InitializerPointer m_Initializer;
+
+    void SetArgsInfo(args_info_clitkBLUTDIR a){m_ArgsInfo=a;}
+    args_info_clitkBLUTDIR m_ArgsInfo;
+
+    void SetCommandIterationUpdate(CommandIterationUpdatePointer c){m_CommandIterationUpdate=c;};
+    CommandIterationUpdatePointer m_CommandIterationUpdate;
+
+    GenericOptimizerPointer m_GenericOptimizer;
+    void SetMaximize(bool b){m_Maximize=b;}
+    bool m_Maximize;
+
+    GenericMetricPointer m_GenericMetric;
+    void SetMetricRegion(RegionType i){m_MetricRegion=i;}
+    RegionType m_MetricRegion;
+    
+  };
+
+
+  //==============================================================================
+  // Update with the number of dimensions
+  //==============================================================================
+  template<unsigned int Dimension>
+  void BLUTDIRGenericFilter::UpdateWithDim(std::string PixelType)
+  {
+    if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<< PixelType<<"..."<<std::endl;
+
+    if(PixelType == "short"){  
+      if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, signed short>(); 
+    }
+    //    else if(PixelType == "unsigned_short"){  
+    //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, unsigned short>(); 
+    //     }
+    
+    //     else if (PixelType == "unsigned_char"){ 
+    //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, unsigned char>();
+    //     }
+    
+    //     else if (PixelType == "char"){ 
+    //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, signed char>();
+    //    }
+    else {
+      if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, float>();
+    }
+  }
+
+
+  //==============================================================================
+  // Update with the number of dimensions and pixeltype
+  //==============================================================================
+  template<unsigned int ImageDimension, class PixelType>
+  void 
+  BLUTDIRGenericFilter::UpdateWithDimAndPixelType()
+  {
+
+
+    //=============================================================================
+    //Input
+    //=============================================================================
+    bool threadsGiven=m_ArgsInfo.threads_given;
+    int threads=m_ArgsInfo.threads_arg;
+    
+    typedef itk::Image< PixelType, ImageDimension >  FixedImageType;
+    typedef itk::Image< PixelType, ImageDimension >  MovingImageType;
+    const unsigned int SpaceDimension = ImageDimension;
+    typedef double TCoordRep;
+
+
+    //=======================================================
+    //Input
+    //=======================================================
+    typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
+    typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;
+
+    typename FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
+    typename MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();
+
+    fixedImageReader->SetFileName(  m_ArgsInfo.reference_arg );
+    movingImageReader->SetFileName( m_ArgsInfo.target_arg );
+    if (m_Verbose) std::cout<<"Reading images..."<<std::endl;
+    fixedImageReader->Update();
+    movingImageReader->Update();
+
+    typename FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+    typename MovingImageType::Pointer movingImage =movingImageReader->GetOutput();
+    typename FixedImageType::Pointer croppedFixedImage=fixedImage;
+
+
+    //=======================================================
+    // Regions
+    //=======================================================
+
+    // The original input region    
+    typename FixedImageType::RegionType fixedImageRegion = fixedImage->GetLargestPossibleRegion();
+
+    // The transform region with respect to the input region:
+    // where should the transform be DEFINED (depends on mask)
+    typename FixedImageType::RegionType transformRegion = fixedImage->GetLargestPossibleRegion();
+    typename FixedImageType::RegionType::SizeType transformRegionSize=transformRegion.GetSize();
+    typename FixedImageType::RegionType::IndexType transformRegionIndex=transformRegion.GetIndex();
+    typename FixedImageType::PointType transformRegionOrigin=fixedImage->GetOrigin();
+
+    // The metric region with respect to the extracted transform region: 
+    // where should the metric be CALCULATED (depends on transform)
+    typename FixedImageType::RegionType metricRegion = fixedImage->GetLargestPossibleRegion();
+    typename FixedImageType::RegionType::SizeType metricRegionSize=metricRegion.GetSize();
+    typename FixedImageType::RegionType::IndexType metricRegionIndex=metricRegion.GetIndex();
+    typename FixedImageType::PointType metricRegionOrigin=fixedImage->GetOrigin();
+    
+
+    //===========================================================================
+    // If given, we connect a mask to reference or target
+    //============================================================================
+    typedef itk::ImageMaskSpatialObject<  ImageDimension >   MaskType;
+    typename MaskType::Pointer  fixedMask=NULL;
+    if (m_ArgsInfo.referenceMask_given)
+      {
+       fixedMask= MaskType::New();
+       typedef itk::Image< unsigned char, ImageDimension >   ImageMaskType;
+       typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
+       typename MaskReaderType::Pointer  maskReader = MaskReaderType::New();
+       maskReader->SetFileName(m_ArgsInfo.referenceMask_arg);
+       try 
+         { 
+           maskReader->Update(); 
+         } 
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught while reading mask !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         } 
+       if (m_Verbose)std::cout <<"Reference image mask was read..." <<std::endl;
+
+       // Set the image to the spatialObject
+       fixedMask->SetImage( maskReader->GetOutput() );
+
+       // Find the bounding box of the "inside" label
+       typedef itk::LabelStatisticsImageFilter<ImageMaskType, ImageMaskType> StatisticsImageFilterType;
+       typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New();
+       statisticsImageFilter->SetInput(maskReader->GetOutput());
+       statisticsImageFilter->SetLabelInput(maskReader->GetOutput());
+       statisticsImageFilter->Update();
+       typename StatisticsImageFilterType::BoundingBoxType boundingBox = statisticsImageFilter->GetBoundingBox(1);
+
+       // Limit the transform region to the mask
+       for (unsigned int i=0; i<ImageDimension; i++)
+         {
+           transformRegionIndex[i]=boundingBox[2*i];
+           transformRegionSize[i]=boundingBox[2*i+1]-boundingBox[2*i]+1;
+         }
+       transformRegion.SetSize(transformRegionSize);
+       transformRegion.SetIndex(transformRegionIndex);
+       fixedImage->TransformIndexToPhysicalPoint(transformRegion.GetIndex(), transformRegionOrigin);
+       
+       // Crop the fixedImage to the bounding box to facilitate multi-resolution 
+       typedef itk::ExtractImageFilter<FixedImageType,FixedImageType> ExtractImageFilterType; 
+       typename ExtractImageFilterType::Pointer extractImageFilter=ExtractImageFilterType::New();
+       extractImageFilter->SetInput(fixedImage);
+       extractImageFilter->SetExtractionRegion(transformRegion);
+       extractImageFilter->Update();
+       croppedFixedImage=extractImageFilter->GetOutput();
+
+       // Update the metric region     
+       metricRegion = croppedFixedImage->GetLargestPossibleRegion();
+       metricRegionIndex=metricRegion.GetIndex();
+       croppedFixedImage->TransformIndexToPhysicalPoint(metricRegionIndex, metricRegionOrigin);
+
+       // Set start index to zero (with respect to croppedFixedImage/transform region)
+       metricRegionIndex.Fill(0);
+       metricRegion.SetIndex(metricRegionIndex);
+       croppedFixedImage->SetRegions(metricRegion);
+       croppedFixedImage->SetOrigin(metricRegionOrigin);
+      }
+
+    typedef itk::ImageMaskSpatialObject<  ImageDimension >   MaskType;
+    typename MaskType::Pointer  movingMask=NULL;
+    if (m_ArgsInfo.targetMask_given)
+      {
+       movingMask= MaskType::New();
+       typedef itk::Image< unsigned char, ImageDimension >   ImageMaskType;
+       typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
+       typename MaskReaderType::Pointer  maskReader = MaskReaderType::New();
+       maskReader->SetFileName(m_ArgsInfo.targetMask_arg);
+       try 
+         { 
+           maskReader->Update(); 
+         } 
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught !" << std::endl; 
+           std::cerr << err << std::endl; 
+         } 
+       if (m_Verbose)std::cout <<"Target image mask was read..." <<std::endl;
+       
+       movingMask->SetImage( maskReader->GetOutput() );
+      }
+
+
+    //=======================================================
+    // Output Regions
+    //=======================================================
+
+    if (m_Verbose)
+      {
+       // Fixed image region
+       std::cout<<"The fixed image has its origin at "<<fixedImage->GetOrigin()<<std::endl 
+                <<"The fixed image region starts at index "<<fixedImageRegion.GetIndex()<<std::endl
+                <<"The fixed image region has size "<< fixedImageRegion.GetSize()<<std::endl;
+
+       // Transform region
+       std::cout<<"The transform has its origin at "<<transformRegionOrigin<<std::endl 
+                <<"The transform region will start at index "<<transformRegion.GetIndex()<<std::endl
+                <<"The transform region has size "<< transformRegion.GetSize()<<std::endl;
+
+       // Metric region
+       std::cout<<"The metric region has its origin at "<<metricRegionOrigin<<std::endl 
+                <<"The metric region will start at index "<<metricRegion.GetIndex()<<std::endl
+                <<"The metric region has size "<< metricRegion.GetSize()<<std::endl;
+       
+      }  
+
+
+    //=======================================================
+    // Pyramids (update them for transform initializer)
+    //=======================================================
+    typedef itk::RecursiveMultiResolutionPyramidImageFilter< FixedImageType, FixedImageType>    FixedImagePyramidType;
+    typedef itk::RecursiveMultiResolutionPyramidImageFilter< MovingImageType, MovingImageType>    MovingImagePyramidType;
+    typename FixedImagePyramidType::Pointer fixedImagePyramid = FixedImagePyramidType::New();
+    typename MovingImagePyramidType::Pointer movingImagePyramid = MovingImagePyramidType::New();
+    fixedImagePyramid->SetUseShrinkImageFilter(false);
+    fixedImagePyramid->SetInput(croppedFixedImage);
+    fixedImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
+    movingImagePyramid->SetUseShrinkImageFilter(false);    
+    movingImagePyramid->SetInput(movingImage);
+    movingImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
+    if (m_Verbose) std::cout<<"Creating the image pyramid..."<<std::endl;
+    fixedImagePyramid->Update();
+    movingImagePyramid->Update();
+    typedef clitk::MultiResolutionPyramidRegionFilter<FixedImageType> FixedImageRegionPyramidType;
+    typename FixedImageRegionPyramidType::Pointer fixedImageRegionPyramid=FixedImageRegionPyramidType::New();
+    fixedImageRegionPyramid->SetRegion(metricRegion);
+    fixedImageRegionPyramid->SetSchedule(fixedImagePyramid->GetSchedule());
+
+
+    //=======================================================
+    // Rigid or Affine Transform
+    //=======================================================
+    typedef itk::AffineTransform <double,3> RigidTransformType;
+    RigidTransformType::Pointer rigidTransform=NULL;
+    if (m_ArgsInfo.initMatrix_given)
+      {
+       if(m_Verbose) std::cout<<"Reading the prior transform matrix "<< m_ArgsInfo.initMatrix_arg<<"..."<<std::endl;
+       rigidTransform=RigidTransformType::New();
+       itk::Matrix<double,4,4> rigidTransformMatrix=clitk::ReadMatrix3D(m_ArgsInfo.initMatrix_arg);
+       
+       //Set the rotation
+       itk::Matrix<double,3,3> finalRotation = clitk::GetRotationalPartMatrix3D(rigidTransformMatrix);
+       rigidTransform->SetMatrix(finalRotation);
+       
+       //Set the translation
+       itk::Vector<double,3> finalTranslation = clitk::GetTranslationPartMatrix3D(rigidTransformMatrix);
+       rigidTransform->SetTranslation(finalTranslation);
+      }
+
+
+    //=======================================================
+    // B-LUT FFD Transform
+    //=======================================================
+    typedef  clitk::BSplineDeformableTransform<TCoordRep,ImageDimension, SpaceDimension > TransformType;
+    typename TransformType::Pointer transform= TransformType::New();
+    if (fixedMask) transform->SetMask( fixedMask );
+    if (rigidTransform) transform->SetBulkTransform( rigidTransform ); 
+
+    //-------------------------------------------------------------------------
+    // The transform initializer
+    //-------------------------------------------------------------------------
+    typedef clitk::BSplineDeformableTransformInitializer< TransformType,FixedImageType> InitializerType;
+    typename InitializerType::Pointer initializer = InitializerType::New();
+    initializer->SetVerbose(m_Verbose);
+    initializer->SetImage(fixedImagePyramid->GetOutput(0));
+    initializer->SetTransform(transform);
+
+    //-------------------------------------------------------------------------
+    // Order
+    //-------------------------------------------------------------------------
+    typename FixedImageType::RegionType::SizeType splineOrders ;
+    splineOrders.Fill(3);
+    if (m_ArgsInfo.order_given)
+      for(unsigned int i=0; i<ImageDimension;i++) 
+       splineOrders[i]=m_ArgsInfo.order_arg[i];
+    if (m_Verbose) std::cout<<"Setting the spline orders  to "<<splineOrders<<"..."<<std::endl;
+    initializer->SetSplineOrders(splineOrders);
+
+    //-------------------------------------------------------------------------
+    // Levels
+    //-------------------------------------------------------------------------
+  
+    // Spacing
+    if (m_ArgsInfo.spacing_given)
+      {
+       initializer->m_ControlPointSpacingArray.resize(m_ArgsInfo.levels_arg);
+       initializer->SetControlPointSpacing(m_ArgsInfo.spacing_arg);
+       initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1]=initializer->m_ControlPointSpacing;
+       if (m_Verbose) std::cout<<"Using a control point spacing of "<<initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1]
+                               <<" at level "<<m_ArgsInfo.levels_arg<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;   
+       
+       for (int i=1; i<m_ArgsInfo.levels_arg; i++ )
+         {
+           initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1-i]=initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-i]*2;
+           if (m_Verbose) std::cout<<"Using a control point spacing of "<<initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1-i]
+                                   <<" at level "<<m_ArgsInfo.levels_arg-i<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;   
+         }
+         
+      }  
+    
+    // Control
+    if (m_ArgsInfo.control_given)
+      {
+       initializer->m_NumberOfControlPointsInsideTheImageArray.resize(m_ArgsInfo.levels_arg);
+       initializer->SetNumberOfControlPointsInsideTheImage(m_ArgsInfo.control_arg);
+       initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1]=initializer->m_NumberOfControlPointsInsideTheImage;
+       if (m_Verbose) std::cout<<"Using "<< initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1]<<"control points inside the image"
+                               <<" at level "<<m_ArgsInfo.levels_arg<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;   
+       
+       for (int i=1; i<m_ArgsInfo.levels_arg; i++ )
+         {
+           for(unsigned int j=0;j<ImageDimension;j++)
+             initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1-i][j]=ceil ((double)initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-i][j]/2.);
+             //            initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1-i]=ceil ((double)initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-i]/2.);
+           if (m_Verbose) std::cout<<"Using "<< initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1-i]<<"control points inside the image"
+                                   <<" at level "<<m_ArgsInfo.levels_arg<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;   
+       
+         }
+      }  
+
+    // Inialize on the first level 
+    if (m_ArgsInfo.verbose_flag) std::cout<<"Initializing transform for level 1 of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
+    if (m_ArgsInfo.spacing_given) initializer->SetControlPointSpacing( initializer->m_ControlPointSpacingArray[0]);
+    if (m_ArgsInfo.control_given) initializer->SetNumberOfControlPointsInsideTheImage(initializer->m_NumberOfControlPointsInsideTheImageArray[0]);     
+    if (m_ArgsInfo.samplingFactor_given) initializer->SetSamplingFactors(m_ArgsInfo.samplingFactor_arg);       
+    // Initialize 
+    initializer->InitializeTransform();
+
+    //-------------------------------------------------------------------------
+    // Initial parameters (passed by reference)
+    //-------------------------------------------------------------------------
+    typedef typename TransformType::ParametersType     ParametersType;
+    const unsigned int numberOfParameters =    transform->GetNumberOfParameters();
+    ParametersType parameters(numberOfParameters);
+    parameters.Fill( 0.0 );
+    transform->SetParameters( parameters );
+    if (m_ArgsInfo.initCoeff_given) initializer->SetInitialParameters(m_ArgsInfo.initCoeff_arg, parameters);
+    
+           
+    //=======================================================
+    // Interpolator
+    //=======================================================
+    typedef clitk::GenericInterpolator<args_info_clitkBLUTDIR, FixedImageType, TCoordRep > GenericInterpolatorType;
+    typename   GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
+    genericInterpolator->SetArgsInfo(m_ArgsInfo);
+    typedef itk::InterpolateImageFunction< FixedImageType, TCoordRep >  InterpolatorType;
+    typename  InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
+
+
+    //=======================================================
+    // Metric
+    //=======================================================
+    typedef clitk::GenericMetric<args_info_clitkBLUTDIR, FixedImageType,MovingImageType > GenericMetricType;
+    typename GenericMetricType::Pointer genericMetric=GenericMetricType::New();
+    genericMetric->SetArgsInfo(m_ArgsInfo);
+    genericMetric->SetFixedImage(fixedImagePyramid->GetOutput(0));
+    if (fixedMask) genericMetric->SetFixedImageMask(fixedMask);
+    genericMetric->SetFixedImageRegion(fixedImageRegionPyramid->GetOutput(0));
+    typedef itk::ImageToImageMetric< FixedImageType, MovingImageType >  MetricType;
+    typename  MetricType::Pointer metric=genericMetric->GetMetricPointer();
+    if (movingMask) metric->SetMovingImageMask(movingMask);
+
+#ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
+    if (threadsGiven) metric->SetNumberOfThreads( threads );
+#else
+    if (m_Verbose) std::cout<<"Not setting the number of threads (not compiled with USE_OPTIMIZED_REGISTRATION_METHODS)..."<<std::endl;
+#endif
+
+
+    //=======================================================
+    // Optimizer
+    //=======================================================
+    typedef clitk::GenericOptimizer<args_info_clitkBLUTDIR> GenericOptimizerType;
+    GenericOptimizerType::Pointer genericOptimizer = GenericOptimizerType::New();
+    genericOptimizer->SetArgsInfo(m_ArgsInfo);
+    genericOptimizer->SetMaximize(genericMetric->GetMaximize());
+    genericOptimizer->SetNumberOfParameters(transform->GetNumberOfParameters());
+    typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
+    OptimizerType::Pointer optimizer = genericOptimizer->GetOptimizerPointer();
+    
+    
+    //=======================================================
+    // Registration
+    //=======================================================
+    typedef itk::MultiResolutionImageRegistrationMethod<  FixedImageType, MovingImageType >    RegistrationType;
+    typename RegistrationType::Pointer   registration  = RegistrationType::New();
+    registration->SetMetric(        metric        );
+    registration->SetOptimizer(     optimizer     );
+    registration->SetInterpolator(  interpolator  );
+    registration->SetTransform (transform);
+    if(threadsGiven) registration->SetNumberOfThreads(threads);
+    registration->SetFixedImage(  croppedFixedImage   );
+    registration->SetMovingImage(  movingImage   );
+    registration->SetFixedImageRegion( metricRegion );
+    registration->SetFixedImagePyramid( fixedImagePyramid );
+    registration->SetMovingImagePyramid( movingImagePyramid );
+    registration->SetInitialTransformParameters( transform->GetParameters() );
+    registration->SetNumberOfLevels( m_ArgsInfo.levels_arg );
+    if (m_Verbose) std::cout<<"Setting the number of resolution levels to "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
+       
+  
+    //================================================================================================
+    // Observers
+    //================================================================================================
+    if (m_Verbose)
+      {
+       // Output iteration info
+       CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
+       observer->SetOptimizer(genericOptimizer);
+       optimizer->AddObserver( itk::IterationEvent(), observer );
+       
+       // Output level info
+       typedef RegistrationInterfaceCommand<RegistrationType,args_info_clitkBLUTDIR> CommandType;
+       typename CommandType::Pointer command = CommandType::New();
+       command->SetInitializer(initializer);
+       command->SetArgsInfo(m_ArgsInfo);
+       command->SetCommandIterationUpdate(observer);
+       command->SetMaximize(genericMetric->GetMaximize());
+       command->SetMetricRegion(metricRegion);
+       registration->AddObserver( itk::IterationEvent(), command );
+      }
+
+
+    //=======================================================
+    // Let's go
+    //=======================================================
+    if (m_Verbose) std::cout << std::endl << "Starting Registration" << std::endl;
+
+    try 
+      { 
+       registration->StartRegistration(); 
+      } 
+    catch( itk::ExceptionObject & err ) 
+      { 
+       std::cerr << "ExceptionObject caught while registering!" << std::endl; 
+       std::cerr << err << std::endl; 
+       return;
+      } 
+  
+
+    //=======================================================
+    // Get the result
+    //=======================================================
+    OptimizerType::ParametersType finalParameters =  registration->GetLastTransformParameters();
+    transform->SetParameters( finalParameters );
+    if (m_Verbose)
+      {
+       std::cout<<"Stop condition description: "
+                <<registration->GetOptimizer()->GetStopConditionDescription()<<std::endl;
+      }
+
+    //=======================================================
+    // Get the BSpline coefficient images and write them
+    //=======================================================
+    if (m_ArgsInfo.coeff_given)
+      { 
+       typedef typename TransformType::CoefficientImageType CoefficientImageType;
+       typename CoefficientImageType::Pointer coefficientImage =transform->GetCoefficientImage();
+       typedef itk::ImageFileWriter<CoefficientImageType> CoeffWriterType;
+       typename CoeffWriterType::Pointer coeffWriter=CoeffWriterType::New();
+       coeffWriter->SetInput(coefficientImage);
+       coeffWriter->SetFileName(m_ArgsInfo.coeff_arg);
+       coeffWriter->Update();
+      }
+    
+    
+
+    //=======================================================
+    // Compute the DVF (only deformable transform)
+    //=======================================================
+    typedef itk::Vector< float, SpaceDimension >  DisplacementType;
+    typedef itk::Image< DisplacementType, ImageDimension >  DeformationFieldType;
+    typedef itk::TransformToDeformationFieldSource<DeformationFieldType, double> ConvertorType;
+    typename ConvertorType::Pointer filter= ConvertorType::New();
+    filter->SetNumberOfThreads(1);
+    transform->SetBulkTransform(NULL);
+    filter->SetTransform(transform);
+    filter->SetOutputParametersFromImage(fixedImage);
+    filter->Update();
+    typename DeformationFieldType::Pointer field = filter->GetOutput();
+
+    //=======================================================
+    // Write the DVF
+    //=======================================================
+    typedef itk::ImageFileWriter< DeformationFieldType >  FieldWriterType;
+    typename FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+    fieldWriter->SetFileName( m_ArgsInfo.vf_arg );
+    fieldWriter->SetInput( field );
+    try
+      {
+       fieldWriter->Update();
+      }
+    catch( itk::ExceptionObject & excp )
+      {
+       std::cerr << "Exception thrown writing the DVF" << std::endl;
+       std::cerr << excp << std::endl;
+       return;
+      }
+  
+  
+    //=======================================================
+    // Resample the moving image
+    //=======================================================
+    typedef itk::ResampleImageFilter< MovingImageType, FixedImageType >    ResampleFilterType;
+    typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
+    if (rigidTransform) transform->SetBulkTransform(rigidTransform);
+    resampler->SetTransform( transform );
+    resampler->SetInput( movingImageReader->GetOutput() );
+    resampler->SetOutputParametersFromImage(fixedImage);
+    resampler->Update();
+    typename FixedImageType::Pointer result=resampler->GetOutput();
+    //     typedef itk::WarpImageFilter< MovingImageType, FixedImageType, DeformationFieldType >    WarpFilterType;
+    //     typename WarpFilterType::Pointer warp = WarpFilterType::New();
+    
+    //     warp->SetDeformationField( field );
+    //     warp->SetInput( movingImageReader->GetOutput() );
+    //     warp->SetOutputOrigin(  fixedImage->GetOrigin() );
+    //     warp->SetOutputSpacing( fixedImage->GetSpacing() );
+    //     warp->SetOutputDirection( fixedImage->GetDirection() );
+    //     warp->SetEdgePaddingValue( 0.0 );
+    //     warp->Update();
+
+    //=======================================================
+    // Write the warped image
+    //=======================================================
+    typedef itk::ImageFileWriter< FixedImageType >  WriterType;
+    typename WriterType::Pointer      writer =  WriterType::New();
+    writer->SetFileName( m_ArgsInfo.output_arg );
+    writer->SetInput( result    );
+
+    try
+      {
+       writer->Update();
+      }
+    catch( itk::ExceptionObject & err ) 
+      { 
+       std::cerr << "ExceptionObject caught !" << std::endl; 
+       std::cerr << err << std::endl; 
+       return;
+      } 
+
+    //=======================================================
+    // Calculate the difference after the deformable transform
+    //=======================================================
+    typedef clitk::DifferenceImageFilter<  FixedImageType, FixedImageType> DifferenceFilterType;
+    if (m_ArgsInfo.after_given)
+      {
+       typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
+       difference->SetValidInput( fixedImage );
+       difference->SetTestInput( result );
+      
+       try
+         {
+           difference->Update();
+         }
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught calculating the difference !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         }
+      
+       typename WriterType::Pointer differenceWriter=WriterType::New();
+       differenceWriter->SetInput(difference->GetOutput());
+       differenceWriter->SetFileName(m_ArgsInfo.after_arg);
+       differenceWriter->Update(); 
+      
+      }
+
+
+    //=======================================================
+    // Calculate the difference before the deformable transform
+    //=======================================================
+    if( m_ArgsInfo.before_given )
+      {
+
+       typename FixedImageType::Pointer moving=FixedImageType::New();
+       if (m_ArgsInfo.initMatrix_given)
+         {
+           typedef itk::ResampleImageFilter<MovingImageType, FixedImageType> ResamplerType;
+           typename ResamplerType::Pointer resampler=ResamplerType::New();
+           resampler->SetInput(movingImage);
+           resampler->SetOutputOrigin(fixedImage->GetOrigin());
+           resampler->SetSize(fixedImage->GetLargestPossibleRegion().GetSize());
+           resampler->SetOutputSpacing(fixedImage->GetSpacing());  
+           resampler->SetDefaultPixelValue( 0. );
+           if (rigidTransform ) resampler->SetTransform(rigidTransform);
+           resampler->Update();
+           moving=resampler->GetOutput();
+         }
+       else
+         moving=movingImage;
+
+       typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
+       difference->SetValidInput( fixedImage );
+       difference->SetTestInput( moving );
+    
+       try
+         {
+           difference->Update();
+         }
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught calculating the difference !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         }
+
+       typename WriterType::Pointer differenceWriter=WriterType::New();
+       writer->SetFileName( m_ArgsInfo.before_arg  );
+       writer->SetInput( difference->GetOutput()  );
+       writer->Update( );
+      }
+
+    return;
+  
+  }
+}//end clitk
+
+#endif // #define clitkBLUTDIRGenericFilter_txx
diff --git a/registration/clitkBSplineDeformableRegistration.cxx b/registration/clitkBSplineDeformableRegistration.cxx
new file mode 100755 (executable)
index 0000000..1cdef2b
--- /dev/null
@@ -0,0 +1,48 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+/**
+ * @file   clitkBSplineDeformableRegistration.cxx
+ * @author Jef Vandemeulebroucke <jefvdmb@gmail.com>
+ * @date   February 16  10:14:53 2009
+ * 
+ * @brief  Optimized BSpline-FFD(itk=accellaration+additional memory requirements) or BLUT-FFD (clitk)
+ * 
+ */
+
+// clitk include
+#include "clitkBSplineDeformableRegistration_ggo.h"
+#include "clitkBSplineDeformableRegistrationGenericFilter.h"
+#include "clitkIO.h"
+#include "clitkImageCommon.h"
+
+
+int main( int argc, char *argv[] )
+{
+  //=======================================================
+  // Init command line
+  //=======================================================
+  GGO(clitkBSplineDeformableRegistration, args_info);
+  CLITK_INIT;
+
+  //filter
+  clitk::BSplineDeformableRegistrationGenericFilter::Pointer genericFilter=clitk::BSplineDeformableRegistrationGenericFilter::New();
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+  
+  return EXIT_SUCCESS;
+}
diff --git a/registration/clitkBSplineDeformableRegistration.ggo b/registration/clitkBSplineDeformableRegistration.ggo
new file mode 100755 (executable)
index 0000000..2853860
--- /dev/null
@@ -0,0 +1,87 @@
+#File clitkBSplineDeformableRegistration.ggo
+#Author: Jef Vandemeulebroucke <jefvdmb@gmail.com>
+#Date : Tue 15 July 2008 16.35 
+
+Package "clitk"
+Version "Register 2 images using optimized ITK FFD (high memory requirements) or BLUT FFD. Both implementations are provided, mainly for debugging purposes.."
+
+option "config"                -       "Config file"                   string          no
+
+
+section "Run Time"
+
+option "verbose"       v       "Verbose"                       flag            off
+option "threads"       -       "Number of threads to use for intensive algorithms (default=min(cores,8))"      int      no
+
+
+section "Input"
+
+option "reference"             r       "Input reference 3D image (float)"      string          yes
+option "target"                        t       "Input target    2D image (float)"      string          yes
+option "mask"                  m       "Mask to placed over the reference image"                 string                no
+
+
+section "Output"
+
+option "vf"                    -       "Result DVF"                            string          yes
+option "coeff"                 -       "Result coefficient images"             string          no      multiple
+option "output"                        o       "Deformed target image"                 string          yes
+option "before"                        -       "Difference image before (but after rigid transform)"           string          no
+option "after"                 -       "Difference image after "               string          no
+
+
+section "Transform (Note that for BLUT FFD only one of --control, --spacing is required. The other will be adjusted to fit the region and allow exact representation. SamplingFactor will be set accordingly"
+
+option "init"                  -       "Initial coefficient images"                                    string          no              multiple
+option "rigid"                 -       "Prior rigid transform matrix from reference to target space"   string          no      
+option "order"                 -       "Spline Order FFD"                                              int       no    multiple        default="3"
+option "control"               -       "Internal control points for each dimension"                    int       no    multiple        
+option "spacing"               -       "Control point spacing for each dimension (mm)"                 double    no    multiple        
+option "wlut"                  -       "With LUT for BSpline calculation"                              flag      off
+option "samplingFactor"                -       "LUT sampling factor"                                           int       no    multiple        
+
+
+section "Interpolator"
+
+option "interp"                -       "Interpolation: 0=NN, 1=Linear, 2=BSpline, 3=BLUT"      int     no  default="1"
+option "interpOrder"   -       "Order if BLUT or BSpline (0-5)"                        int     no  default="3"
+option "interpSF"      -       "Sampling factor if BLUT"                               int     no  default="20"
+
+
+section "Metric (optimized, threaded (opt) versions are marked *)"
+
+option "metric"        -       "Type: 0=Mean-Squares*, 1=Normalized CC*, 2=Histogram CC, 3=Gradient-Difference, 4=Viola-Wells MI, 5=Histogram MI, 6=Mattes' MI*, 7=Normalized MI, 8=CR, 9=SSD for BLUT FFD**"  int     no      default="9"
+option "samples"       -       "Specify fraction [0, 1] of samples of the reference image used for the metric (* only). Use high fraction for detailed images (eg. 0.2, 0.5), for smooth images 0.01 might be enough." float   no      default="1"
+option "intThreshold"  -       "Fixed image samples intensity threshold (* only)"                                                      float   no              
+option "subtractMean"  -       "1: Subtract mean for NCC calculation (narrows optimal)"                                                flag    on      
+option "bins"          -       "2,5-8: Number of histogram bins"                                                                       int     no      default="50"
+option "random"        -       "4,6: Samples should be taken randomly, otherwise uniformly"                                            flag    off     
+option "stdDev"                -       "4: specify the standard deviation in mm of the gaussian kernels for both PDF estimations"              float   no      default="0.4"   
+option "explicitPDFDerivatives"        -       "6: Calculate PDF derivatives explicitly (rigid=true; FFD=false)"                               flag    off
+
+
+section "Optimizer"
+
+option "optimizer"     -       "0=Simplex, 1=Powell, 2=FRPR, 3=Regular Step GD, 4=VersorRigid3D, 5=Conjugated Gradient, 6=L-BFGS, 7=L-BFGS-B" int no default="7" 
+option "delta"         -       "0: Initial delta, otherwise automatic"                                                 double  no                      
+option "step"          -       "1,2,3,4: Initial stepsize (to be multiplied with the gradient)"                        double  no      default="2.0"   
+option "relax"                 -       "3,4: Relaxation of the stepsize (multiplied each time the gradient changes sign)"      double  no      default="0.7"
+option "valueTol"      -       "0,1,2: Tolerance on the function"                                                      double  no      default="0.01"
+option "stepTol"       -       "0,1,3,4: Tolerance on the step size"                                                   double  no      default="0.1"
+option "gradTol"       -       "3,4,6,7: Tolerance on the (projected) gradient magnitude (7: 1=low->1e-10=high precision)"     double  no      default="1e-5"                  
+option "lineAcc"       -       "6: Line accuracy (eg: high=0.1, low=0.9)"      double  no      default="0.9"
+option "convFactor"    -       "7: Convergence factor: terminate if factor*machine_precision>reduction in cost (1e+12 low -> 1e+1 high precision) "    double          no      default="1e+7"
+option "maxIt"         -       "0-7: Maximum number of iterations"                                     int     no      default="500"
+option "maxLineIt"     -       "1,2: Maximum number of line iterations"                                        int     no      default="50"    
+option "maxEval"       -       "6,7: Maximum number of evaluations"                                            int     no      default="500"
+option "maxCorr"       -       "7: Maximum number of corrections"                                              int     no      default="5"
+option "selectBound"   -       "7: Select the type of bound: 0=none, 1=u, 2=u&l, 3=l"                  int     no      default="0"
+option "lowerBound"    -       "7: The lower bound"                                                    double  no      default="0.0"
+option "upperBound"    -       "7: The upper bound"                                                    double  no      default="0.0"
+
+
+Section "Registration"
+
+option "levels"                -       "Number of resolution levels"                                   int     no      default="1"                                             
+
+
diff --git a/registration/clitkBSplineDeformableRegistrationGenericFilter.cxx b/registration/clitkBSplineDeformableRegistrationGenericFilter.cxx
new file mode 100755 (executable)
index 0000000..788eb5d
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef _clitkBSplineDeformableRegistrationGenericFilter_cxx
+#define _clitkBSplineDeformableRegistrationGenericFilter_cxx
+#include "clitkBSplineDeformableRegistrationGenericFilter.h"
+
+
+namespace clitk {
+
+  clitk::BSplineDeformableRegistrationGenericFilter::BSplineDeformableRegistrationGenericFilter()
+  {
+    m_Verbose=false;
+  }
+  
+  
+  void clitk::BSplineDeformableRegistrationGenericFilter::Update()
+  {
+    //Get the image Dimension and PixelType
+    int Dimension;
+    std::string PixelType;
+    
+    clitk::ReadImageDimensionAndPixelType(m_ReferenceFileName, Dimension, PixelType);
+    
+    if(Dimension==2) UpdateWithDim<2>(PixelType);
+    else if(Dimension==3) UpdateWithDim<3>(PixelType);
+    //else if (Dimension==4)UpdateWithDim<4>(PixelType); 
+    else 
+      {
+       std::cout<<"Error, Only for 2 and 3 Dimensions!!!"<<std::endl ;
+       return;
+      }
+
+  }
+} //end namespace
+
+#endif
diff --git a/registration/clitkBSplineDeformableRegistrationGenericFilter.h b/registration/clitkBSplineDeformableRegistrationGenericFilter.h
new file mode 100755 (executable)
index 0000000..7700326
--- /dev/null
@@ -0,0 +1,120 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef _clitkBSplineDeformableRegistrationGenericFilter_h
+#define _clitkBSplineDeformableRegistrationGenericFilter_h
+/**
+   =================================================
+   * @file   clitkBSplineDeformableRegistrationGenericFilter.h
+   * @author Jef Vandemeulebroucke <jef@creatis.insa-lyon.fr>
+   * @date   14 March 2009
+   * 
+   * @brief 
+   * 
+   =================================================*/
+
+// clitk
+#include "clitkBSplineDeformableRegistration_ggo.h"
+#include "clitkIO.h"
+#include "clitkImageCommon.h"
+#include "clitkDifferenceImageFilter.h"
+#include "clitkTransformUtilities.h"
+#include "clitkLBFGSBOptimizer.h"
+#include "clitkBSplineDeformableTransform.h"
+#include "clitkGenericOptimizer.h"
+#include "clitkGenericInterpolator.h"
+#include "clitkGenericMetric.h"
+
+// itk include
+#include "itkMultiResolutionImageRegistrationMethod.h"
+#include "itkMultiResolutionPyramidImageFilter.h"
+#include "itkImage.h"
+#include "itkBSplineDeformableTransform.h"
+#include "itkImageFileReader.h"
+#include "itkImageFileWriter.h"
+#include "itkResampleImageFilter.h"
+#include "itkCommand.h"
+#include "itkImageMaskSpatialObject.h"
+#include "itkEuler3DTransform.h"
+#include "itkWarpImageFilter.h"
+#include "itkLightObject.h"
+#include "itkImageToImageMetric.h"
+#include "itkInterpolateImageFunction.h"
+#include "itkLabelStatisticsImageFilter.h"
+
+
+namespace clitk
+{
+
+  class ITK_EXPORT BSplineDeformableRegistrationGenericFilter : public itk::LightObject
+  
+  {
+  public:
+    typedef BSplineDeformableRegistrationGenericFilter  Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+    
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);  
+    
+    /** Run-time type information (and related methods) */
+    itkTypeMacro( BSplineDeformableRegistrationGenericFilter, LightObject );
+    
+    
+    //====================================================================
+    // Set methods
+    void SetArgsInfo(const args_info_clitkBSplineDeformableRegistration& a)
+    {
+      m_ArgsInfo=a;
+      m_ReferenceFileName=m_ArgsInfo.reference_arg;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+    }
+    
+    //====================================================================
+    // Update
+    virtual void Update();
+    
+  protected:
+    //const char * GetNameOfClass() const { return "BSplineDeformableRegistrationGenericFilter"; }
+    
+    //====================================================================
+    // Constructor & Destructor
+    BSplineDeformableRegistrationGenericFilter();
+    ~BSplineDeformableRegistrationGenericFilter(){;}
+    
+    //====================================================================
+    //Protected member functions
+    template <unsigned int Dimension>  void UpdateWithDim(std::string PixelType);
+    template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+    
+    args_info_clitkBSplineDeformableRegistration m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_ReferenceFileName;
+    
+  };
+  
+} // end namespace clitk
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkBSplineDeformableRegistrationGenericFilter.txx"
+#endif
+  
+#endif //#define _clitkBSplineDeformableRegistrationGenericFilter_h
+
+
+
+
diff --git a/registration/clitkBSplineDeformableRegistrationGenericFilter.txx b/registration/clitkBSplineDeformableRegistrationGenericFilter.txx
new file mode 100755 (executable)
index 0000000..f76c8fa
--- /dev/null
@@ -0,0 +1,857 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkBSplineDeformableRegistrationGenericFilter_txx
+#define __clitkBSplineDeformableRegistrationGenericFilter_txx
+#include "clitkBSplineDeformableRegistrationGenericFilter.h"
+
+
+namespace clitk
+{
+
+  //==============================================================================
+  //Creating an observer class that allows us to change parameters at subsequent levels
+  //==============================================================================
+  template <typename TRegistration>
+  class RegistrationInterfaceCommand : public itk::Command 
+  {
+  public:
+    typedef RegistrationInterfaceCommand   Self;
+  
+
+    typedef itk::Command             Superclass;
+    typedef itk::SmartPointer<Self>  Pointer;
+    itkNewMacro( Self );
+  protected:
+    RegistrationInterfaceCommand() {};
+  public:
+    typedef   TRegistration                              RegistrationType;
+    typedef   RegistrationType *                         RegistrationPointer;
+  
+    // Two arguments are passed to the Execute() method: the first
+    // is the pointer to the object which invoked the event and the 
+    // second is the event that was invoked.
+    void Execute(itk::Object * object, const itk::EventObject & event)
+    {
+      if( !(itk::IterationEvent().CheckEvent( &event )) )
+       {
+         return;
+       }
+      RegistrationPointer registration = dynamic_cast<RegistrationPointer>( object );
+      unsigned int numberOfLevels=registration->GetNumberOfLevels();
+      unsigned int currentLevel=registration->GetCurrentLevel()+1;
+      std::cout<<std::endl;
+      std::cout<<"========================================"<<std::endl;
+      std::cout<<"Starting resolution level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
+      std::cout<<"========================================"<<std::endl;        
+      std::cout<<std::endl;
+    }
+  
+    void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+  
+  };
+
+
+  //==============================================================================
+  // Creating an observer class that allows output at each iteration
+  //==============================================================================
+  class CommandIterationUpdate : public itk::Command 
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<Self>  Pointer;
+    itkNewMacro( Self );
+  protected:
+    CommandIterationUpdate() {};
+  public:
+    typedef   clitk::GenericOptimizer<args_info_clitkBSplineDeformableRegistration>     OptimizerType;
+    typedef   const OptimizerType   *           OptimizerPointer;
+  
+    // We set the generic optimizer
+    void SetOptimizer(OptimizerPointer o){m_Optimizer=o;}
+    
+    // Execute
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+    {
+      Execute( (const itk::Object *)caller, event);
+    }
+  
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+    {  
+      if( !(itk::IterationEvent().CheckEvent( &event )) )
+       {
+         return;
+       }
+      
+      m_Optimizer->OutputIterationInfo();
+    }
+
+    OptimizerPointer m_Optimizer;
+  };
+
+
+  //==============================================================================
+  // Update with the number of dimensions
+  //==============================================================================
+  template<unsigned int Dimension>
+  void BSplineDeformableRegistrationGenericFilter::UpdateWithDim(std::string PixelType)
+  {
+
+    if (m_Verbose) std::cout  << "Images were detected to be "<< Dimension << "D and " << PixelType << "..." << std::endl;
+    
+    if(PixelType == "short"){  
+      if (m_Verbose) std::cout  << "Launching warp in "<< Dimension <<"D and signed short..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, signed short>(); 
+    }
+    //    else if(PixelType == "unsigned_short"){  
+    //       if (m_Verbose) std::cout  << "Launching warp in "<< Dimension <<"D and unsigned_short..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, unsigned short>(); 
+    //     }
+    
+    //     else if (PixelType == "unsigned_char"){ 
+    //       if (m_Verbose) std::cout  << "Launching warp in "<< Dimension <<"D and unsigned_char..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, unsigned char>();
+    //     }
+    
+    //     else if (PixelType == "char"){ 
+    //       if (m_Verbose) std::cout  << "Launching warp in "<< Dimension <<"D and signed_char..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, signed char>();
+    //    }
+    else {
+      if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, float>();
+    }
+  }
+
+  
+
+  //==============================================================================
+  // Update with the number of dimensions and pixeltype
+  //==============================================================================
+  template<unsigned int ImageDimension, class PixelType>
+  void BSplineDeformableRegistrationGenericFilter::UpdateWithDimAndPixelType()
+  {
+      
+    //=======================================================
+    // Run-time
+    //=======================================================
+    bool threadsGiven=m_ArgsInfo.threads_given;
+    int threads=m_ArgsInfo.threads_arg;
+    
+    typedef itk::Image< PixelType, ImageDimension >  FixedImageType;
+    typedef itk::Image< PixelType, ImageDimension >  MovingImageType;
+    const unsigned int SpaceDimension = ImageDimension;
+    typedef double TCoordRep;
+
+
+    //=======================================================
+    //Input
+    //=======================================================
+    typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
+    typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;
+
+    typename FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
+    typename MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();
+
+    fixedImageReader->SetFileName(  m_ArgsInfo.reference_arg );
+    movingImageReader->SetFileName( m_ArgsInfo.target_arg );
+    if (m_Verbose) std::cout<<"Reading images..."<<std::endl;
+    fixedImageReader->Update();
+    movingImageReader->Update();
+
+    typename FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+    typename MovingImageType::Pointer movingImage =movingImageReader->GetOutput();
+    typename FixedImageType::RegionType fixedImageRegion = fixedImage->GetLargestPossibleRegion();
+
+    // The metric region: where should the metric be CALCULATED (depends on mask)
+    typename FixedImageType::RegionType metricRegion = fixedImage->GetLargestPossibleRegion();
+    typename FixedImageType::RegionType::SizeType metricRegionSize=metricRegion.GetSize();
+    typename FixedImageType::RegionType::IndexType metricRegionIndex=metricRegion.GetIndex();
+    typename FixedImageType::PointType metricRegionOrigin=fixedImage->GetOrigin();
+    
+    // The transform region: where should the transform be DEFINED (depends on mask)
+    typename FixedImageType::RegionType transformRegion = fixedImage->GetLargestPossibleRegion();
+    typename FixedImageType::RegionType::SizeType transformRegionSize=transformRegion.GetSize();
+    typename FixedImageType::RegionType::IndexType transformRegionIndex=transformRegion.GetIndex();
+    typename FixedImageType::PointType transformRegionOrigin=fixedImage->GetOrigin();
+
+
+    //=======================================================
+    // If given, we connect a mask to the fixed image
+    //======================================================
+    typedef itk::ImageMaskSpatialObject<  ImageDimension >   MaskType;
+    typename MaskType::Pointer  spatialObjectMask=NULL;
+   
+    if (m_ArgsInfo.mask_given)
+      {
+       typedef itk::Image< unsigned char, ImageDimension >   ImageMaskType;
+       typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
+       typename MaskReaderType::Pointer  maskReader = MaskReaderType::New();
+       maskReader->SetFileName(m_ArgsInfo.mask_arg);
+       
+       try 
+         { 
+           maskReader->Update(); 
+         } 
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught while reading mask !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         } 
+       if (m_Verbose)std::cout <<"Reference image mask was read..." <<std::endl;
+
+
+       // Set the image to the spatialObject
+       spatialObjectMask = MaskType::New();
+       spatialObjectMask->SetImage( maskReader->GetOutput() );
+
+       // Find the bounding box of the "inside" label
+       typedef itk::LabelStatisticsImageFilter<ImageMaskType, ImageMaskType> StatisticsImageFilterType;
+       typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New();
+       statisticsImageFilter->SetInput(maskReader->GetOutput());
+       statisticsImageFilter->SetLabelInput(maskReader->GetOutput());
+       statisticsImageFilter->Update();
+       typename StatisticsImageFilterType::BoundingBoxType boundingBox = statisticsImageFilter->GetBoundingBox(1);
+
+       // Limit the transform region to the mask
+       for (unsigned int i=0; i<ImageDimension; i++)
+         {
+           transformRegionIndex[i]=boundingBox[2*i];
+           transformRegionSize[i]=boundingBox[2*i+1]-boundingBox[2*i]+1;
+         }
+       transformRegion.SetSize(transformRegionSize);
+       transformRegion.SetIndex(transformRegionIndex);
+       fixedImage->TransformIndexToPhysicalPoint(transformRegion.GetIndex(), transformRegionOrigin);
+       
+       // Limit the metric region to the mask
+       metricRegion=transformRegion;
+       fixedImage->TransformIndexToPhysicalPoint(metricRegion.GetIndex(), metricRegionOrigin);
+     }
+
+
+
+    //=======================================================
+    // Regions
+    //=====================================================
+    if (m_Verbose)
+      {
+       // Fixed image region
+       std::cout<<"The fixed image has its origin at "<<fixedImage->GetOrigin()<<std::endl 
+                <<"The fixed image region starts at index "<<fixedImageRegion.GetIndex()<<std::endl
+                <<"The fixed image region has size "<< fixedImageRegion.GetSize()<<std::endl;
+
+       // Transform region
+       std::cout<<"The transform has its origin at "<<transformRegionOrigin<<std::endl 
+                <<"The transform region will start at index "<<transformRegion.GetIndex()<<std::endl
+                <<"The transform region has size "<< transformRegion.GetSize()<<std::endl;
+
+       // Metric region
+       std::cout<<"The metric region has its origin at "<<metricRegionOrigin<<std::endl 
+                <<"The metric region will start at index "<<metricRegion.GetIndex()<<std::endl
+                <<"The metric region has size "<< metricRegion.GetSize()<<std::endl;
+       
+      }  
+
+    
+    //=======================================================
+    //Pyramids
+    //=======================================================
+    typedef itk::RecursiveMultiResolutionPyramidImageFilter< FixedImageType, FixedImageType>    FixedImagePyramidType;
+    typedef itk::RecursiveMultiResolutionPyramidImageFilter< MovingImageType, MovingImageType>    MovingImagePyramidType;
+    typename FixedImagePyramidType::Pointer fixedImagePyramid = FixedImagePyramidType::New();
+    typename MovingImagePyramidType::Pointer movingImagePyramid = MovingImagePyramidType::New();
+    
+
+    //     //=======================================================
+    //     // Rigid Transform
+    //     //=======================================================
+    //     typedef itk::Euler3DTransform <double> RigidTransformType;
+    //     RigidTransformType::Pointer rigidTransform=RigidTransformType::New();
+    
+    //     if (m_ArgsInfo.rigid_given)
+    //       {
+    //         itk::Matrix<double,4,4> rigidTransformMatrix=clitk::ReadMatrix3D(m_ArgsInfo.rigid_arg);
+    
+    //         //Set the rotation
+    //         itk::Matrix<double,3,3> finalRotation = clitk::GetRotationalPartMatrix3D(rigidTransformMatrix);
+    //         rigidTransform->SetMatrix(finalRotation);
+    
+    //         //Set the translation
+    //         itk::Vector<double,3> finalTranslation = clitk::GetTranslationPartMatrix3D(rigidTransformMatrix);
+    //         rigidTransform->SetTranslation(finalTranslation);
+    
+    //       }
+
+
+    //=======================================================
+    // BSpline Transform
+    //=======================================================
+    typename FixedImageType::RegionType::SizeType splineOrders ;
+   
+    //Default is cubic splines
+    splineOrders.Fill(3);
+    if (m_ArgsInfo.order_given)
+      for(unsigned int i=0; i<ImageDimension;i++) 
+       splineOrders[i]=m_ArgsInfo.order_arg[i];
+
+    // BLUT or ITK FFD
+    typedef itk::Transform<TCoordRep, ImageDimension, SpaceDimension> TransformType;
+    typename TransformType::Pointer transform;
+    typedef  itk::BSplineDeformableTransform<TCoordRep,SpaceDimension, 3> BSplineTransformType;
+    typedef  BSplineTransformType* BSplineTransformPointer;
+    typedef  clitk::BSplineDeformableTransform<TCoordRep,ImageDimension, SpaceDimension > BLUTTransformType;
+    typedef  BLUTTransformType* BLUTTransformPointer;
+
+    // JV parameter array is passed by reference, create outside context so it exists afterwards!!!!!
+    typedef typename TransformType::ParametersType     ParametersType;
+    ParametersType parameters;
+
+
+    // CLITK BLUT transform
+    if(m_ArgsInfo.wlut_flag)
+      {
+       typename BLUTTransformType::Pointer  bsplineTransform = BLUTTransformType::New();
+       if (m_Verbose) std::cout<<"Setting the spline orders  to "<<splineOrders<<"..."<<std::endl;
+       bsplineTransform->SetSplineOrders(splineOrders);
+      
+       //-------------------------------------------------------------------------
+       // Define the region: Either the spacing or the number of CP should be given 
+       //-------------------------------------------------------------------------
+       
+       // Region
+       typedef typename BSplineTransformType::RegionType RegionType;
+       RegionType bsplineRegion;
+       typename RegionType::SizeType   gridSizeOnImage;
+       typename RegionType::SizeType   gridBorderSize;
+       typename RegionType::SizeType   totalGridSize;
+      
+       // Spacing
+       typedef typename BSplineTransformType::SpacingType SpacingType;
+       SpacingType fixedImageSpacing, chosenSpacing, adaptedSpacing;
+       fixedImageSpacing = fixedImage->GetSpacing();
+
+       // Only spacing given: adjust if necessary
+       if (m_ArgsInfo.spacing_given && !m_ArgsInfo.control_given)
+         {
+           for(unsigned int r=0; r<ImageDimension; r++) 
+             {
+               chosenSpacing[r]= m_ArgsInfo.spacing_arg[r];
+               gridSizeOnImage[r] = ceil( (double) transformRegion.GetSize()[r] / ( round(chosenSpacing[r]/fixedImageSpacing[r]) ) );
+               adaptedSpacing[r]= ( round(chosenSpacing[r]/fixedImageSpacing[r]) *fixedImageSpacing[r] ) ;
+             }
+           if (m_Verbose) std::cout<<"The chosen control point spacing "<<chosenSpacing<<"..."<<std::endl;
+           if (m_Verbose) std::cout<<"The control points spacing was adapted to "<<adaptedSpacing<<"..."<<std::endl; 
+           if (m_Verbose) std::cout<<"The number of (internal) control points is "<<gridSizeOnImage<<"..."<<std::endl; 
+         }
+
+       // Only number of CP given: adjust if necessary
+       else if (m_ArgsInfo.control_given && !m_ArgsInfo.spacing_given)
+         {
+           for(unsigned int r=0; r<ImageDimension; r++) 
+             {
+               gridSizeOnImage[r]= m_ArgsInfo.control_arg[r];
+               chosenSpacing[r]=fixedImageSpacing[r]*( (double)(transformRegion.GetSize()[r])  / 
+                                                       (double)(gridSizeOnImage[r]) );
+               adaptedSpacing[r]= fixedImageSpacing[r]* ceil( (double)(transformRegion.GetSize()[r] - 1)  / 
+                                                              (double)(gridSizeOnImage[r] - 1) );
+             }
+           if (m_Verbose) std::cout<<"The chosen control point spacing "<<chosenSpacing<<"..."<<std::endl;
+           if (m_Verbose) std::cout<<"The control points spacing was adapted to "<<adaptedSpacing<<"..."<<std::endl; 
+           if (m_Verbose) std::cout<<"The number of (internal) control points is "<<gridSizeOnImage<<"..."<<std::endl; 
+         }
+       
+       // Spacing and number of CP given: no adjustment adjust, just warnings
+       else if (m_ArgsInfo.control_given && m_ArgsInfo.spacing_given)
+         {
+           for(unsigned int r=0; r<ImageDimension; r++) 
+             {
+               adaptedSpacing[r]= m_ArgsInfo.spacing_arg[r];
+               gridSizeOnImage[r] =  m_ArgsInfo.control_arg[r];
+               if (gridSizeOnImage[r]*adaptedSpacing[r]< transformRegion.GetSize()[r]*fixedImageSpacing[r]) 
+                 {
+                   std::cout<<"WARNING: Specified control point region ("<<gridSizeOnImage[r]*adaptedSpacing[r]
+                            <<"mm) does not cover the transform region ("<< transformRegion.GetSize()[r]*fixedImageSpacing[r]
+                            <<"mm) for dimension "<<r<<"!" <<std::endl
+                            <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;
+                 }
+               if (  fmod(adaptedSpacing[r], fixedImageSpacing[r]) ) 
+                 {
+                   std::cout<<"WARNING: Specified control point spacing for dimension "<<r
+                            <<" does not allow exact representation of BLUT FFD!"<<std::endl
+                            <<"Spacing ratio is non-integer: "<<adaptedSpacing[r]/ fixedImageSpacing[r]<<std::endl
+                            <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;  
+                 }
+             }
+           if (m_Verbose) std::cout<<"The control points spacing was set to "<<adaptedSpacing<<"..."<<std::endl; 
+           if (m_Verbose) std::cout<<"The number of (internal) control points spacing is "<<gridSizeOnImage<<"..."<<std::endl; 
+         }
+
+       //JV  border size should depend on spline order
+       for(unsigned int r=0; r<ImageDimension; r++) gridBorderSize[r]=splineOrders[r]; // Border for spline order = 3 ( 1 lower, 2 upper )
+       totalGridSize = gridSizeOnImage + gridBorderSize;
+       bsplineRegion.SetSize( totalGridSize );
+       if (m_Verbose) std::cout<<"The total control point grid size was set to "<<totalGridSize<<"..."<<std::endl;
+
+       // Direction
+       typename FixedImageType::DirectionType gridDirection = fixedImage->GetDirection();
+       SpacingType gridOriginOffset = gridDirection * adaptedSpacing;
+
+       // Origin: 1 CP border for spatial dimensions 
+       typedef typename BSplineTransformType::OriginType OriginType;
+       OriginType gridOrigin = transformRegionOrigin - gridOriginOffset;
+       if (m_Verbose) std::cout<<"The control point grid origin was set to "<<gridOrigin<<"..."<<std::endl;
+
+       // Set 
+       bsplineTransform->SetGridSpacing( adaptedSpacing );
+       bsplineTransform->SetGridOrigin( gridOrigin );
+       bsplineTransform->SetGridRegion( bsplineRegion );
+       bsplineTransform->SetGridDirection( gridDirection );
+
+       //Bulk transform
+       //if (m_Verbose) std::cout<<"Setting rigid transform..."<<std::endl;
+       //bsplineTransform->SetBulkTransform( rigidTransform );
+  
+       //Vector BSpline interpolator
+       //bsplineTransform->SetOutputSpacing(fixedImage->GetSpacing());
+       typename RegionType::SizeType samplingFactors;
+       for (unsigned int i=0; i< ImageDimension; i++)
+         {
+           if (m_Verbose) std::cout<<"For dimension "<<i<<", the ideal sampling factor (if integer) is a multitude of "
+                                   << (double)adaptedSpacing[i]/ (double) fixedImageSpacing[i]<<"..."<<std::endl;
+           if (m_ArgsInfo.samplingFactor_given) samplingFactors[i]=m_ArgsInfo.samplingFactor_arg[i];
+           else samplingFactors[i]=(int) ((double)adaptedSpacing[i]/ (double) movingImage->GetSpacing()[i]);
+           if (m_Verbose) std::cout<<"Setting sampling factor "<<i<<" to "<<samplingFactors[i]<<"..."<<std::endl;
+         }
+       bsplineTransform->SetLUTSamplingFactors(samplingFactors);
+
+       //initial parameters
+       if (m_ArgsInfo.init_given)
+         {
+           typedef itk::ImageFileReader<typename BLUTTransformType::CoefficientImageType> CoefficientReaderType;
+           typename CoefficientReaderType::Pointer coeffReader=CoefficientReaderType::New();
+           coeffReader->SetFileName(m_ArgsInfo.init_arg[0]);
+           coeffReader->Update();
+           bsplineTransform->SetCoefficientImage(coeffReader->GetOutput());
+         }
+       else
+         {
+           //typedef typename TransformType::ParametersType     ParametersType;
+           const unsigned int numberOfParameters =    bsplineTransform->GetNumberOfParameters();
+           parameters=ParametersType( numberOfParameters );
+           parameters.Fill( 0.0 );
+           bsplineTransform->SetParameters( parameters );
+         }
+
+       // Mask
+       if (spatialObjectMask) bsplineTransform->SetMask( spatialObjectMask );
+
+       // Pass
+       transform=bsplineTransform;
+      }
+
+    //ITK BSpline transform
+    else
+      {
+       typename BSplineTransformType::Pointer  bsplineTransform = BSplineTransformType::New();
+
+       // Define the region
+       typedef typename BSplineTransformType::RegionType RegionType;
+       RegionType bsplineRegion;
+       typename RegionType::SizeType   gridSizeOnImage;
+       typename RegionType::SizeType   gridBorderSize;
+       typename RegionType::SizeType   totalGridSize;
+
+       //Set the number of control points
+       for(unsigned int r=0; r<ImageDimension; r++)  gridSizeOnImage[r]=m_ArgsInfo.control_arg[r];
+       if (m_Verbose) std::cout<<"Setting the number of internal control points "<<gridSizeOnImage<<"..."<<std::endl;
+       gridBorderSize.Fill( 3 );    // Border for spline order = 3 ( 1 lower, 2 upper )
+       totalGridSize = gridSizeOnImage + gridBorderSize;
+       bsplineRegion.SetSize( totalGridSize );
+
+       // Spacing
+       typedef typename BSplineTransformType::SpacingType SpacingType;
+       SpacingType spacing = fixedImage->GetSpacing();
+       typename FixedImageType::SizeType fixedImageSize = fixedImageRegion.GetSize();
+       if (m_ArgsInfo.spacing_given)
+         {
+           
+           for(unsigned int r=0; r<ImageDimension; r++)
+             {
+               spacing[r] =m_ArgsInfo.spacing_arg[r];
+             }
+         }
+       else
+         {
+           for(unsigned int r=0; r<ImageDimension; r++)
+             {
+               spacing[r] *= static_cast<double>(fixedImageSize[r] - 1)  / 
+                 static_cast<double>(gridSizeOnImage[r] - 1);
+             }
+         }
+       if (m_Verbose) std::cout<<"The control points spacing was set to "<<spacing<<"..."<<std::endl;
+
+       // Direction
+       typename FixedImageType::DirectionType gridDirection = fixedImage->GetDirection();
+       SpacingType gridOriginOffset = gridDirection * spacing;
+
+       // Origin
+       typedef typename BSplineTransformType::OriginType OriginType;
+       OriginType origin = fixedImage->GetOrigin();
+       OriginType gridOrigin = origin - gridOriginOffset; 
+
+       // Set
+       bsplineTransform->SetGridSpacing( spacing );
+       bsplineTransform->SetGridOrigin( gridOrigin );
+       bsplineTransform->SetGridRegion( bsplineRegion );
+       bsplineTransform->SetGridDirection( gridDirection );
+
+       // Bulk transform
+       // if (m_Verbose) std::cout<<"Setting rigid transform..."<<std::endl;
+       // bsplineTransform->SetBulkTransform( rigidTransform );
+
+       // Initial parameters
+       if (m_ArgsInfo.init_given)
+         {
+           typedef itk::ImageFileReader<typename BSplineTransformType::ImageType> CoefficientReaderType;
+           typename BSplineTransformType::ImageType::Pointer coeffImages[SpaceDimension];
+           for(unsigned int i=0; i<SpaceDimension; i++)
+             {
+               typename CoefficientReaderType::Pointer coeffReader=CoefficientReaderType::New();
+               coeffReader->SetFileName(m_ArgsInfo.init_arg[i]);
+               coeffReader->Update();
+               coeffImages[i]=coeffReader->GetOutput();
+             }
+           bsplineTransform->SetCoefficientImage(coeffImages);
+         }
+       else
+         {
+           const unsigned int numberOfParameters =    bsplineTransform->GetNumberOfParameters();
+           parameters=ParametersType( numberOfParameters );
+           parameters.Fill( 0.0 );
+           bsplineTransform->SetParameters( parameters );
+         }
+
+       // Pass
+       transform=bsplineTransform;
+
+      }
+  
+
+    //=======================================================
+    // Interpolator
+    //=======================================================
+    typedef clitk::GenericInterpolator<args_info_clitkBSplineDeformableRegistration, FixedImageType, TCoordRep > GenericInterpolatorType;
+    typename   GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
+    genericInterpolator->SetArgsInfo(m_ArgsInfo);
+    typedef itk::InterpolateImageFunction< FixedImageType, TCoordRep >  InterpolatorType;
+    typename  InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
+
+
+    //=======================================================
+    // Metric
+    //=======================================================
+    typedef clitk::GenericMetric<args_info_clitkBSplineDeformableRegistration, FixedImageType,MovingImageType > GenericMetricType;
+    typename GenericMetricType::Pointer genericMetric=GenericMetricType::New();
+    genericMetric->SetArgsInfo(m_ArgsInfo);
+    genericMetric->SetFixedImageRegion(metricRegion);
+    typedef itk::ImageToImageMetric< FixedImageType, MovingImageType >  MetricType;
+    typename  MetricType::Pointer metric=genericMetric->GetMetricPointer();
+    if (spatialObjectMask) metric->SetFixedImageMask( spatialObjectMask );
+
+#ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
+    if (threadsGiven) metric->SetNumberOfThreads( threads );
+#else
+    if (m_Verbose) std::cout<<"Not setting the number of threads (not compiled with USE_OPTIMIZED_REGISTRATION_METHODS)..."<<std::endl;
+#endif
+
+
+    //=======================================================
+    // Optimizer
+    //=======================================================
+    typedef clitk::GenericOptimizer<args_info_clitkBSplineDeformableRegistration> GenericOptimizerType;
+    GenericOptimizerType::Pointer genericOptimizer = GenericOptimizerType::New();
+    genericOptimizer->SetArgsInfo(m_ArgsInfo);
+    genericOptimizer->SetMaximize(genericMetric->GetMaximize());
+    genericOptimizer->SetNumberOfParameters(transform->GetNumberOfParameters());
+    typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
+    OptimizerType::Pointer optimizer = genericOptimizer->GetOptimizerPointer();
+    
+    
+    //=======================================================
+    // Registration
+    //=======================================================
+    typedef itk::MultiResolutionImageRegistrationMethod<  FixedImageType, MovingImageType >    RegistrationType;
+    typename RegistrationType::Pointer   registration  = RegistrationType::New();
+    registration->SetMetric(        metric        );
+    registration->SetOptimizer(     optimizer     );
+    registration->SetInterpolator(  interpolator  );
+    registration->SetTransform (transform);
+    if(threadsGiven) registration->SetNumberOfThreads(threads);
+    registration->SetFixedImage(  fixedImage   );
+    registration->SetMovingImage(   movingImage   );
+    registration->SetFixedImageRegion( metricRegion );
+    registration->SetFixedImagePyramid( fixedImagePyramid );
+    registration->SetMovingImagePyramid( movingImagePyramid );
+    registration->SetInitialTransformParameters( transform->GetParameters() );
+    registration->SetNumberOfLevels(m_ArgsInfo.levels_arg);
+    if (m_Verbose) std::cout<<"Setting the number of resolution levels to "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
+       
+  
+    //================================================================================================
+    // Observers
+    //================================================================================================
+    if (m_Verbose)
+      {
+       // Output iteration info
+       CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
+       observer->SetOptimizer(genericOptimizer);
+       optimizer->AddObserver( itk::IterationEvent(), observer );
+       
+       
+       // Output level info
+       typedef RegistrationInterfaceCommand<RegistrationType> CommandType;
+       typename CommandType::Pointer command = CommandType::New();
+       registration->AddObserver( itk::IterationEvent(), command );
+      }
+
+
+    //=======================================================
+    // Let's go
+    //=======================================================
+    if (m_Verbose) std::cout << std::endl << "Starting Registration" << std::endl;
+
+    try 
+      { 
+       registration->StartRegistration(); 
+      } 
+    catch( itk::ExceptionObject & err ) 
+      { 
+       std::cerr << "ExceptionObject caught while registering!" << std::endl; 
+       std::cerr << err << std::endl; 
+       return;
+      } 
+  
+
+    //=======================================================
+    // Get the result
+    //=======================================================
+    OptimizerType::ParametersType finalParameters =  registration->GetLastTransformParameters();
+    transform->SetParameters( finalParameters );
+
+    //=======================================================
+    // Get the BSpline coefficient images and write them
+    //=======================================================
+    if (m_ArgsInfo.coeff_given)
+      { 
+       if(m_ArgsInfo.wlut_flag)
+         {
+           BLUTTransformPointer bsplineTransform=dynamic_cast<BLUTTransformPointer>(registration->GetTransform());
+           typedef  itk::Image<itk::Vector<TCoordRep, SpaceDimension>, ImageDimension> CoefficientImageType;
+           typename CoefficientImageType::Pointer coefficientImage =bsplineTransform->GetCoefficientImage();
+           typedef itk::ImageFileWriter<CoefficientImageType> CoeffWriterType;
+           typename CoeffWriterType::Pointer coeffWriter=CoeffWriterType::New();
+           coeffWriter->SetInput(coefficientImage);
+           coeffWriter->SetFileName(m_ArgsInfo.coeff_arg[0]);
+           coeffWriter->Update();
+         }
+       else
+         {
+           BSplineTransformPointer bsplineTransform=dynamic_cast<BSplineTransformPointer>(registration->GetTransform());
+           typedef  itk::Image<TCoordRep, ImageDimension> CoefficientImageType;
+           typename CoefficientImageType::Pointer *coefficientImages =bsplineTransform->GetCoefficientImage();
+           typedef itk::ImageFileWriter<CoefficientImageType> CoeffWriterType;
+           for (unsigned int i=0;i<SpaceDimension; i ++)
+             {
+               typename CoeffWriterType::Pointer coeffWriter=CoeffWriterType::New();
+               coeffWriter->SetInput(coefficientImages[i]);
+               coeffWriter->SetFileName(m_ArgsInfo.coeff_arg[i]);
+               coeffWriter->Update();
+             }
+         }
+      }
+  
+  
+    //=======================================================
+    // Generate the DVF
+    //=======================================================
+    typedef itk::Vector< float, SpaceDimension >  DisplacementType;
+    typedef itk::Image< DisplacementType, ImageDimension >  DeformationFieldType;
+  
+    typename DeformationFieldType::Pointer field = DeformationFieldType::New();
+    field->SetRegions( fixedImageRegion );
+    field->SetOrigin( fixedImage->GetOrigin() );
+    field->SetSpacing( fixedImage->GetSpacing() );
+    field->SetDirection( fixedImage->GetDirection() );
+    field->Allocate();
+  
+    typedef itk::ImageRegionIteratorWithIndex< DeformationFieldType > FieldIterator;
+    FieldIterator fi( field, fixedImageRegion );
+    fi.GoToBegin();
+  
+    typename TransformType::InputPointType  fixedPoint;
+    typename TransformType::OutputPointType movingPoint;
+    typename DeformationFieldType::IndexType index;
+  
+    DisplacementType displacement;
+    while( ! fi.IsAtEnd() )
+      {
+       index = fi.GetIndex();
+       field->TransformIndexToPhysicalPoint( index, fixedPoint );
+       movingPoint = transform->TransformPoint( fixedPoint );
+       displacement = movingPoint - fixedPoint;
+       fi.Set( displacement );
+       ++fi;
+      }
+
+    //=======================================================
+    // Write the DVF
+    //=======================================================
+    typedef itk::ImageFileWriter< DeformationFieldType >  FieldWriterType;
+    typename FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+    fieldWriter->SetFileName( m_ArgsInfo.vf_arg );
+    fieldWriter->SetInput( field );
+    try
+      {
+       fieldWriter->Update();
+      }
+    catch( itk::ExceptionObject & excp )
+      {
+       std::cerr << "Exception thrown writing the DVF" << std::endl;
+       std::cerr << excp << std::endl;
+       return;
+      }
+  
+  
+    //=======================================================
+    // Resample the moving image
+    //=======================================================
+    typedef itk::WarpImageFilter< MovingImageType, FixedImageType, DeformationFieldType >    WarpFilterType;
+    typename WarpFilterType::Pointer warp = WarpFilterType::New();
+
+    warp->SetDeformationField( field );
+    warp->SetInput( movingImageReader->GetOutput() );
+    warp->SetOutputOrigin(  fixedImage->GetOrigin() );
+    warp->SetOutputSpacing( fixedImage->GetSpacing() );
+    warp->SetOutputDirection( fixedImage->GetDirection() );
+    warp->SetEdgePaddingValue( 0.0 );
+    warp->Update();
+
+    //=======================================================
+    // Write the warped image
+    //=======================================================
+    typedef itk::ImageFileWriter< FixedImageType >  WriterType;
+    typename WriterType::Pointer      writer =  WriterType::New();
+    writer->SetFileName( m_ArgsInfo.output_arg );
+    writer->SetInput( warp->GetOutput()    );
+
+    try
+      {
+       writer->Update();
+      }
+    catch( itk::ExceptionObject & err ) 
+      { 
+       std::cerr << "ExceptionObject caught !" << std::endl; 
+       std::cerr << err << std::endl; 
+       return;
+      } 
+
+    //=======================================================
+    // Calculate the difference after the deformable transform
+    //=======================================================
+    typedef clitk::DifferenceImageFilter<  FixedImageType, FixedImageType> DifferenceFilterType;
+    if (m_ArgsInfo.after_given)
+      {
+       typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
+       difference->SetValidInput( fixedImage );
+       difference->SetTestInput( warp->GetOutput() );
+      
+       try
+         {
+           difference->Update();
+         }
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught calculating the difference !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         }
+      
+       typename WriterType::Pointer differenceWriter=WriterType::New();
+       differenceWriter->SetInput(difference->GetOutput());
+       differenceWriter->SetFileName(m_ArgsInfo.after_arg);
+       differenceWriter->Update(); 
+      
+      }
+
+
+    //=======================================================
+    // Calculate the difference before the deformable transform
+    //=======================================================
+    if( m_ArgsInfo.before_given )
+      {
+
+       typename FixedImageType::Pointer moving=FixedImageType::New();
+       if (m_ArgsInfo.rigid_given)
+         {
+           typedef itk::ResampleImageFilter<MovingImageType, FixedImageType> ResamplerType;
+           typename ResamplerType::Pointer resampler=ResamplerType::New();
+           resampler->SetInput(movingImage);
+           resampler->SetOutputOrigin(fixedImage->GetOrigin());
+           resampler->SetSize(fixedImage->GetLargestPossibleRegion().GetSize());
+           resampler->SetOutputSpacing(fixedImage->GetSpacing());  
+           resampler->SetDefaultPixelValue( 0. );
+           //resampler->SetTransform(rigidTransform);
+           resampler->Update();
+           moving=resampler->GetOutput();
+         }
+       else
+         moving=movingImage;
+
+       typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
+       difference->SetValidInput( fixedImage );
+       difference->SetTestInput( moving );
+    
+       try
+         {
+           difference->Update();
+         }
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught calculating the difference !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         }
+
+       typename WriterType::Pointer differenceWriter=WriterType::New();
+       writer->SetFileName( m_ArgsInfo.before_arg  );
+       writer->SetInput( difference->GetOutput()  );
+       writer->Update( );
+      }
+
+    return;
+  }
+}
+
+#endif // __clitkBSplineDeformableRegistrationGenericFilter_txx
diff --git a/registration/clitkBSplineDeformableTransform.h b/registration/clitkBSplineDeformableTransform.h
new file mode 100644 (file)
index 0000000..2aeaac6
--- /dev/null
@@ -0,0 +1,365 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkBSplineDeformableTransform_h
+#define __clitkBSplineDeformableTransform_h
+#include "clitkVectorBSplineResampleImageFunctionWithLUT.h"
+
+//itk include
+#include "itkTransform.h"
+#include "itkImage.h"
+#include "itkImageRegion.h"
+#include "itkSpatialObject.h"
+
+namespace clitk
+{
+
+  template <
+    class TCoordRep = double,               // Data type for scalars, coordinate representation,vectors
+    unsigned int NInputDimensions = 3,        // Number of input dimensions
+    unsigned int NOutputDimensions = 3 >      // Number of output dimensions
+  class ITK_EXPORT BSplineDeformableTransform : 
+    public itk::Transform< TCoordRep, NInputDimensions, NOutputDimensions >
+  {
+  public:
+
+    //====================================================================
+    // Typedefs
+    //====================================================================
+    typedef BSplineDeformableTransform                         Self;
+    typedef itk::Transform< TCoordRep, NInputDimensions, NOutputDimensions > Superclass;
+    typedef itk::SmartPointer<Self>                                 Pointer;
+    typedef itk::SmartPointer<const Self>                           ConstPointer;
+      
+    /** New macro for creation of through the object factory.*/
+    itkNewMacro( Self );
+
+    /** Run-time type information (and related methods). */
+    itkTypeMacro( BSplineDeformableTransform, Transform );
+
+    /** Dimension of the domain space. */
+    itkStaticConstMacro(OutputDimension, unsigned int, NOutputDimensions);
+
+    /** Dimension of the input model. */
+    itkStaticConstMacro(InputDimension, unsigned int, NInputDimensions);
+
+    /** Standard scalar type for this class. */
+    typedef typename Superclass::ScalarType ScalarType;
+
+    /** Standard parameters container. */
+    typedef typename Superclass::ParametersType ParametersType;
+
+    /** Standard Jacobian container. */
+    typedef typename Superclass::JacobianType JacobianType;
+
+    /** Standard vector type for this class. */
+    typedef itk::Vector<TCoordRep,
+                       InputDimension> InputVectorType;
+    typedef itk::Vector<TCoordRep,
+                       OutputDimension> OutputVectorType;
+  
+    /** Standard covariant vector type for this class. */
+    typedef itk::CovariantVector<TCoordRep,
+                                InputDimension> InputCovariantVectorType;
+    typedef itk::CovariantVector<TCoordRep,
+                                OutputDimension> OutputCovariantVectorType;
+
+    /** Standard vnl_vector type for this class. */
+    typedef vnl_vector_fixed<TCoordRep,
+                            InputDimension> InputVnlVectorType;
+    typedef vnl_vector_fixed<TCoordRep,
+                            OutputDimension> OutputVnlVectorType;
+
+    /** Standard coordinate point type for this class. */
+    typedef itk::Point<TCoordRep,
+                      InputDimension> InputPointType;
+    typedef itk::Point<TCoordRep,
+                      OutputDimension> OutputPointType;
+
+    //JV Parameters as images with OutputDimension number of components per Pixel
+    typedef typename ParametersType::ValueType                          ParametersValueType;
+    typedef typename itk::Vector<ParametersValueType, OutputDimension>  PixelType;
+    typedef itk::Image<PixelType, InputDimension>                       CoefficientImageType;
+    typedef typename CoefficientImageType::Pointer                      CoefficientImagePointer;
+
+  
+    /** Typedefs for specifying the extend to the grid. */
+    typedef itk::ImageRegion<InputDimension>                RegionType;
+    typedef typename RegionType::IndexType                  IndexType;
+    typedef typename RegionType::SizeType                   SizeType;
+    typedef typename CoefficientImageType::SpacingType      SpacingType;
+    typedef typename CoefficientImageType::DirectionType    DirectionType;
+    typedef typename CoefficientImageType::PointType        OriginType;
+    typedef itk::ContinuousIndex<TCoordRep, InputDimension> ContinuousIndexType;
+  
+    //JV added for the BLUT interpolator
+    //typedef itk::Vector<TCoordRep, InputDimension> OutputSpacingType;
+
+    //JV m_VectorInterpolator
+    typedef VectorBSplineResampleImageFunctionWithLUT
+    <CoefficientImageType, TCoordRep> VectorInterpolatorType;
+    typedef  typename  VectorInterpolatorType::CoefficientDataType CoefficientDataType;
+    typedef  typename  VectorInterpolatorType::CoefficientDataType WeightsDataType;
+
+    /** Typedef of the bulk transform. */
+    typedef itk::Transform<ScalarType, InputDimension, OutputDimension> BulkTransformType;
+    typedef BulkTransformType*                  BulkTransformPointer;
+
+    /** Typedef of the mask */
+    typedef itk::SpatialObject<  InputDimension >   MaskType;
+    typedef MaskType*    MaskPointer;
+
+    //====================================================================
+    // Set et Gets
+    //====================================================================
+    //JV  added for the BLUT interpolator
+    void SetSplineOrder(const unsigned int &  splineOrder);
+    void SetSplineOrders(const SizeType &  splineOrders);
+    itkGetMacro( SplineOrders, SizeType );
+    itkGetConstMacro( SplineOrders, SizeType );
+    void SetLUTSamplingFactor(const int &  samplingFactor);
+    void SetLUTSamplingFactors(const SizeType &  samplingFactors);
+    itkGetMacro( LUTSamplingFactors, SizeType );
+    itkGetConstMacro( LUTSamplingFactors,SizeType );
+    //void SetOutputSpacing(const OutputSpacingType & outputSpacing);
+    //itkGetMacro( OutputSpacing, OutputSpacingType );
+    //itkGetConstMacro( OutputSpacing, OutputSpacingType );
+
+    void SetParameters(const ParametersType & parameters);
+  
+    void SetFixedParameters(const ParametersType & parameters);
+
+    void SetParametersByValue(const ParametersType & parameters);
+
+    void SetIdentity();
+
+    /** Get the Transformation Parameters. */
+    virtual const ParametersType& GetParameters(void) const;
+
+    /** Get the Transformation Fixed Parameters. */
+    virtual const ParametersType& GetFixedParameters(void) const;
+  
+    // The coefficientImage
+    virtual CoefficientImagePointer GetCoefficientImage()
+    { return m_CoefficientImage; }
+    virtual const CoefficientImagePointer  GetCoefficientImage() const
+    { return m_CoefficientImage; }
+    virtual void SetCoefficientImage(CoefficientImagePointer image);  
+
+    /** This method specifies the region over which the grid resides. */
+    virtual void SetGridRegion( const RegionType& region );
+    itkGetMacro( GridRegion, RegionType );
+    itkGetConstMacro( GridRegion, RegionType );
+
+    /** This method specifies the grid spacing or resolution. */
+    virtual void SetGridSpacing( const SpacingType& spacing );
+    itkGetMacro( GridSpacing, SpacingType );
+    itkGetConstMacro( GridSpacing, SpacingType );
+
+    /** This method specifies the grid directions . */
+    virtual void SetGridDirection( const DirectionType & spacing );
+    itkGetMacro( GridDirection, DirectionType );
+    itkGetConstMacro( GridDirection, DirectionType );
+
+    /** This method specifies the grid origin. */
+    virtual void SetGridOrigin( const OriginType& origin );
+    itkGetMacro( GridOrigin, OriginType );
+    itkGetConstMacro( GridOrigin, OriginType );
+    
+    // Set the bulk transform, real pointer
+    // itkSetConstObjectMacro( BulkTransform, BulkTransformType );
+    // itkGetConstObjectMacro( BulkTransform, BulkTransformType );
+    void SetBulkTransform(BulkTransformPointer b){m_BulkTransform=b;}
+    BulkTransformPointer GetBulkTransform(void) {return m_BulkTransform;}
+
+    //Set mask, inside transform applies, outside zero, real pointer
+    void SetMask(MaskPointer m){m_Mask=m;}
+    MaskPointer GetMask(void){return m_Mask;}
+    // itkSetConstObjectMacro( Mask, MaskType );
+    // itkGetConstObjectMacro( Mask, MaskType );
+
+    /** Transform points by a BSpline deformable transformation. */
+    OutputPointType  TransformPoint(const InputPointType  &point ) const;
+  
+    // JV added for just the deformable part, without bulk
+    OutputPointType  DeformablyTransformPoint(const InputPointType  &point ) const;
+  
+    /** Parameter index array type. */
+    typedef itk::Array<unsigned long> ParameterIndexArrayType;
+
+    /** Transform points by a BSpline deformable transformation. 
+     * On return, weights contains the interpolation weights used to compute the 
+     * deformation and indices of the x (zeroth) dimension coefficient parameters
+     * in the support region used to compute the deformation.
+     * Parameter indices for the i-th dimension can be obtained by adding
+     * ( i * this->GetNumberOfParametersPerDimension() ) to the indices array.
+     */
+
+    // JV not implemented
+    //  virtual void TransformPoint( const InputPointType & inputPoint,
+    //                                  OutputPointType & outputPoint,
+    //                                  WeightsType & weights,
+    //                                  ParameterIndexArrayType & indices, 
+    //                                  bool & inside ) const;
+    //     virtual void DeformablyTransformPoint( const InputPointType & inputPoint,
+    //                                            OutputPointType & outputPoint,
+    //                                            WeightsType & weights,
+    //                                            ParameterIndexArrayType & indices, 
+    //                                            bool & inside ) const;
+    //     virtual void GetJacobian( const InputPointType & inputPoint,
+    //                               WeightsType & weights,
+    //                               ParameterIndexArrayType & indices
+    //                               ) const;
+   
+    /** Method to transform a vector - 
+     *  not applicable for this type of transform. */
+    virtual OutputVectorType TransformVector(const InputVectorType &) const
+    { 
+      itkExceptionMacro(<< "Method not applicable for deformable transform." );
+      return OutputVectorType(); 
+    }
+
+    /** Method to transform a vnl_vector - 
+     *  not applicable for this type of transform */
+    virtual OutputVnlVectorType TransformVector(const InputVnlVectorType &) const
+    { 
+      itkExceptionMacro(<< "Method not applicable for deformable transform. ");
+      return OutputVnlVectorType(); 
+    }
+
+    /** Method to transform a CovariantVector - 
+     *  not applicable for this type of transform */
+    virtual OutputCovariantVectorType TransformCovariantVector(
+                                                              const InputCovariantVectorType &) const
+    { 
+      itkExceptionMacro(<< "Method not applicable for deformable transfrom. ");
+      return OutputCovariantVectorType(); 
+    } 
+    
+    /** Compute the Jacobian Matrix of the transformation at one point */
+    virtual const JacobianType& GetJacobian(const InputPointType  &point ) const;
+
+    /** Return the number of parameters that completely define the Transfom */
+    virtual unsigned int GetNumberOfParameters(void) const;
+
+    /** Return the number of parameters per dimension */
+    unsigned int GetNumberOfParametersPerDimension(void) const;
+
+    /** Return the region of the grid wholly within the support region */
+    itkGetConstReferenceMacro( ValidRegion, RegionType );
+
+    /** Indicates that this transform is linear. That is, given two
+     * points P and Q, and scalar coefficients a and b, then
+     *
+     *           T( a*P + b*Q ) = a * T(P) + b * T(Q)
+     */
+    virtual bool IsLinear() const { return false; }
+
+   //unsigned int GetNumberOfAffectedWeights() const;
+
+  protected:
+    /** Print contents of an BSplineDeformableTransform. */
+    void PrintSelf(std::ostream &os, itk::Indent indent) const;
+
+
+    BSplineDeformableTransform();
+    virtual ~BSplineDeformableTransform();
+
+    /** Wrap flat array into images of coefficients. */
+    void WrapAsImages();
+
+    /** Convert an input point to a continuous index inside the BSpline grid */
+    void TransformPointToContinuousIndex( const InputPointType & point, ContinuousIndexType & index ) const;
+
+  private:
+    BSplineDeformableTransform(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+
+    /** The bulk transform. */
+    BulkTransformPointer  m_BulkTransform;
+    MaskPointer m_Mask;
+
+    // JV added for BLUT interpolator
+    SizeType m_SplineOrders;
+    SizeType m_LUTSamplingFactors;
+
+    /** Variables defining the coefficient grid extend. */
+    RegionType    m_GridRegion;
+    SpacingType   m_GridSpacing;
+    DirectionType m_GridDirection;
+    OriginType    m_GridOrigin;
+
+    DirectionType m_PointToIndex;
+    DirectionType m_IndexToPoint;
+  
+    RegionType    m_ValidRegion;
+
+    /** Variables defining the interpolation support region. */
+    SizeType m_Offset;
+    itk::FixedArray<bool,InputDimension>    m_SplineOrderOdd;
+    SizeType      m_SupportSize;
+    IndexType     m_ValidRegionLast;
+  
+    /** Array holding images wrapped from the flat parameters. */
+    CoefficientImagePointer   m_WrappedImage;
+
+    /** Vector image representing the B-spline coefficients 
+     *  in each dimension. */
+    CoefficientImagePointer   m_CoefficientImage;
+
+    /** Jacobian as OutputDimension number of images. */
+    typedef typename JacobianType::ValueType JacobianValueType;
+    typedef typename itk::Vector<JacobianValueType,OutputDimension> JacobianPixelType;
+    typedef itk::Image<JacobianPixelType, OutputDimension> JacobianImageType;
+    typename JacobianImageType::Pointer m_JacobianImage[OutputDimension];
+    typedef itk::ImageRegionIterator<JacobianImageType> IteratorType;
+
+    /** Keep track of last support region used in computing the Jacobian
+     * for fast resetting of Jacobian to zero.
+     */
+    //JV for J calculation
+    mutable RegionType    m_SupportRegion;
+    mutable IndexType     m_SupportIndex;
+    mutable IndexType m_LastJacobianIndex;
+    mutable IteratorType m_Iterator[OutputDimension];
+    mutable JacobianPixelType m_ZeroVector;
+    mutable ContinuousIndexType m_Index;
+
+    /** Keep a pointer to the input parameters. */
+    const ParametersType *  m_InputParametersPointer;
+
+    /** Internal parameters buffer. */
+    ParametersType          m_InternalParametersBuffer;
+
+    //JV  the BLUT interpolator
+    typename VectorInterpolatorType::Pointer m_VectorInterpolator;
+  
+    /** Check if a continuous index is inside the valid region. */
+    bool InsideValidRegion( const ContinuousIndexType& index ) const;
+
+
+  }; //class BSplineDeformableTransform
+
+
+}  // namespace itk
+
+#if ITK_TEMPLATE_TXX
+# include "clitkBSplineDeformableTransform.txx"
+#endif
+
+
+#endif // __clitkBSplineDeformableTransform_h 
diff --git a/registration/clitkBSplineDeformableTransform.txx b/registration/clitkBSplineDeformableTransform.txx
new file mode 100644 (file)
index 0000000..4290191
--- /dev/null
@@ -0,0 +1,1043 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkBSplineDeformableTransform_txx
+#define __clitkBSplineDeformableTransform_tx
+#include "clitkBSplineDeformableTransform.h"
+
+//itk
+#include "itkContinuousIndex.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkImageRegionConstIteratorWithIndex.h"
+#include "itkIdentityTransform.h"
+
+namespace clitk
+{
+
+  // Constructor with default arguments
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::BSplineDeformableTransform():Superclass(OutputDimension,0)
+  {
+    unsigned int i;
+    
+    //JV default spline order
+    for ( i=0;i<InputDimension; i++)
+      m_SplineOrders[i]=3;
+
+    //JV default LUTSamplingfactor
+    for ( i=0;i<InputDimension; i++)
+      m_LUTSamplingFactors[i]=20;
+
+    for (i=0;i<InputDimension; i++)
+      m_SupportSize[i] = m_SplineOrders[i]+1;
+
+    //Instantiate a Vector Bspline Interpolator
+    m_VectorInterpolator =VectorInterpolatorType::New();
+    m_VectorInterpolator->SetLUTSamplingFactors(m_LUTSamplingFactors);
+    m_VectorInterpolator->SetSplineOrders(m_SplineOrders);
+
+    // Set Bulk transform to NULL (no bulk performed)
+    m_BulkTransform = NULL;
+
+    // Mask
+    m_Mask=NULL;
+
+    // Default grid size is zero
+    typename RegionType::SizeType size;
+    typename RegionType::IndexType index;
+    size.Fill( 0 );
+    index.Fill( 0 );
+    m_GridRegion.SetSize( size );
+    m_GridRegion.SetIndex( index );
+
+    m_GridOrigin.Fill( 0.0 );  // default origin is all zeros
+    m_GridSpacing.Fill( 1.0 ); // default spacing is all ones
+    m_GridDirection.SetIdentity(); // default spacing is all ones
+
+    m_InternalParametersBuffer = ParametersType(0);
+    // Make sure the parameters pointer is not NULL after construction.
+    m_InputParametersPointer = &m_InternalParametersBuffer;
+
+    // Initialize coeffient images
+    m_WrappedImage = CoefficientImageType::New();
+    m_WrappedImage->SetRegions( m_GridRegion );
+    m_WrappedImage->SetOrigin( m_GridOrigin.GetDataPointer() );
+    m_WrappedImage->SetSpacing( m_GridSpacing.GetDataPointer() );
+    m_WrappedImage->SetDirection( m_GridDirection );
+    m_CoefficientImage = NULL;
+  
+    // Variables for computing interpolation
+    for (i=0; i <InputDimension;i++)
+      {
+       m_Offset[i] = m_SplineOrders[i] / 2;
+       if ( m_SplineOrders[i] % 2 ) 
+         {
+           m_SplineOrderOdd[i] = true;
+         }
+       else
+         {
+           m_SplineOrderOdd[i] = false;
+         }
+      }
+    m_ValidRegion = m_GridRegion;
+       
+    // Initialize jacobian images 
+    for (i=0; i <OutputDimension;i++)
+      {
+       m_JacobianImage[i] = JacobianImageType::New();
+       m_JacobianImage[i]->SetRegions( m_GridRegion );
+       m_JacobianImage[i]->SetOrigin( m_GridOrigin.GetDataPointer() );
+       m_JacobianImage[i]->SetSpacing( m_GridSpacing.GetDataPointer() );
+       m_JacobianImage[i]->SetDirection( m_GridDirection );
+      }
+    
+    /** Fixed Parameters store the following information:
+     *     Grid Size
+     *     Grid Origin
+     *     Grid Spacing
+     *     Grid Direction */
+    //JV we add the splineOrders, LUTsamplingfactor, m_Mask  and m_BulkTransform
+    /*
+      Spline orders
+      Sampling factors
+      m_Mask
+      m_BulkTransform
+      The size of these is equal to the  NInputDimensions
+    *********************************************************/
+    this->m_FixedParameters.SetSize ( NInputDimensions * (NInputDimensions + 5)+2 );
+    this->m_FixedParameters.Fill ( 0.0 );
+    for ( i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[2*NInputDimensions+i] = m_GridSpacing[i];
+      }
+    for (unsigned int di=0; di<NInputDimensions; di++)
+      {
+       for (unsigned int dj=0; dj<NInputDimensions; dj++)
+         {
+           this->m_FixedParameters[3*NInputDimensions+(di*NInputDimensions+dj)] = m_GridDirection[di][dj];
+         }
+      }
+
+    //JV add splineOrders
+    for ( i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[ ( (3+NInputDimensions)*NInputDimensions)+i] = (this->GetSplineOrders())[i];
+      }
+    
+    //JV add LUTsamplingFactors
+    for ( i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[( (4+NInputDimensions)*NInputDimensions)+i ] = this->GetLUTSamplingFactors()[i];
+      }
+
+    // JV add the mask pointer
+    this->m_FixedParameters[( (5+NInputDimensions)*NInputDimensions)]=(double)((size_t)m_Mask);
+
+    // JV add the bulkTransform pointer
+    this->m_FixedParameters[( (5+NInputDimensions)*NInputDimensions) +1]=(double)((size_t)m_BulkTransform);
+
+
+    // Calculate the PointToIndex matrices
+    DirectionType scale;
+    for( unsigned int i=0; i<OutputDimension; i++)
+      {
+       scale[i][i] = m_GridSpacing[i];
+      }
+
+    m_IndexToPoint = m_GridDirection * scale;
+    m_PointToIndex = m_IndexToPoint.GetInverse();
+
+    // Jacobian
+    m_LastJacobianIndex = m_ValidRegion.GetIndex();
+
+    //JV initialize some variables for jacobian calculation
+    m_SupportRegion.SetSize(m_SupportSize);
+    m_SupportIndex.Fill(0);
+    m_SupportRegion.SetIndex(m_SupportIndex);
+    for (  i = 0; i < OutputDimension; i++ ) 
+      m_ZeroVector[i]=itk::NumericTraits<JacobianValueType>::Zero;
+  
+  }
+    
+
+  // Destructor
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::~BSplineDeformableTransform()
+  {
+
+  }
+
+
+  // JV set Spline Order
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetSplineOrder(const unsigned int & splineOrder)
+  {
+    SizeType splineOrders;
+    for (unsigned int i=0;i<InputDimension;i++)splineOrders[i]=splineOrder;
+
+    this->SetSplineOrders(splineOrders);
+  }
+   
+
+  // JV set Spline Orders
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetSplineOrders(const SizeType & splineOrders)
+  {
+    if(m_SplineOrders!=splineOrders)
+      {
+       m_SplineOrders=splineOrders;
+       
+       //update the interpolation function
+       m_VectorInterpolator->SetSplineOrders(m_SplineOrders);
+       
+       //update the varaibles for computing interpolation
+       for (unsigned int i=0; i <InputDimension;i++)
+         {
+           m_SupportSize[i] = m_SplineOrders[i]+1;
+           m_Offset[i] = m_SplineOrders[i] / 2;
+           
+           if ( m_SplineOrders[i] % 2 ) 
+             {
+               m_SplineOrderOdd[i] = true;
+             }
+           else
+             {
+               m_SplineOrderOdd[i] = false;
+             }
+         }
+       this->Modified();
+      }
+  }
+
+
+  // JV set sampling factor
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetLUTSamplingFactor( const int & samplingFactor)
+  {
+    SizeType samplingFactors;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      samplingFactors[i]=samplingFactor;
+    
+    //update the interpolation function
+    this->SetLUTSamplingFactors(samplingFactors);
+  }
+
+
+  // JV set sampling factors
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetLUTSamplingFactors( const SizeType & samplingFactors)
+  {
+    if(m_LUTSamplingFactors!=samplingFactors)
+      {
+       for (unsigned int i=0; i<NInputDimensions; i++)
+         m_LUTSamplingFactors[i]=samplingFactors[i];
+       
+       //update the interpolation function
+       m_VectorInterpolator->SetLUTSamplingFactors(m_LUTSamplingFactors);
+       
+       this->Modified();
+      }
+  }
+
+
+  // Get the number of parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  unsigned int
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetNumberOfParameters(void) const
+  {
+
+    // The number of parameters equal OutputDimension * number of
+    // of pixels in the grid region.
+    return ( static_cast<unsigned int>( OutputDimension ) *
+            static_cast<unsigned int>( m_GridRegion.GetNumberOfPixels() ) );
+
+  }
+
+
+  // Get the number of parameters per dimension
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  unsigned int
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetNumberOfParametersPerDimension(void) const
+  {
+    // The number of parameters per dimension equal number of
+    // of pixels in the grid region.
+    return ( static_cast<unsigned int>( m_GridRegion.GetNumberOfPixels() ) );
+
+  }
+
+
+  // Set the grid region
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridRegion( const RegionType & region )
+  {
+    if ( m_GridRegion != region )
+      {
+       m_GridRegion = region;
+
+       // set regions for each coefficient and jacobian image
+       m_WrappedImage->SetRegions( m_GridRegion );
+       for (unsigned int j=0; j <OutputDimension;j++)
+         m_JacobianImage[j]->SetRegions( m_GridRegion );
+       
+       // Set the valid region
+       // If the grid spans the interval [start, last].
+       // The valid interval for evaluation is [start+offset, last-offset]
+       // when spline order is even.
+       // The valid interval for evaluation is [start+offset, last-offset)
+       // when spline order is odd.
+       // Where offset = vcl_floor(spline / 2 ).
+       // Note that the last pixel is not included in the valid region
+       // with odd spline orders.
+       typename RegionType::SizeType size = m_GridRegion.GetSize();
+       typename RegionType::IndexType index = m_GridRegion.GetIndex();
+       for ( unsigned int j = 0; j < NInputDimensions; j++ )
+         {
+           index[j] += 
+             static_cast< typename RegionType::IndexValueType >( m_Offset[j] );
+           size[j] -= 
+             static_cast< typename RegionType::SizeValueType> ( 2 * m_Offset[j] );
+           m_ValidRegionLast[j] = index[j] +
+             static_cast< typename RegionType::IndexValueType >( size[j] ) - 1;
+         }
+       m_ValidRegion.SetSize( size );
+       m_ValidRegion.SetIndex( index );
+
+       // If we are using the default parameters, update their size and set to identity.
+       // Input parameters point to internal buffer => using default parameters.
+       if (m_InputParametersPointer == &m_InternalParametersBuffer)
+         {
+           // Check if we need to resize the default parameter buffer.
+           if ( m_InternalParametersBuffer.GetSize() != this->GetNumberOfParameters() )
+             {
+               m_InternalParametersBuffer.SetSize( this->GetNumberOfParameters() );
+               // Fill with zeros for identity.
+               m_InternalParametersBuffer.Fill( 0 );
+             }
+         }
+
+       this->Modified();
+      }
+  }
+
+
+  // Set the grid spacing
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridSpacing( const SpacingType & spacing )
+  {
+    if ( m_GridSpacing != spacing )
+      {
+       m_GridSpacing = spacing;
+
+       // Set spacing for each coefficient and jacobian image
+       m_WrappedImage->SetSpacing( m_GridSpacing.GetDataPointer() );
+       for (unsigned int j=0; j <OutputDimension; j++) m_JacobianImage[j]->SetSpacing( m_GridSpacing.GetDataPointer() );
+       
+       // Set scale
+       DirectionType scale;
+       for( unsigned int i=0; i<OutputDimension; i++)
+         {
+           scale[i][i] = m_GridSpacing[i];
+         }
+
+       m_IndexToPoint = m_GridDirection * scale;
+       m_PointToIndex = m_IndexToPoint.GetInverse();
+
+       this->Modified();
+      }
+
+  }
+
+  // Set the grid direction
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridDirection( const DirectionType & direction )
+  {
+    if ( m_GridDirection != direction )
+      {
+       m_GridDirection = direction;
+
+       // Set direction for each coefficient and jacobian image
+       m_WrappedImage->SetDirection( m_GridDirection );
+       for (unsigned int j=0; j <OutputDimension; j++) m_JacobianImage[j]->SetDirection( m_GridDirection );
+       
+       // Set scale
+       DirectionType scale;
+       for( unsigned int i=0; i<OutputDimension; i++)
+         {
+           scale[i][i] = m_GridSpacing[i];
+         }
+
+       m_IndexToPoint = m_GridDirection * scale;
+       m_PointToIndex = m_IndexToPoint.GetInverse();
+
+       this->Modified();
+      }
+
+  }
+
+
+  // Set the grid origin
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridOrigin( const OriginType& origin )
+  {
+    if ( m_GridOrigin != origin )
+      {
+       m_GridOrigin = origin;
+
+       // Set origin for each coefficient and jacobianimage
+       m_WrappedImage->SetOrigin( m_GridOrigin.GetDataPointer() );
+       for (unsigned int j=0; j <OutputDimension; j++) m_JacobianImage[j]->SetOrigin( m_GridOrigin.GetDataPointer() );
+       
+       this->Modified();
+      }
+
+  }
+
+
+  // Set the parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetIdentity()
+  {
+    if( m_InputParametersPointer )
+      {
+       ParametersType * parameters =
+         const_cast<ParametersType *>( m_InputParametersPointer );
+       parameters->Fill( 0.0 );
+       this->Modified();
+      }
+    else 
+      {
+       itkExceptionMacro( << "Input parameters for the spline haven't been set ! "
+                          << "Set them using the SetParameters or SetCoefficientImage method first." );
+      }
+  }
+
+
+  // Set the parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetParameters( const ParametersType & parameters )
+  {
+
+    // Check if the number of parameters match the
+    // Expected number of parameters
+    if ( parameters.Size() != this->GetNumberOfParameters() )
+      {
+       itkExceptionMacro(<<"Mismatched between parameters size "
+                         << parameters.size() 
+                         << " and region size "
+                         << m_GridRegion.GetNumberOfPixels() );
+      }
+
+    // Clean up buffered parameters
+    m_InternalParametersBuffer = ParametersType( 0 );
+
+    // Keep a reference to the input parameters
+    m_InputParametersPointer = &parameters;
+
+    // Wrap flat array as images of coefficients
+    this->WrapAsImages();
+
+    //Set input to vector interpolator
+    m_VectorInterpolator->SetInputImage(this->GetCoefficientImage());
+
+    // Modified is always called since we just have a pointer to the
+    // parameters and cannot know if the parameters have changed.
+    this->Modified();
+  }
+
+
+  // Set the Fixed Parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetFixedParameters( const ParametersType & parameters )
+  {
+    // JV number should be exact, no defaults for spacing
+    if ( parameters.Size() != NInputDimensions * (5 + NInputDimensions)+2 )
+      {
+       itkExceptionMacro(<< "Mismatched between parameters size "
+                         << parameters.size() 
+                         << " and number of fixed parameters "
+                         << NInputDimensions * (5 + NInputDimensions)+2 );
+      }
+    /********************************************************* 
+    Fixed Parameters store the following information:
+        Grid Size
+        Grid Origin
+        Grid Spacing
+        Grid Direction */
+    // JV we add the splineOrders, LUTsamplingfactor, mask pointer and bulktransform pointer
+    /*
+      Spline orders
+      Sampling factors
+      m_Mask
+      m_BulkTransform
+    The size of these is equal to the  NInputDimensions
+    *********************************************************/
+  
+    /** Set the Grid Parameters */
+    SizeType   gridSize;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       gridSize[i] = static_cast<int> (parameters[i]);
+      }
+    RegionType bsplineRegion;
+    bsplineRegion.SetSize( gridSize );
+  
+    /** Set the Origin Parameters */
+    OriginType origin;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       origin[i] = parameters[NInputDimensions+i];
+      }
+  
+    /** Set the Spacing Parameters */
+    SpacingType spacing;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       spacing[i] = parameters[2*NInputDimensions+i];
+      }
+
+    /** Set the Direction Parameters */
+    DirectionType direction;
+    for (unsigned int di=0; di<NInputDimensions; di++)
+      {
+       for (unsigned int dj=0; dj<NInputDimensions; dj++)
+         {
+           direction[di][dj] = parameters[3*NInputDimensions+(di*NInputDimensions+dj)];
+         }
+      }
+
+    //JV add the spline orders
+    SizeType splineOrders;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       splineOrders[i]=parameters[(3+NInputDimensions)*NInputDimensions+i];
+      }
+
+    //JV add the LUT sampling factor
+    SizeType  samplingFactors;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       samplingFactors[i]=parameters[(4+NInputDimensions)*NInputDimensions+i];
+      }
+
+    //JV add the MaskPointer
+    m_Mask=((MaskPointer)( (size_t)parameters[(5+NInputDimensions)*NInputDimensions]));
+
+    //JV add the MaskPointer
+    m_BulkTransform=((BulkTransformPointer)( (size_t)parameters[(5+NInputDimensions)*NInputDimensions+1]));
+
+    //Set the members
+    this->SetGridSpacing( spacing );
+    this->SetGridDirection( direction );
+    this->SetGridOrigin( origin );
+    this->SetGridRegion( bsplineRegion );
+
+    //JV add the LUT parameters
+    this->SetSplineOrders( splineOrders );
+    this->SetLUTSamplingFactors( samplingFactors );
+      
+  }
+
+
+  // Wrap flat parameters as images
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::WrapAsImages()
+  {
+    //JV Wrap parameter array in vectorial image, changed parameter order: A1x A1y A1z, A2x ....
+    PixelType * dataPointer =reinterpret_cast<PixelType *>( const_cast<double *>(m_InputParametersPointer->data_block() )) ;
+    unsigned int numberOfPixels = m_GridRegion.GetNumberOfPixels();
+    
+    m_WrappedImage->GetPixelContainer()->SetImportPointer( dataPointer,numberOfPixels);//InputDimension
+    m_CoefficientImage = m_WrappedImage;
+    
+    //JV Wrap jacobian into OutputDimension X Vectorial images
+    this->m_Jacobian.set_size( OutputDimension, this->GetNumberOfParameters() );
+
+    // Use memset to set the memory
+    JacobianPixelType * jacobianDataPointer = reinterpret_cast<JacobianPixelType *>(this->m_Jacobian.data_block());
+    memset(jacobianDataPointer, 0,  OutputDimension*numberOfPixels*sizeof(JacobianPixelType));
+    m_LastJacobianIndex = m_ValidRegion.GetIndex();
+
+    for (unsigned int j=0; j<OutputDimension; j++)
+      {
+       m_JacobianImage[j]->GetPixelContainer()->
+         SetImportPointer( jacobianDataPointer, numberOfPixels );
+       jacobianDataPointer += numberOfPixels;
+     }
+  }
+
+
+  // Set the parameters by value
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetParametersByValue( const ParametersType & parameters )
+  {
+
+    // Check if the number of parameters match the
+    // Expected number of parameters
+    if ( parameters.Size() != this->GetNumberOfParameters() )
+      {
+       itkExceptionMacro(<<"Mismatched between parameters size "
+                         << parameters.size() 
+                         << " and region size "
+                         << m_GridRegion.GetNumberOfPixels() );
+      }
+
+    // Copy it
+    m_InternalParametersBuffer = parameters;
+    m_InputParametersPointer = &m_InternalParametersBuffer;
+
+    // Wrap flat array as images of coefficients
+    this->WrapAsImages();
+
+    // Modified is always called since we just have a pointer to the
+    // Parameters and cannot know if the parameters have changed.
+    this->Modified();
+
+  }
+
+  // Get the parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  const 
+  typename BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::ParametersType &
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetParameters( void ) const
+  {
+    /** NOTE: For efficiency, this class does not keep a copy of the parameters - 
+     * it just keeps pointer to input parameters. 
+     */
+    if (NULL == m_InputParametersPointer)
+      {
+       itkExceptionMacro( <<"Cannot GetParameters() because m_InputParametersPointer is NULL. Perhaps SetCoefficientImage() has been called causing the NULL pointer." );
+      }
+
+    return (*m_InputParametersPointer);
+  }
+
+
+  // Get the parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  const 
+  typename BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::ParametersType &
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetFixedParameters( void ) const
+  {
+    RegionType resRegion = this->GetGridRegion(  );
+  
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[i] = (resRegion.GetSize())[i];
+      }
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[NInputDimensions+i] = (this->GetGridOrigin())[i];
+      } 
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[2*NInputDimensions+i] =  (this->GetGridSpacing())[i];
+      }
+    for (unsigned int di=0; di<NInputDimensions; di++)
+      {
+       for (unsigned int dj=0; dj<NInputDimensions; dj++)
+         {
+           this->m_FixedParameters[3*NInputDimensions+(di*NInputDimensions+dj)] = (this->GetGridDirection())[di][dj];
+         }
+      }
+
+    //JV add splineOrders
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[(3+NInputDimensions)*NInputDimensions+i] = (this->GetSplineOrders())[i];
+      }
+    
+    //JV add LUTsamplingFactor
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[(4+NInputDimensions)*NInputDimensions+i] = (this->GetLUTSamplingFactors())[i];
+      }
+    
+    //JV add the mask
+    this->m_FixedParameters[(5+NInputDimensions)*NInputDimensions]=(double)((size_t) m_Mask);
+
+    //JV add the bulktransform pointer
+    this->m_FixedParameters[(5+NInputDimensions)*NInputDimensions+1]=(double)((size_t) m_BulkTransform);
+    
+    return (this->m_FixedParameters);
+  }
+
+  
+  // Set the B-Spline coefficients using input images
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void 
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetCoefficientImage( CoefficientImagePointer image )
+  {
+    
+    this->SetGridRegion( image->GetBufferedRegion() );
+    this->SetGridSpacing( image->GetSpacing() );
+    this->SetGridDirection( image->GetDirection() );
+    this->SetGridOrigin( image->GetOrigin() );
+    m_CoefficientImage = image;
+
+    // Update the interpolator    
+    m_VectorInterpolator->SetInputImage(this->GetCoefficientImage());
+
+    // Clean up buffered parameters
+    m_InternalParametersBuffer = ParametersType( 0 );
+    m_InputParametersPointer  = NULL;
+      
+  }  
+
+
+  // Print self
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::PrintSelf(std::ostream &os, itk::Indent indent) const
+  {
+
+    this->Superclass::PrintSelf(os, indent);
+
+    os << indent << "GridRegion: " << m_GridRegion << std::endl;
+    os << indent << "GridOrigin: " << m_GridOrigin << std::endl;
+    os << indent << "GridSpacing: " << m_GridSpacing << std::endl;
+    os << indent << "GridDirection: " << m_GridDirection << std::endl;
+    os << indent << "IndexToPoint: " << m_IndexToPoint << std::endl;
+    os << indent << "PointToIndex: " << m_PointToIndex << std::endl;
+
+    os << indent << "CoefficientImage: [ ";
+    os << m_CoefficientImage.GetPointer() << " ]" << std::endl;
+
+    os << indent << "WrappedImage: [ ";
+    os << m_WrappedImage.GetPointer() << " ]" << std::endl;
+    os << indent << "InputParametersPointer: " 
+       << m_InputParametersPointer << std::endl;
+    os << indent << "ValidRegion: " << m_ValidRegion << std::endl;
+    os << indent << "LastJacobianIndex: " << m_LastJacobianIndex << std::endl;
+    os << indent << "BulkTransform: ";
+    os << m_BulkTransform << std::endl;
+
+    if ( m_BulkTransform )
+      {
+       os << indent << "BulkTransformType: " 
+          << m_BulkTransform->GetNameOfClass() << std::endl;
+      }
+    os << indent << "VectorBSplineInterpolator: ";
+    os << m_VectorInterpolator.GetPointer() << std::endl;
+    os << indent << "Mask: ";
+    os << m_Mask<< std::endl;
+  }
+
+
+  // Verify 
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  bool 
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::InsideValidRegion( const ContinuousIndexType& index ) const
+  {
+    bool inside = true;
+
+    if ( !m_ValidRegion.IsInside( index ) )
+      {
+       inside = false;
+      }
+    //JV verify for each input dimension
+    if ( inside)
+      {
+       typedef typename ContinuousIndexType::ValueType ValueType;
+       for( unsigned int j = 0; j < InputDimension; j++ )
+         {
+           if (m_SplineOrderOdd[j])
+             {
+               if ( index[j] >= static_cast<ValueType>( m_ValidRegionLast[j] ) )
+                 { 
+                   inside = false;
+                   break;
+                 }
+             }
+         }
+      }
+    
+    return inside;
+  }
+
+
+  // Transform a point
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  typename BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::OutputPointType
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::TransformPoint(const InputPointType &inputPoint) const 
+  {
+  
+   InputPointType transformedPoint;
+   OutputPointType outputPoint;
+
+   // BulkTransform
+   if ( m_BulkTransform )
+     {
+       transformedPoint = m_BulkTransform->TransformPoint( inputPoint );
+     }
+   else
+      {
+       transformedPoint = inputPoint;
+      }
+   
+    // Deformable transform
+    if ( m_CoefficientImage )
+      {
+       // Check if inside mask
+       if(m_Mask &&  !(m_Mask->IsInside(inputPoint) ) )
+         {
+           // Outside: no (deformable) displacement
+           return transformedPoint;
+         }             
+       
+       // Check if inside valid region
+       bool inside = true;
+       ContinuousIndexType index;
+       this->TransformPointToContinuousIndex( inputPoint, index );
+       inside = this->InsideValidRegion( index );
+       if ( !inside )
+         {
+           // Outside: no (deformable) displacement
+           return transformedPoint;
+         }
+       
+       // Call the vector interpolator
+       itk::Vector<TCoordRep,OutputDimension> displacement=m_VectorInterpolator->EvaluateAtContinuousIndex(index);
+
+       // Return the results
+       outputPoint = transformedPoint+displacement;
+
+      }
+
+    else
+      {
+       itkWarningMacro( << "B-spline coefficients have not been set" );
+       outputPoint = transformedPoint;
+      }
+    
+    return outputPoint;
+  }
+
+
+
+  //JV Deformably transform a point
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  typename BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::OutputPointType
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::DeformablyTransformPoint(const InputPointType &inputPoint) const 
+  {
+    OutputPointType outputPoint;
+    if ( m_CoefficientImage )
+      {
+
+       // Check if inside mask
+       if(m_Mask && !(m_Mask->IsInside(inputPoint) ) )
+         {
+           // Outside: no (deformable) displacement
+           return inputPoint;
+         }     
+       
+       // Check if inside
+       bool inside = true;
+       ContinuousIndexType index;
+       this->TransformPointToContinuousIndex( inputPoint, index );
+       inside = this->InsideValidRegion( index );
+
+       if ( !inside )
+         {
+           //outside: no (deformable) displacement
+            return inputPoint;
+            //return outputPoint;
+         }
+
+       // Call the vector interpolator
+       itk::Vector<TCoordRep,OutputDimension> displacement=m_VectorInterpolator->EvaluateAtContinuousIndex(index);
+       
+       // Return the results
+       outputPoint = inputPoint+displacement;
+      }
+
+    // No coefficients available
+    else
+      {
+       itkWarningMacro( << "B-spline coefficients have not been set" );
+       outputPoint = inputPoint;
+      }
+   
+    return outputPoint;
+  }
+  
+
+  // JV weights are identical as for transformpoint, could be done simultaneously in metric!!!!
+  // Compute the Jacobian in one position 
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  const 
+  typename BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::JacobianType & 
+  BSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetJacobian( const InputPointType & point ) const
+  {
+    // Can only compute Jacobian if parameters are set via
+    // SetParameters or SetParametersByValue
+    //     if( m_InputParametersPointer == NULL )
+    //       {
+    //         itkExceptionMacro( <<"Cannot compute Jacobian: parameters not set" );
+    //       }
+
+  
+    //========================================================
+    // Zero all components of jacobian
+    //========================================================
+    // JV not thread safe (m_LastJacobianIndex), instantiate N transforms
+    // NOTE: for efficiency, we only need to zero out the coefficients
+    // that got fill last time this method was called.
+
+    unsigned int j=0;
+      
+    //Define the  region for each jacobian image 
+    m_SupportRegion.SetIndex( m_LastJacobianIndex );
+    
+    //Initialize the iterators
+    for ( j = 0; j < OutputDimension; j++ ) 
+      m_Iterator[j] = IteratorType( m_JacobianImage[j], m_SupportRegion);
+    
+    //Set the previously-set to zero 
+    while ( ! (m_Iterator[0]).IsAtEnd() )
+      {
+       for ( j = 0; j < OutputDimension; j++ )
+         {
+           m_Iterator[j].Set( m_ZeroVector );
+           ++(m_Iterator[j]);
+         }
+      }
+    
+    //========================================================
+    // For each dimension, copy the weight to the support region
+    //========================================================
+
+    // Check if inside mask
+    if(m_Mask &&  !(m_Mask->IsInside(point) ) )
+      {
+       // Outside: no (deformable) displacement
+       return this->m_Jacobian;
+      }        
+
+    //Get index   
+    this->TransformPointToContinuousIndex( point, m_Index );
+
+    // NOTE: if the support region does not lie totally within the grid
+    // we assume zero displacement and return the input point
+    if ( !this->InsideValidRegion( m_Index ) )
+      {
+       return this->m_Jacobian;
+      }
+
+    //Compute interpolation weights
+    const WeightsDataType *weights=NULL;
+    m_VectorInterpolator->EvaluateWeightsAtContinuousIndex( m_Index, &weights, m_LastJacobianIndex);
+    m_SupportRegion.SetIndex( m_LastJacobianIndex );
+
+    //Reset the iterators
+    for ( j = 0; j < OutputDimension; j++ ) 
+      m_Iterator[j] = IteratorType( m_JacobianImage[j], m_SupportRegion);
+
+    // For each dimension, copy the weight to the support region
+    while ( ! (m_Iterator[0]).IsAtEnd() )
+      {
+       //copy weight to jacobian image
+       for ( j = 0; j < OutputDimension; j++ )
+         {
+           m_ZeroVector[j]=*weights;
+           (m_Iterator[j]).Set( m_ZeroVector);
+           m_ZeroVector[j]=itk::NumericTraits<JacobianValueType>::Zero;
+           ++(m_Iterator[j]);
+         }
+       // go to next coefficient in the support region
+       weights++;
+      }
+
+    // Return the result
+    return this->m_Jacobian;
+
+  }
+
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  BSplineDeformableTransform<TCoordRep, NInputDimensions,NOutputDimensions>
+  ::TransformPointToContinuousIndex( const InputPointType & point, ContinuousIndexType & index ) const
+  {
+    unsigned int j;
+
+    itk::Vector<double, OutputDimension> tvector;
+
+    for ( j = 0; j < OutputDimension; j++ )
+      {
+       tvector[j] = point[j] - this->m_GridOrigin[j];
+      }
+
+    itk::Vector<double, OutputDimension> cvector;
+
+    cvector = m_PointToIndex * tvector;
+
+    for ( j = 0; j < OutputDimension; j++ )
+      {
+       index[j] = static_cast< typename ContinuousIndexType::CoordRepType >( cvector[j] );
+      }
+  }
+
+
+} // namespace
+
+#endif
diff --git a/registration/clitkBSplineDeformableTransformInitializer.h b/registration/clitkBSplineDeformableTransformInitializer.h
new file mode 100644 (file)
index 0000000..6b2971a
--- /dev/null
@@ -0,0 +1,174 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkBSplineDeformableTransformInitializer_h
+#define __clitkBSplineDeformableTransformInitializer_h
+#include "clitkResampleBSplineDeformableTransformImageFilter.h"
+
+#include "itkObject.h"
+#include "itkObjectFactory.h"
+#include <iostream>
+
+namespace clitk
+{
+
+
+template < class TTransform, class TImage >
+class ITK_EXPORT BSplineDeformableTransformInitializer : public itk::Object
+{
+public:
+  /** Standard class typedefs. */
+  typedef BSplineDeformableTransformInitializer     Self;
+  typedef itk::Object                               Superclass;
+  typedef itk::SmartPointer<Self>                   Pointer;
+  typedef itk::SmartPointer<const Self>             ConstPointer;
+
+  /** New macro for creation of through a Smart Pointer. */
+  itkNewMacro( Self );
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( BSplineDeformableTransformInitializer, Object );
+
+  // Typedefs
+  typedef TTransform                                TransformType;
+  typedef typename TransformType::Pointer           TransformPointer;
+  typedef typename TransformType::RegionType        RegionType;
+  typedef typename RegionType::SizeType             SizeType;
+  typedef typename TransformType::SpacingType       SpacingType;
+  itkStaticConstMacro(InputDimension, unsigned int, TransformType::InputDimension);
+  typedef   TImage                                  ImageType;
+  typedef typename ImageType::ConstPointer        ImagePointer;
+  typedef typename TransformType::CoefficientImageType CoefficientImageType;
+  typedef typename TransformType::ParametersType ParametersType;
+
+  // Set and Get
+  itkBooleanMacro(Verbose);
+  itkSetMacro( Verbose, bool);
+  itkGetConstReferenceMacro( Verbose, bool);
+   itkSetObjectMacro( Transform,   TransformType   );
+  itkGetConstObjectMacro( Transform,   TransformType   );
+  itkSetObjectMacro( Image,  ImageType  );
+  itkGetConstObjectMacro( Image,  ImageType  );
+  void SetSplineOrder(const unsigned int & splineOrder)
+  {
+    SizeType s;
+    s.Fill(splineOrder);
+    this->SetSplineOrders(s);
+  }
+  void SetSplineOrders(const SizeType & splineOrders)
+  {
+    m_SplineOrders=splineOrders;
+  }
+  void SetNumberOfControlPointsInsideTheImage(  SizeType & n  )
+  {
+    m_NumberOfControlPointsInsideTheImage=n;
+    m_NumberOfControlPointsIsGiven=true;
+    this->Modified();
+  }
+  void SetNumberOfControlPointsInsideTheImage(  int * n)
+  {
+    SizeType s;
+    for (unsigned int i=0;i<InputDimension;i++) 
+      s[i]=n[i];
+    this->SetNumberOfControlPointsInsideTheImage( s );
+  }
+  void SetNumberOfControlPointsInsideTheImage(  unsigned int & n )
+  {
+    SizeType s;
+    s.Fill( n );;
+    this->SetNumberOfControlPointsInsideTheImage( s );
+  }
+  void SetControlPointSpacing( SpacingType n )
+  {
+    m_ControlPointSpacing= n;
+    m_ControlPointSpacingIsGiven=true;
+    this->Modified();
+  }
+  void SetControlPointSpacing( double*& n )
+  {
+    SpacingType s( n );
+    this->SetControlPointSpacing(s);
+  }
+  void SetControlPointSpacing( double n )
+  {
+    SpacingType s;
+    s.Fill( n );
+    this->SetControlPointSpacing(s);
+  }
+  void SetSamplingFactors(  SizeType n  )
+  {
+    m_SamplingFactors=n;
+    m_SamplingFactorIsGiven=true;
+    this->Modified();
+  }
+  void SetSamplingFactors(  int *& n)
+  {
+    SizeType s;
+    for (unsigned int i=0;i<InputDimension;i++) 
+      s[i]=n[i];
+    this-> SetSamplingFactors( s );
+  }
+  void SetSamplingFactors( unsigned  int n )
+  {
+    SizeType s;
+    s.Fill( n );
+    this-> SetSamplingFactors( s );
+  }
+  virtual void InitializeTransform();
+  void SetInitialParameters(const typename CoefficientImageType::Pointer coefficientImage, ParametersType& params);
+  void SetInitialParameters(const std::string & s, ParametersType& params);
+  // For easy acces, declared public
+  std::vector<SizeType> m_NumberOfControlPointsInsideTheImageArray;
+  std::vector<SizeType> m_SamplingFactorsArray;
+  std::vector<SpacingType> m_ControlPointSpacingArray;
+
+  SpacingType   m_ControlPointSpacing;
+  SizeType   m_SamplingFactors;
+  SizeType   m_SplineOrders;
+  SpacingType   m_ChosenSpacing;
+  SizeType   m_NumberOfControlPointsInsideTheImage;
+  bool m_NumberOfControlPointsIsGiven;
+  bool m_ControlPointSpacingIsGiven;
+  bool m_SamplingFactorIsGiven;
+  bool m_TransformRegionIsGiven;
+
+  typename TransformType::ParametersType* m_Parameters;
+
+protected:
+  BSplineDeformableTransformInitializer();
+  ~BSplineDeformableTransformInitializer(){};
+
+private:
+  BSplineDeformableTransformInitializer(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+  bool m_Verbose;
+  TransformPointer    m_Transform;
+  ImagePointer        m_Image;
+  
+}; //class BSplineDeformableTransformInitializer
+
+
+}  // namespace clitk
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkBSplineDeformableTransformInitializer.txx"
+#endif
+
+#endif /* __clitkBSplineDeformableTransformInitializer_h */
diff --git a/registration/clitkBSplineDeformableTransformInitializer.txx b/registration/clitkBSplineDeformableTransformInitializer.txx
new file mode 100644 (file)
index 0000000..0a93ab0
--- /dev/null
@@ -0,0 +1,244 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkBSplineDeformableTransformInitializer_txx
+#define __clitkBSplineDeformableTransformInitializer_txx
+#include "clitkBSplineDeformableTransformInitializer.h"
+
+namespace clitk
+{
+
+
+  template < class TTransform, class TImage >
+  BSplineDeformableTransformInitializer<TTransform, TImage >
+  ::BSplineDeformableTransformInitializer()
+  {
+    this->m_NumberOfControlPointsInsideTheImage.Fill( 5 );
+    this->m_ControlPointSpacing.Fill(64.);
+    this->m_ChosenSpacing.Fill(64.);
+    m_NumberOfControlPointsIsGiven=false;
+    m_ControlPointSpacingIsGiven=false;
+    m_TransformRegionIsGiven=false;
+    m_SamplingFactorIsGiven=false;
+    m_SplineOrders.Fill(3);
+    m_Parameters=NULL;
+  }
+
+  template < class TTransform, class TImage >
+  void
+  BSplineDeformableTransformInitializer<TTransform, TImage >
+  ::InitializeTransform()
+  {
+    // Sanity check:
+    // The image is required for the region and spacing
+    if( ! this->m_Image )
+      {
+       itkExceptionMacro( "Reference Image has not been set" );
+       return;
+      }
+    
+    // A pointer to the transform is required
+    if( ! this->m_Transform )
+      {
+       itkExceptionMacro( "Transform has not been set" );
+       return;
+      }
+
+    // If the image come from a filter, then update that filter.
+    if( this->m_Image->GetSource() )
+      {
+       this->m_Image->GetSource()->Update();
+      }
+
+
+    //--------------------------------------
+    // Spacing & Size on image
+    //--------------------------------------
+    SpacingType fixedImageSpacing = m_Image->GetSpacing();
+    SizeType fixedImageSize=m_Image->GetLargestPossibleRegion().GetSize();
+    typename RegionType::SizeType   gridBorderSize;
+    typename RegionType::SizeType   totalGridSize;
+
+    // Only spacing given: adjust if necessary
+    if (m_ControlPointSpacingIsGiven  && !m_NumberOfControlPointsIsGiven)
+      {
+       for(unsigned int r=0; r<InputDimension; r++) 
+         {
+           // JV
+           m_ChosenSpacing[r]= m_ControlPointSpacing[r];
+           m_ControlPointSpacing[r]= ( round(m_ChosenSpacing[r]/fixedImageSpacing[r]) *fixedImageSpacing[r] ) ;
+           m_NumberOfControlPointsInsideTheImage[r] = ceil( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] );
+           if (  ( ceil( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] ) )
+                == ( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] ) )
+             {
+               m_NumberOfControlPointsInsideTheImage[r] +=1;
+               DD("Adding control point");
+             }
+         }
+      }
+  
+    // Only number of CP given: adjust if necessary
+    // JV -1 ?
+    else if (!m_ControlPointSpacingIsGiven  && m_NumberOfControlPointsIsGiven)
+      {
+       for(unsigned int r=0; r<InputDimension; r++) 
+         {
+           m_ChosenSpacing[r]=fixedImageSpacing[r]*( (double)(fixedImageSize[r])  / 
+                                                     (double)(m_NumberOfControlPointsInsideTheImage[r]) );
+           m_ControlPointSpacing[r]= fixedImageSpacing[r]* ceil( (double)(fixedImageSize[r] - 1)  / 
+                                                                 (double)(m_NumberOfControlPointsInsideTheImage[r] - 1) );
+         }
+      }
+  
+    // Both or none of Spacing and number of CP given: no adjustment adjust, just warnings
+    else 
+      {
+       for(unsigned int r=0; r<InputDimension; r++) 
+         {
+           m_ChosenSpacing[r]= m_ControlPointSpacing[r];
+           if (m_NumberOfControlPointsInsideTheImage[r]*m_ControlPointSpacing[r]< fixedImageSize[r]*fixedImageSpacing[r]) 
+             {
+               std::cout<<"WARNING: Specified control point region ("<<m_NumberOfControlPointsInsideTheImage[r]*m_ControlPointSpacing[r]
+                        <<"mm) does not cover the fixed image region ("<< fixedImageSize[r]*fixedImageSpacing[r]
+                        <<"mm) for dimension "<<r<<"!" <<std::endl
+                        <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;
+             }
+           if (  fmod(m_ControlPointSpacing[r], fixedImageSpacing[r]) ) 
+             {
+               std::cout<<"WARNING: Specified control point spacing for dimension "<<r
+                        <<" does not allow exact representation of BLUT FFD!"<<std::endl
+                        <<"Spacing ratio is non-integer: "<<m_ControlPointSpacing[r]/ fixedImageSpacing[r]<<std::endl
+                        <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;  
+             }
+         }
+      }
+
+    if (m_Verbose) std::cout<<"The chosen control point spacing "<<m_ChosenSpacing<<"..."<<std::endl;
+    if (m_Verbose) std::cout<<"The control points spacing was adapted to "<<m_ControlPointSpacing<<"..."<<std::endl; 
+    if (m_Verbose) std::cout<<"The number of (internal) control points is "<<m_NumberOfControlPointsInsideTheImage<<"..."<<std::endl; 
+    
+
+    //--------------------------------------
+    // Border size 
+    //--------------------------------------
+    for(unsigned int r=0; r<InputDimension; r++) gridBorderSize[r]=m_SplineOrders[r]; // Border for spline order = 3 ( 1 lower, 2 upper )
+    totalGridSize = m_NumberOfControlPointsInsideTheImage + gridBorderSize;
+    if (m_Verbose) std::cout<<"The total control point grid size was set to "<<totalGridSize<<"..."<<std::endl;
+    RegionType gridRegion;
+    gridRegion.SetSize(totalGridSize);
+  
+    //--------------------------------------
+    // Origin
+    //--------------------------------------
+    typedef typename TransformType::OriginType OriginType;
+    OriginType fixedImageOrigin, gridOrigin;
+
+    // In case of non-zero index
+    m_Image->TransformIndexToPhysicalPoint(m_Image->GetLargestPossibleRegion().GetIndex(),fixedImageOrigin);
+    typename ImageType::DirectionType gridDirection = m_Image->GetDirection();      
+    SizeType orderShift;
+
+    // Shift depends on order
+    for(unsigned int r=0; r<InputDimension; r++)
+      {
+       orderShift[r] = m_SplineOrders[r] / 2;
+       gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
+      } 
+    if (m_Verbose) std::cout<<"The control point grid origin was set to "<<gridOrigin<<"..."<<std::endl;
+
+
+    //--------------------------------------
+    // LUT sampling factors
+    //--------------------------------------
+    for (unsigned int i=0; i< InputDimension; i++)
+      {
+       if (m_Verbose) std::cout<<"For dimension "<<i<<", the ideal sampling factor (if integer) is a multitude of "
+                               << m_ControlPointSpacing[i]/ fixedImageSpacing[i]<<"..."<<std::endl;
+       if ( !m_SamplingFactorIsGiven) m_SamplingFactors[i]= (int) ( m_ControlPointSpacing[i]/ fixedImageSpacing[i]);
+       if (m_Verbose) std::cout<<"Setting sampling factor "<<i<<" to "<<m_SamplingFactors[i]<<"..."<<std::endl;
+      }
+
+
+    //--------------------------------------
+    // Set
+    //--------------------------------------
+    this->m_Transform->SetSplineOrders(m_SplineOrders);
+    this->m_Transform->SetGridRegion( gridRegion );
+    this->m_Transform->SetGridOrigin( gridOrigin );
+    this->m_Transform->SetGridSpacing( m_ControlPointSpacing );
+    this->m_Transform->SetGridDirection( gridDirection );
+    this->m_Transform->SetLUTSamplingFactors(m_SamplingFactors);
+
+  }
+
+  template < class TTransform, class TImage >
+  void
+  BSplineDeformableTransformInitializer<TTransform, TImage >
+  ::SetInitialParameters( const std::string& s, ParametersType& params) 
+  {
+    //---------------------------------------
+    // Read Initial parameters
+    //---------------------------------------
+    typedef itk::ImageFileReader<CoefficientImageType> CoefficientReaderType;
+    typename CoefficientReaderType::Pointer coeffReader=CoefficientReaderType::New();
+    coeffReader->SetFileName(s);
+    if(m_Verbose) std::cout<<"Reading initial coefficients from file: "<<s<<"..."<<std::endl;
+    coeffReader->Update();
+    typename CoefficientImageType::Pointer coefficientImage=coeffReader->GetOutput();
+    this->SetInitialParameters(coefficientImage, params);
+  }
+  
+  template < class TTransform, class TImage >
+  void
+  BSplineDeformableTransformInitializer<TTransform, TImage >
+  ::SetInitialParameters(const typename CoefficientImageType::Pointer coefficientImage, ParametersType& params) 
+  {
+    // Keep a reference 
+    m_Parameters=&params;
+
+    // Resample
+    typedef ResampleBSplineDeformableTransformImageFilter<CoefficientImageType,CoefficientImageType> ResamplerType;
+    typename ResamplerType::Pointer resampler=ResamplerType::New();
+    resampler->SetInput(coefficientImage);     
+    resampler->SetOutputParametersFromImage(m_Transform->GetCoefficientImage()); 
+    if(m_Verbose) std::cout<<"Resampling initial coefficients..."<<std::endl;
+    resampler->Update();
+
+    // Copy parameters into the existing array, I know its crappy
+    typedef itk::ImageRegionConstIterator<CoefficientImageType> Iterator;
+    Iterator it (resampler->GetOutput(), resampler->GetOutput()->GetLargestPossibleRegion() );
+    it.GoToBegin();
+    unsigned int i=0;
+    while(! it.IsAtEnd())
+      {
+       for (unsigned int j=0; j<InputDimension;j++)
+         params[i+j]=it.Get()[j];
+
+       ++it;
+       i+=InputDimension;
+      }
+
+    // JV pass the reference to the array !!
+    this->m_Transform->SetParameters(params);
+  }
+
+
+  
+}  // namespace itk
+
+#endif
diff --git a/registration/clitkBSplinePyramid.cxx b/registration/clitkBSplinePyramid.cxx
new file mode 100644 (file)
index 0000000..c06d83f
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkBSplinePyramid.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkBSplinePyramid_ggo.h"
+#include "clitkIO.h"
+#include "clitkBSplinePyramidGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkBSplinePyramid, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::BSplinePyramidGenericFilter::Pointer genericFilter=clitk::BSplinePyramidGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkBSplinePyramid.ggo b/registration/clitkBSplinePyramid.ggo
new file mode 100644 (file)
index 0000000..823135e
--- /dev/null
@@ -0,0 +1,15 @@
+#File clitkBSplinePyramid.ggo
+Package "clitkBSplinePyramid"
+version "1.0"
+purpose "Down (or Up) sample with a  factor 2 using Bspline pyramids. BSplineDownsampleImageFilter is BUGGED! See the ITK post of jvdmb@hotmail.com."
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+option "input"         i       "Input image filename"            string        yes
+option "output"        o       "Output image filename"           string        yes
+
+
+option "up"            u       "Upsample instead of downsample"                  flag  off
+option "resamplerType" t       "The type of B-spline resampler used: 0=resampler, 1=L2, 2=centered, 3=L2 centered"     int     no      default="0"
+option "splineOrder"   -       "Spline order"  int     no      default="3"
diff --git a/registration/clitkBSplinePyramidGenericFilter.cxx b/registration/clitkBSplinePyramidGenericFilter.cxx
new file mode 100644 (file)
index 0000000..2c1ff64
--- /dev/null
@@ -0,0 +1,72 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkBSplinePyramidGenericFilter_cxx
+#define clitkBSplinePyramidGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkBSplinePyramidGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkBSplinePyramidGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  BSplinePyramidGenericFilter::BSplinePyramidGenericFilter()
+  {
+    m_Verbose=false;
+    m_InputFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void BSplinePyramidGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension, Components;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType, Components);
+
+    
+    // Call UpdateWithDim
+    if(Dimension==2) UpdateWithDim<2>(PixelType, Components);
+    else if(Dimension==3) UpdateWithDim<3>(PixelType, Components);
+    else if (Dimension==4)UpdateWithDim<4>(PixelType, Components); 
+    else 
+      {
+       std::cout<<"Error, Only for 2, 3 or 4  Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkBSplinePyramidGenericFilter_cxx
diff --git a/registration/clitkBSplinePyramidGenericFilter.h b/registration/clitkBSplinePyramidGenericFilter.h
new file mode 100644 (file)
index 0000000..b51dc27
--- /dev/null
@@ -0,0 +1,120 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkBSplinePyramidGenericFilter_h
+#define clitkBSplinePyramidGenericFilter_h
+
+/* =================================================
+ * @file   clitkBSplinePyramidGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkImageCommon.h"
+#include "clitkBSplinePyramid_ggo.h"
+#include "clitkVectorImageToImageFilter.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkBSplineDownsampleImageFilter.h"
+#include "itkBSplineUpsampleImageFilter.h"
+#include "itkCompose3DVectorImageFilter.h"
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT BSplinePyramidGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef BSplinePyramidGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( BSplinePyramidGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkBSplinePyramid & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+      m_InputFileName=m_ArgsInfo.input_arg;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    BSplinePyramidGenericFilter();
+    ~BSplinePyramidGenericFilter() {};
+
+    
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <unsigned int Dimension>  void UpdateWithDim(std::string PixelType, unsigned int Components);
+    template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+    template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndVectorType();
+
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkBSplinePyramid m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_InputFileName;
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkBSplinePyramidGenericFilter.txx"
+#endif
+
+#endif // #define clitkBSplinePyramidGenericFilter_h
diff --git a/registration/clitkBSplinePyramidGenericFilter.txx b/registration/clitkBSplinePyramidGenericFilter.txx
new file mode 100644 (file)
index 0000000..c0768b9
--- /dev/null
@@ -0,0 +1,398 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkBSplinePyramidGenericFilter_txx
+#define clitkBSplinePyramidGenericFilter_txx
+
+/* =================================================
+ * @file   clitkBSplinePyramidGenericFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+namespace clitk
+{
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions
+  //-------------------------------------------------------------------
+  template<unsigned int Dimension>
+  void 
+  BSplinePyramidGenericFilter::UpdateWithDim(std::string PixelType, unsigned int Components)
+  {
+    if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<<Components<<" component(s) of "<<  PixelType<<"..."<<std::endl;
+    
+    if (Components==1)
+      {
+       if(PixelType == "short"){  
+         if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
+         UpdateWithDimAndPixelType<Dimension, signed short>(); 
+       }
+       //    else if(PixelType == "unsigned_short"){  
+       //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
+       //       UpdateWithDimAndPixelType<Dimension, unsigned short>(); 
+       //     }
+       
+       else if (PixelType == "unsigned_char"){ 
+         if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
+         UpdateWithDimAndPixelType<Dimension, unsigned char>();
+       }
+       
+       //     else if (PixelType == "char"){ 
+       //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
+       //       UpdateWithDimAndPixelType<Dimension, signed char>();
+       //     }
+       else {
+         if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
+         UpdateWithDimAndPixelType<Dimension, float>();
+       }
+      }
+    else if (Components==3)
+      {
+       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and 3D float (DVF)" << std::endl;
+       UpdateWithDimAndVectorType<Dimension, itk::Vector<float, 3> >();
+      }
+    else std::cerr<<"Number of components is "<<Components<<", not supported!"<<std::endl;
+    
+  }
+
+
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions and the pixeltype
+  //-------------------------------------------------------------------
+  template <unsigned int Dimension, class  PixelType> 
+  void 
+  BSplinePyramidGenericFilter::UpdateWithDimAndPixelType()
+  {
+
+    // ImageTypes
+    typedef itk::Image<PixelType, Dimension> InputImageType;
+    typedef itk::Image<PixelType, Dimension> OutputImageType;
+    
+    // Read the input
+    typedef itk::ImageFileReader<InputImageType> InputReaderType;
+    typename InputReaderType::Pointer reader = InputReaderType::New();
+    reader->SetFileName( m_InputFileName);
+    reader->Update();
+    typename InputImageType::Pointer input= reader->GetOutput();
+
+    // Resampler Types
+    typedef itk::BSplineResampleImageFilterBase<InputImageType, InputImageType> ResamplerType;
+    typedef itk::BSplineCenteredResampleImageFilterBase<InputImageType, InputImageType> CenteredResamplerType;
+    typedef itk::BSplineL2ResampleImageFilterBase<InputImageType, InputImageType> L2ResamplerType;
+    typedef itk::BSplineCenteredL2ResampleImageFilterBase<InputImageType, InputImageType> CenteredL2ResamplerType;
+    
+    // Filter
+    typedef itk::ImageToImageFilter< InputImageType, InputImageType > ImageToImageFilterType;
+    typename  ImageToImageFilterType::Pointer filter;
+
+    if (!m_ArgsInfo.up_flag)
+      {
+       switch (m_ArgsInfo.resamplerType_arg)
+         {
+           
+           // Resampler
+         case 0: {
+           typename itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, ResamplerType >::Pointer df 
+             = itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, ResamplerType >::New();
+           df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+           filter=df;
+           if (m_Verbose) std::cout<<"Using the BSpline downsample image filter with standard Resampler"<<std::endl;
+           break;
+         }
+           
+           //CenteredResamplerType
+         case 1: {
+           typename itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, CenteredResamplerType >::Pointer df 
+             = itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, CenteredResamplerType >::New();
+           df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+           filter=df;
+           if (m_Verbose) std::cout<<"Using the BSpline downsample image filter with centered Resampler"<<std::endl;
+           break;
+         }
+         
+           //L2ResamplerType
+         case 2:
+           {
+             typename itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, L2ResamplerType >::Pointer df 
+               = itk::BSplineDownsampleImageFilter< InputImageType,InputImageType,L2ResamplerType >::New();
+             df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);   
+             filter=df;
+             if (m_Verbose) std::cout<<"Using the BSpline downsample image filter with L2 Resampler"<<std::endl;
+             break;
+           }
+         
+           //Centered L2ResamplerType
+         case 3:
+           {
+             typename itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, CenteredL2ResamplerType >::Pointer df 
+               = itk::BSplineDownsampleImageFilter< InputImageType,InputImageType,CenteredL2ResamplerType >::New();
+             df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+             filter=df;
+             if (m_Verbose) std::cout<<"Using the BSpline downsample image filter with L2 centered Resampler"<<std::endl;
+             break;
+           }
+
+         }
+      }
+    else
+      {
+       switch (m_ArgsInfo.resamplerType_arg)
+         {
+           
+           // Resampler
+         case 0: {
+           typename itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, ResamplerType >::Pointer df 
+             = itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, ResamplerType >::New();
+           df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+           filter=df;
+           if (m_Verbose) std::cout<<"Using the BSpline upsample image filter with standard Resampler"<<std::endl;
+           break;
+         }
+           
+           //CenteredResamplerType
+         case 1: {
+           typename itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, CenteredResamplerType >::Pointer df 
+             = itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, CenteredResamplerType >::New();
+           df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+           filter=df;
+           if (m_Verbose) std::cout<<"Using the BSpline upsample image filter with centered Resampler"<<std::endl;
+           break;
+         }
+         
+           //L2ResamplerType
+         case 2:
+           {
+             typename itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, L2ResamplerType >::Pointer df 
+               = itk::BSplineUpsampleImageFilter< InputImageType,InputImageType,L2ResamplerType >::New();
+             df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);   
+             filter=df;
+             if (m_Verbose) std::cout<<"Using the BSpline upsample image filter with L2 Resampler"<<std::endl;
+             break;
+           }
+         
+           //Centered L2ResamplerType
+         case 3:
+           {
+             typename itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, CenteredL2ResamplerType >::Pointer df 
+               = itk::BSplineUpsampleImageFilter< InputImageType,InputImageType,CenteredL2ResamplerType >::New();
+             df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+             filter=df;
+             if (m_Verbose) std::cout<<"Using the BSpline upsample image filter with L2 centered Resampler"<<std::endl;
+             break;
+           }
+
+         }
+      }
+
+
+    // Update
+    filter->SetInput(input);
+    filter->Update();
+    typename OutputImageType::Pointer output=filter->GetOutput();
+         
+    // Output
+    typedef itk::ImageFileWriter<OutputImageType> WriterType;
+    typename WriterType::Pointer writer = WriterType::New();
+    writer->SetFileName(m_ArgsInfo.output_arg);
+    writer->SetInput(output);
+    writer->Update();
+
+  }
+  
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions and the pixeltype
+  //-------------------------------------------------------------------
+  template <unsigned int Dimension, class  VectorType> 
+  void 
+  BSplinePyramidGenericFilter::UpdateWithDimAndVectorType()
+  {
+
+    // ImageTypes
+    typedef typename VectorType::ValueType PixelType;
+    typedef itk::Image<VectorType, Dimension> VectorInputImageType;
+    typedef itk::Image<PixelType, Dimension> InputImageType;
+    typedef itk::Image<PixelType, Dimension> OutputImageType;
+    typedef itk::Image<VectorType, Dimension> VectorOutputImageType;
+    
+    // Read the input
+    typedef itk::ImageFileReader<VectorInputImageType> InputReaderType;
+    typename InputReaderType::Pointer reader = InputReaderType::New();
+    reader->SetFileName( m_InputFileName);
+    reader->Update();
+    typename VectorInputImageType::Pointer vectorInput= reader->GetOutput();
+
+    // Process components separetely and gather afterwards
+    std::vector<typename OutputImageType::Pointer> components;
+
+    for (unsigned int i=0; i<3;i++)
+      {
+       // Extract component
+       typedef clitk::VectorImageToImageFilter<VectorInputImageType, OutputImageType> FilterType;
+       typename FilterType::Pointer dfilter=FilterType::New();
+       dfilter->SetInput(vectorInput);
+       dfilter->SetComponentIndex(i);
+       dfilter->Update();
+       typename InputImageType::Pointer input=dfilter->GetOutput();
+
+       //============================================================================================
+       // Resampler Types
+       typedef itk::BSplineResampleImageFilterBase<InputImageType, InputImageType> ResamplerType;
+       typedef itk::BSplineCenteredResampleImageFilterBase<InputImageType, InputImageType> CenteredResamplerType;
+       typedef itk::BSplineL2ResampleImageFilterBase<InputImageType, InputImageType> L2ResamplerType;
+       typedef itk::BSplineCenteredL2ResampleImageFilterBase<InputImageType, InputImageType> CenteredL2ResamplerType;
+       
+       // Filter
+       typedef itk::ImageToImageFilter< InputImageType, InputImageType > ImageToImageFilterType;
+       typename  ImageToImageFilterType::Pointer filter;
+       
+       if (!m_ArgsInfo.up_flag)
+         {
+           switch (m_ArgsInfo.resamplerType_arg)
+             {
+               
+               // Resampler
+             case 0: {
+               typename itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, ResamplerType >::Pointer df 
+                 = itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, ResamplerType >::New();
+               df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+               filter=df;
+               if (m_Verbose) std::cout<<"Using the BSpline downsample image filter with standard Resampler"<<std::endl;
+               break;
+             }
+           
+               //CenteredResamplerType
+             case 1: {
+               typename itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, CenteredResamplerType >::Pointer df 
+                 = itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, CenteredResamplerType >::New();
+               df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+               filter=df;
+               if (m_Verbose) std::cout<<"Using the BSpline downsample image filter with centered Resampler"<<std::endl;
+               break;
+             }
+         
+               //L2ResamplerType
+             case 2:
+               {
+                 typename itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, L2ResamplerType >::Pointer df 
+                   = itk::BSplineDownsampleImageFilter< InputImageType,InputImageType,L2ResamplerType >::New();
+                 df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);       
+                 filter=df;
+                 if (m_Verbose) std::cout<<"Using the BSpline downsample image filter with L2 Resampler"<<std::endl;
+                 break;
+               }
+         
+               //Centered L2ResamplerType
+             case 3:
+               {
+                 typename itk::BSplineDownsampleImageFilter< InputImageType,InputImageType, CenteredL2ResamplerType >::Pointer df 
+                   = itk::BSplineDownsampleImageFilter< InputImageType,InputImageType,CenteredL2ResamplerType >::New();
+                 df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+                 filter=df;
+                 if (m_Verbose) std::cout<<"Using the BSpline downsample image filter with L2 centered Resampler"<<std::endl;
+                 break;
+               }
+
+             }
+         }
+       else
+         {
+           switch (m_ArgsInfo.resamplerType_arg)
+             {
+           
+               // Resampler
+             case 0: {
+               typename itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, ResamplerType >::Pointer df 
+                 = itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, ResamplerType >::New();
+               df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+               filter=df;
+               if (m_Verbose) std::cout<<"Using the BSpline upsample image filter with standard Resampler"<<std::endl;
+               break;
+             }
+           
+               //CenteredResamplerType
+             case 1: {
+               typename itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, CenteredResamplerType >::Pointer df 
+                 = itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, CenteredResamplerType >::New();
+               df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+               filter=df;
+               if (m_Verbose) std::cout<<"Using the BSpline upsample image filter with centered Resampler"<<std::endl;
+               break;
+             }
+         
+               //L2ResamplerType
+             case 2:
+               {
+                 typename itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, L2ResamplerType >::Pointer df 
+                   = itk::BSplineUpsampleImageFilter< InputImageType,InputImageType,L2ResamplerType >::New();
+                 df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);       
+                 filter=df;
+                 if (m_Verbose) std::cout<<"Using the BSpline upsample image filter with L2 Resampler"<<std::endl;
+                 break;
+               }
+         
+               //Centered L2ResamplerType
+             case 3:
+               {
+                 typename itk::BSplineUpsampleImageFilter< InputImageType,InputImageType, CenteredL2ResamplerType >::Pointer df 
+                   = itk::BSplineUpsampleImageFilter< InputImageType,InputImageType,CenteredL2ResamplerType >::New();
+                 df->SetSplineOrder(m_ArgsInfo.splineOrder_arg);
+                 filter=df;
+                 if (m_Verbose) std::cout<<"Using the BSpline upsample image filter with L2 centered Resampler"<<std::endl;
+                 break;
+               }
+
+             }
+         }
+
+       // Update
+       filter->SetInput(input);
+       filter->Update();
+       typename OutputImageType::Pointer output=filter->GetOutput();
+
+       //===============================================================================
+       // keep component
+       components.push_back(output);
+      }
+    
+    // Join
+    typedef itk::Compose3DVectorImageFilter<InputImageType,VectorOutputImageType> ComposeFilterType;
+    typename ComposeFilterType::Pointer composeFilter=ComposeFilterType::New();
+    for (unsigned int i=0; i<3;i++)
+      composeFilter->SetInput(i,components[i]);
+    composeFilter->Update();
+    typename VectorOutputImageType::Pointer vectorOutput = composeFilter->GetOutput();
+
+         
+    // Output
+    typedef itk::ImageFileWriter<VectorOutputImageType> WriterType;
+    typename WriterType::Pointer writer = WriterType::New();
+    writer->SetFileName(m_ArgsInfo.output_arg);
+    writer->SetInput(vectorOutput);
+    writer->Update();
+
+  }
+  
+}//end clitk
+#endif //#define clitkBSplinePyramidGenericFilter_txx
diff --git a/registration/clitkCalculateTRE.cxx b/registration/clitkCalculateTRE.cxx
new file mode 100755 (executable)
index 0000000..af66b75
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkCalculateTRE.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkCalculateTRE_ggo.h"
+#include "clitkIO.h"
+#include "clitkCalculateTREGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkCalculateTRE, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::CalculateTREGenericFilter::Pointer genericFilter=clitk::CalculateTREGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkCalculateTRE.ggo b/registration/clitkCalculateTRE.ggo
new file mode 100755 (executable)
index 0000000..3a79d16
--- /dev/null
@@ -0,0 +1,33 @@
+#File clitkCalculateTRE.ggo
+Package "clitkCalculateTRE"
+version "1.0"
+purpose "Calculate TRE: give a reference point list and 1 or more target point lists. In case of the latter, the number of DVF (or the size of the 4th D) given should match the number of lists. Use --shipFirst to skip the first phase of a 4D DVF. General summarizes for all points (mean, SD, max) in magnitude and par component. Tre and warp gives all values for all points. "
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+
+section "Input"
+
+option "ref"                   -       "List of points in reference"           string          yes                     
+option "input"         i       "Lists of points in targets"            string          multiple        yes
+option "vf"                    -       "Input deformation fields"              string          multiple        yes
+option "skip"          -       "Skip a phase of a 4D DVF"              int             no      
+
+section "Interpolation"
+
+option "interpVF"      -       "Interpolation: 0=NN, 1=Linear, 2=BSpline, 3=BLUT"      int     no  default="1"
+option "interpVFOrder" -       "Order if BLUT or BSpline (0-5)"                        int     no  default="3"
+option "interpVFSF"    -       "Sampling factor if BLUT"                               int     no  default="20"
+
+
+section "Output"
+
+option "general"               -       "Summarized TRE values (mean, SD, max)" string          no      
+option "original"              -       "Original distances: base filename"     string          no      
+option "originalMag"           -       "Original magnitude of distances: base filename"        string          no      
+option "displacement"          -       "Estmated displacements: base filename" string          no      
+option "displacementMag"       -       "Estimated magnitude displacements: base filename"      string          no
+option "tre"                   -       "All TRE values: base filename"         string          no      
+option "treMag"                        -       "All TRE magnitude values: base filename"               string          no      
+option "warp"                  -       "All warped points: base filename"      string          no      
diff --git a/registration/clitkCalculateTREGenericFilter.cxx b/registration/clitkCalculateTREGenericFilter.cxx
new file mode 100755 (executable)
index 0000000..1da773b
--- /dev/null
@@ -0,0 +1,137 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkCalculateTREGenericFilter_cxx
+#define clitkCalculateTREGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkCalculateTREGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkCalculateTREGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  CalculateTREGenericFilter::CalculateTREGenericFilter()
+  {
+    m_Verbose=false;
+    m_InputFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void CalculateTREGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension, Components;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType, Components);
+
+    
+    // Call UpdateWithDim
+    if(Dimension==2) ReadVectorFields<2,2>();
+    else if(Dimension==3) ReadVectorFields<3,3>();
+    else if (Dimension==4)ReadVectorFields<4,3>(); 
+    else 
+      {
+       std::cout<<"Error, Only for 2, 3 or 4  Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+
+
+  //-----------------------------
+  // Process DVF
+  //-----------------------------
+  template< >
+  void 
+  CalculateTREGenericFilter::ProcessVectorFields<4,3>(std::vector<itk::Image<itk::Vector<float, 3>, 4>::Pointer > dvfs,  char** filenames )
+  {
+    // Typedefs
+    typedef itk::Vector<float,3> PixelType;
+    typedef itk::Image<PixelType, 4> InputImageType;
+    typedef itk::Image<PixelType, 3> OutputImageType;
+
+    // IO
+    InputImageType::Pointer input=dvfs[0];
+    std::vector<itk::Image<itk::Vector<float, 3>, 3>::Pointer > new_dvfs;
+    
+    // Split vector field
+    typedef itk::ExtractImageFilter<InputImageType,OutputImageType> FilterType;
+    unsigned int splitDimension=3;
+
+    // Make new file names
+    std::vector<std::string> new_filenames;
+    std::string base = filenames[0];
+
+    // Set the extract region
+    InputImageType::SizeType size=input->GetLargestPossibleRegion().GetSize();
+    size[splitDimension]=0;
+    InputImageType::RegionType extracted_region;
+    extracted_region.SetSize(size);
+    InputImageType::IndexType index=input->GetLargestPossibleRegion().GetIndex();
+    
+  
+    // Loop
+    for (unsigned int i=0;i<input->GetLargestPossibleRegion().GetSize()[splitDimension];i++)
+      {
+       
+       // Skip?
+       if (m_ArgsInfo.skip_given && i==(unsigned int) m_ArgsInfo.skip_arg) continue;
+
+       // extract dvf
+        FilterType::Pointer filter= FilterType::New();
+       filter->SetInput(input);
+       index[splitDimension]=i;
+       extracted_region.SetIndex(index);
+       filter->SetExtractionRegion(extracted_region);
+       filter->Update();
+       new_dvfs.push_back(filter->GetOutput());
+       
+       // make name
+       std::ostringstream number_dvf;
+       number_dvf << i;
+       std::string number =  number_dvf.str();
+       new_filenames.push_back(base+"_"+number);
+      }
+
+    // Update
+    this->UpdateWithDim<3>(new_dvfs, new_filenames); 
+
+  }
+
+
+
+
+  
+} //end clitk
+
+#endif  //#define clitkCalculateTREGenericFilter_cxx
diff --git a/registration/clitkCalculateTREGenericFilter.h b/registration/clitkCalculateTREGenericFilter.h
new file mode 100755 (executable)
index 0000000..d9caea1
--- /dev/null
@@ -0,0 +1,124 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkCalculateTREGenericFilter_h
+#define clitkCalculateTREGenericFilter_h
+
+/* =================================================
+ * @file   clitkCalculateTREGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkCalculateTRE_ggo.h"
+#include "clitkGenericVectorInterpolator.h"
+#include "clitkPointListWriter.h"
+#include "clitkPointListReader.h"
+#include "clitkDeformationListStatisticsFilter.h"
+#include "clitkList.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkExtractImageFilter.h"
+
+//general
+#include <iomanip>
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT CalculateTREGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef CalculateTREGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( CalculateTREGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkCalculateTRE& a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+      m_InputFileName=m_ArgsInfo.vf_arg[0];
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    CalculateTREGenericFilter();
+    ~CalculateTREGenericFilter() {};
+
+    
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <unsigned int Dimension,unsigned int Components> void ReadVectorFields(void);
+    template <unsigned int Dimension,unsigned int Components> void ProcessVectorFields(std::vector< typename itk::Image<itk::Vector<float, Components>, Dimension>::Pointer > dvfs, char** filenames);
+    template <unsigned int Dimension> void UpdateWithDim( std::vector<typename itk::Image<itk::Vector<float, Dimension>, Dimension>::Pointer > dvfs,  std::vector<std::string> filenames);
+    
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkCalculateTRE m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_InputFileName;
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkCalculateTREGenericFilter.txx"
+#endif
+
+#endif // #define clitkCalculateTREGenericFilter_h
diff --git a/registration/clitkCalculateTREGenericFilter.txx b/registration/clitkCalculateTREGenericFilter.txx
new file mode 100755 (executable)
index 0000000..1198ac8
--- /dev/null
@@ -0,0 +1,606 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkCalculateTREGenericFilter_txx
+#define clitkCalculateTREGenericFilter_txx
+
+/* =================================================
+ * @file   clitkCalculateTREGenericFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+namespace clitk
+{
+  
+  //-----------------------------
+  // Read DVF
+  //-----------------------------
+  template<unsigned int Dimension, unsigned int Components >
+  void 
+  CalculateTREGenericFilter::ReadVectorFields(void)
+  {
+    
+    typedef itk::Vector<float, Components> VectorType;
+    typedef itk::Image<VectorType, Dimension> DeformationFieldType;
+
+    typedef itk::ImageFileReader<DeformationFieldType> InputReaderType;    
+    std::vector<typename DeformationFieldType::Pointer> dvfs;
+    for (unsigned int i=0; i< m_ArgsInfo.vf_given; i++)
+      {
+       typename InputReaderType::Pointer reader = InputReaderType::New();
+       reader->SetFileName( m_ArgsInfo.vf_arg[i]);
+       if (m_Verbose) std::cout<<"Reading vector field "<< i <<"..."<<std::endl;
+       reader->Update();
+       dvfs.push_back( reader->GetOutput() );
+      }
+    
+    ProcessVectorFields<Dimension, Components>(dvfs, m_ArgsInfo.vf_arg);
+  }
+
+  //-----------------------------
+  // Process DVF
+  //-----------------------------
+  template<unsigned int Dimension, unsigned int Components >
+  void 
+  CalculateTREGenericFilter::ProcessVectorFields(std::vector<typename itk::Image<itk::Vector<float, Components>, Dimension>::Pointer > dvfs, char** filenames )
+  {
+    
+    std::vector<std::string> new_filenames;
+    for (unsigned int i=0;i<m_ArgsInfo.vf_given;i++)
+      new_filenames.push_back(filenames[i]);
+    UpdateWithDim<Dimension>(dvfs, new_filenames); 
+  }
+
+    
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions
+  //-------------------------------------------------------------------
+  template<unsigned int Dimension>
+  void 
+  CalculateTREGenericFilter::UpdateWithDim(std::vector<typename itk::Image<itk::Vector<float, Dimension>, Dimension>::Pointer > dvfs,  std::vector<std::string> filenames)
+  {
+    if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D..."<<std::endl;
+
+    //-----------------------------
+    // Typedefs
+    //-----------------------------
+    typedef double ValueType;
+    typedef std::vector<ValueType> MeasureListType;
+
+    typedef itk::Point<double, Dimension> PointType;
+    typedef clitk::List<PointType> PointListType;
+    typedef clitk::Lists<PointType> PointListsType;
+
+    typedef itk::Vector<double, Dimension> VectorType;
+    typedef clitk::List<VectorType> VectorListType;
+    typedef clitk::Lists<VectorType> VectorListsType;
+    
+    typedef itk::Vector<float, Dimension> DeformationVectorType;
+    typedef itk::Image<DeformationVectorType, Dimension> DeformationFieldType;
+
+    //-----------------------------
+    // Number of inputs
+    //-----------------------------
+    unsigned int numberOfFields=filenames.size();
+    unsigned int numberOfLists=m_ArgsInfo.input_given;
+    if ( (numberOfLists!=numberOfFields)  &&  (numberOfLists!=1) )
+      {
+       std::cerr<<"Error: Number of lists (="<<numberOfLists<<") different from number of DVF's (="<<numberOfFields<<") !"<<std::endl;
+       return;
+      }
+    else if (numberOfLists==1) 
+      {
+       if (m_Verbose) std::cout<<numberOfFields<<" DVFs and 1 point list given..."<<std::endl;
+      }
+    else 
+      {
+       if (m_Verbose) std::cout<<numberOfLists<<" point lists and DVFs given..."<<std::endl;
+      }
+
+    
+    //-----------------------------
+    // Input point lists
+    //-----------------------------   
+    PointListsType pointLists;
+    unsigned int numberOfPoints=0;
+    for (unsigned int i=0; i<numberOfFields; i++)
+      {
+       // Read the lists
+       if (numberOfLists==1) 
+         pointLists.push_back(PointListType(m_ArgsInfo.input_arg[0], m_Verbose) );
+       else
+         pointLists.push_back(PointListType(m_ArgsInfo.input_arg[i], m_Verbose) );
+
+
+       // Verify the number of points
+       if (i==0) numberOfPoints=pointLists[i].size();
+       else 
+         {
+           if  (numberOfPoints!=pointLists[i].size())
+             {
+               std::cerr<<"Size of first list ("<<numberOfPoints
+                        <<") is different from size of list "<<i
+                        <<" ("<<pointLists[i].size()<<")..."<<std::endl;
+               return;
+             }
+         }
+      }    
+    
+
+    PointListType referencePointList;
+    if (m_Verbose) std::cout<<"Reference point list:"<<std::endl;
+    referencePointList=PointListType(m_ArgsInfo.ref_arg, m_Verbose);
+    if  (numberOfPoints!=referencePointList.size())
+      {
+       std::cerr<<"Size of the first list ("<<numberOfPoints
+                <<") is different from size of the reference list ("
+                << referencePointList.size() <<")..."<<std::endl;
+       return;
+      }
+
+    
+    //-----------------------------
+    // Interpolator
+    //-----------------------------
+    typedef clitk::GenericVectorInterpolator<args_info_clitkCalculateTRE,DeformationFieldType, double> GenericVectorInterpolatorType;
+    typename GenericVectorInterpolatorType::Pointer genericInterpolator=GenericVectorInterpolatorType::New();
+    genericInterpolator->SetArgsInfo(m_ArgsInfo);
+    typedef itk::VectorInterpolateImageFunction<DeformationFieldType, double> InterpolatorType; 
+    typename InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
+    
+
+    //=====================================================================================
+    // Original distance between points
+    //=====================================================================================
+    VectorListsType originalDistanceLists(numberOfFields);
+    
+    //-----------------------------
+    // Calculate original distances
+    //-----------------------------
+    PointType referencePoint;
+    VectorType distance;
+    for (unsigned int phaseIndex=0; phaseIndex<numberOfFields; phaseIndex++)
+      {
+       for (unsigned int pointIndex=0; pointIndex<numberOfPoints; pointIndex++)   
+         {
+           referencePoint=referencePointList[pointIndex];
+           distance=pointLists[phaseIndex][pointIndex]-referencePoint;
+           originalDistanceLists[phaseIndex].push_back(distance);
+         }
+      }
+       
+    //-----------------------------
+    // Statistics Original
+    //-----------------------------
+    typedef DeformationListStatisticsFilter<VectorType> StatisticsFilterType;
+    typename StatisticsFilterType::Pointer statisticsFilter=StatisticsFilterType::New();
+    
+    // Statistics  (magnitude)
+    MeasureListType oMeanList, oStdList, oMaxList;
+    ValueType oMean, oStd, oMax;
+    statisticsFilter->GetStatistics(originalDistanceLists, oMean, oStd, oMax, oMeanList, oStdList, oMaxList);
+
+    // Statistics  (per component)
+    VectorListType oMeanXYZList, oStdXYZList,oMaxXYZList;
+    VectorType oMeanXYZ, oStdXYZ, oMaxXYZ;
+    statisticsFilter->GetStatistics(originalDistanceLists, oMeanXYZ, oStdXYZ, oMaxXYZ, oMeanXYZList, oStdXYZList, oMaxXYZList);
+
+
+    //-----------------------------
+    // Output
+    //-----------------------------
+    std::vector<std::string> labels;
+    labels.push_back("MeanX\tSDX");
+    labels.push_back("MeanY\tSDY");
+    labels.push_back("MeanZ\tSDZ");
+    labels.push_back("MeanT\tSDT");
+    labels.push_back("MaxX");
+    labels.push_back("MaxY");
+    labels.push_back("MaxZ");
+    labels.push_back("MaxT");
+
+
+    // Output to screen
+    if(m_Verbose)
+      {
+       
+       // Numbers of DVF
+       std::cout<<"# Number\tDVF"<<std::endl;
+       for (unsigned int phaseIndex=0; phaseIndex<numberOfFields; phaseIndex++)
+         std::cout<<phaseIndex<<"\t"<<filenames[phaseIndex]<<std::endl;
+
+       
+       std::cout<<std::endl;
+       std::cout<<"=================================================="<<std::endl;
+       std::cout<<"||       Original distance between points       ||"<<std::endl;
+       std::cout<<"=================================================="<<std::endl;
+       std::cout<<std::endl;
+
+       std::cout<<std::setprecision(3);
+
+       
+
+       // Labels of the columns
+       std::cout<<"#DVF\tMean\tSD\t"<<labels[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)     std::cout<<"\t"<< labels[dim];
+       std::cout<<"\tMax \t"<<labels[4];
+       for(unsigned int dim=1;dim<Dimension;dim++)     std::cout<<"\t"<< labels[dim+4];
+       std::cout<<std::endl;
+       for (unsigned int phaseIndex=0; phaseIndex<numberOfFields; phaseIndex++)
+         {
+           std::cout<<phaseIndex;
+           std::cout<<"\t"<<oMeanList[phaseIndex]<<"\t"<<oStdList[phaseIndex];
+           std::cout<<"\t"<<oMeanXYZList[phaseIndex][0]<<"\t"<<oStdXYZList[phaseIndex][0];
+           for(unsigned int dim=1;dim<Dimension;dim++)
+             std::cout<<"\t"<<oMeanXYZList[phaseIndex][dim]<<"\t"<<oStdXYZList[phaseIndex][dim];
+           std::cout<<"\t"<<oMaxList[phaseIndex];
+           std::cout<<"\t"<<oMaxXYZList[phaseIndex][0];
+           for(unsigned int dim=1;dim<Dimension;dim++)
+             std::cout<<"\t"<<oMaxXYZList[phaseIndex][dim];
+           std::cout<<std::endl;
+         }
+
+       // General
+       std::cout<<std::endl;
+       std::cout<<"@";
+       std::cout<<"\t"<<oMean<<"\t"<<oStd;
+       std::cout<<"\t"<<oMeanXYZ[0]<<"\t"<<oStdXYZ[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)
+         std::cout<<"\t"<<oMeanXYZ[dim]<<"\t"<<oStdXYZ[dim];
+       std::cout<<"\t"<<oMax;
+       std::cout<<"\t"<<oMaxXYZ[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)
+         std::cout<<"\t"<<oMaxXYZ[dim];
+       std::cout<<std::endl;
+      }
+
+    // Output to file
+    if( m_ArgsInfo.general_given)
+      {
+       // Add to the file
+       std::ofstream general(m_ArgsInfo.general_arg);
+
+
+       // Numbers of DVF
+       for (unsigned int phaseIndex=0; phaseIndex<numberOfFields; phaseIndex++)
+         general<<phaseIndex<<"\t"<< filenames[phaseIndex]<<std::endl;
+         
+       general<<std::endl;
+       general<<"=================================================="<<std::endl;
+       general<<"||       Original distance between points       ||"<<std::endl;
+       general<<"=================================================="<<std::endl;
+       general<<std::endl;
+
+       general<<std::setprecision(3);
+
+       // Labels of the columns
+       general<<"#DVF\tMean\tSD\t"<<labels[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)     general<<"\t"<< labels[dim];
+       general<<"\tMax \t"<<labels[4];
+       for(unsigned int dim=1;dim<Dimension;dim++)     general<<"\t"<< labels[dim+4];
+       general<<std::endl;
+       for (unsigned int phaseIndex=0; phaseIndex<numberOfFields; phaseIndex++)
+         {
+           general<<phaseIndex;
+           general<<"\t"<<oMeanList[phaseIndex]<<"\t"<<oStdList[phaseIndex];
+           general<<"\t"<<oMeanXYZList[phaseIndex][0]<<"\t"<<oStdXYZList[phaseIndex][0];
+           for(unsigned int dim=1;dim<Dimension;dim++)
+             general<<"\t"<<oMeanXYZList[phaseIndex][dim]<<"\t"<<oStdXYZList[phaseIndex][dim];
+           general<<"\t"<<oMaxList[phaseIndex];
+           general<<"\t"<<oMaxXYZList[phaseIndex][0];
+           for(unsigned int dim=1;dim<Dimension;dim++)
+             general<<"\t"<<oMaxXYZList[phaseIndex][dim];
+           general<<std::endl;
+         }
+
+       // General
+       general<<std::endl;
+       general<<"@";
+       general<<"\t"<<oMean<<"\t"<<oStd;
+       general<<"\t"<<oMeanXYZ[0]<<"\t"<<oStdXYZ[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)
+         general<<"\t"<<oMeanXYZ[dim]<<"\t"<<oStdXYZ[dim];
+       general<<"\t"<<oMax;
+       general<<"\t"<<oMaxXYZ[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)
+         general<<"\t"<<oMaxXYZ[dim];
+       general<<std::endl;
+       general.close();
+      }
+
+
+    //=====================================================================================
+    // Distance between points after warp
+    //=====================================================================================
+    PointListsType warpedPointLists(numberOfFields);
+    VectorListsType treLists(numberOfFields), displacementLists(numberOfFields);
+    
+    //-----------------------------
+    // Calculate residual distances
+    //-----------------------------
+    VectorType displacement, tre;
+    PointType  warpedPoint;
+
+    for (unsigned int phaseIndex=0; phaseIndex<numberOfFields; phaseIndex++)
+      { 
+       interpolator->SetInputImage( dvfs[phaseIndex]);
+       for (unsigned int pointIndex=0; pointIndex<numberOfPoints; pointIndex++)   
+         {
+           // Reference
+           referencePoint=referencePointList[pointIndex];
+
+           // Inside?
+           if ( interpolator->IsInsideBuffer(referencePoint) )
+             displacement=interpolator->Evaluate(referencePoint); 
+           else
+             displacement.Fill(0.0); 
+
+           // Warp
+           warpedPoint=referencePoint+displacement;
+           displacementLists[phaseIndex].push_back(displacement);
+           warpedPointLists[phaseIndex].push_back(warpedPoint);
+           tre=pointLists[phaseIndex][pointIndex]-warpedPoint;
+           treLists[phaseIndex].push_back(tre);
+         }
+      }
+
+
+    //-----------------------------
+    // Statistics displacements
+    //-----------------------------
+    
+    // Statistics  (magnitude)
+    MeasureListType dmeanList, dstdList, dmaxList;
+    ValueType dmean, dstd, dmax;
+    statisticsFilter->GetStatistics(displacementLists, dmean, dstd, dmax, dmeanList, dstdList, dmaxList);
+
+    // Statistics  (per component)
+    VectorListType dmeanXYZList, dstdXYZList,dmaxXYZList;
+    VectorType dmeanXYZ, dstdXYZ, dmaxXYZ;
+    statisticsFilter->GetStatistics(displacementLists, dmeanXYZ, dstdXYZ, dmaxXYZ,dmeanXYZList, dstdXYZList, dmaxXYZList);
+
+
+    //-----------------------------
+    // Statistics TRE
+    //-----------------------------
+    
+    // Statistics  (magnitude)
+    MeasureListType meanList, stdList, maxList;
+    ValueType mean, std, max;
+    statisticsFilter->GetStatistics(treLists, mean, std, max, meanList, stdList, maxList);
+
+    // Statistics  (per component)
+    VectorListType meanXYZList, stdXYZList,maxXYZList;
+    VectorType meanXYZ, stdXYZ, maxXYZ;
+    statisticsFilter->GetStatistics(treLists, meanXYZ, stdXYZ, maxXYZ, meanXYZList, stdXYZList, maxXYZList);
+
+
+    // Output to screen
+    if(m_Verbose)
+      {
+
+       std::cout<<std::endl;
+       std::cout<<"=================================================="<<std::endl;
+       std::cout<<"||       Residual distance between points       ||"<<std::endl;
+       std::cout<<"=================================================="<<std::endl;
+       std::cout<<std::endl;
+
+       std::cout<<std::setprecision(3);
+
+       // Labels of the columns
+       std::cout<<"#DVF\tMean\tSD\t"<<labels[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)     std::cout<<"\t"<< labels[dim];
+       std::cout<<"\tMax \t"<<labels[4];
+       for(unsigned int dim=1;dim<Dimension;dim++)     std::cout<<"\t"<< labels[dim+4];
+       std::cout<<std::endl;
+       for (unsigned int phaseIndex=0; phaseIndex<numberOfFields; phaseIndex++)
+         {
+           std::cout<<phaseIndex;
+           std::cout<<"\t"<<meanList[phaseIndex]<<"\t"<<stdList[phaseIndex];
+           std::cout<<"\t"<<meanXYZList[phaseIndex][0]<<"\t"<<stdXYZList[phaseIndex][0];
+           for(unsigned int dim=1;dim<Dimension;dim++)
+             std::cout<<"\t"<<meanXYZList[phaseIndex][dim]<<"\t"<<stdXYZList[phaseIndex][dim];
+           std::cout<<"\t"<<maxList[phaseIndex];
+           std::cout<<"\t"<<maxXYZList[phaseIndex][0];
+           for(unsigned int dim=1;dim<Dimension;dim++)
+             std::cout<<"\t"<<maxXYZList[phaseIndex][dim];
+           std::cout<<std::endl;
+         }
+
+       // General
+       std::cout<<std::endl;
+       std::cout<<"@";
+       std::cout<<"\t"<<mean<<"\t"<<std;
+       std::cout<<"\t"<<meanXYZ[0]<<"\t"<<stdXYZ[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)
+         std::cout<<"\t"<<meanXYZ[dim]<<"\t"<<stdXYZ[dim];
+       std::cout<<"\t"<<max;
+       std::cout<<"\t"<<maxXYZ[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)
+         std::cout<<"\t"<<maxXYZ[dim];
+       std::cout<<std::endl;
+      }
+
+    // Output to file
+    if( m_ArgsInfo.general_given)
+      {
+       // Add to the file
+       std::ofstream general(m_ArgsInfo.general_arg, ios_base::app);
+
+       general<<std::endl;
+       general<<"=================================================="<<std::endl;
+       general<<"||       Residual distance between points       ||"<<std::endl;
+       general<<"=================================================="<<std::endl;
+       general<<std::endl;
+
+       general<<std::setprecision(3);
+
+       // Labels of the columns
+       general<<"#DVF\tMean\tSD\t"<<labels[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)     general<<"\t"<< labels[dim];
+       general<<"\tMax \t"<<labels[4];
+       for(unsigned int dim=1;dim<Dimension;dim++)     general<<"\t"<< labels[dim+4];
+       general<<std::endl;
+       for (unsigned int phaseIndex=0; phaseIndex<numberOfFields; phaseIndex++)
+         {
+           general<<phaseIndex;
+           general<<"\t"<<meanList[phaseIndex]<<"\t"<<stdList[phaseIndex];
+           general<<"\t"<<meanXYZList[phaseIndex][0]<<"\t"<<stdXYZList[phaseIndex][0];
+           for(unsigned int dim=1;dim<Dimension;dim++)
+             general<<"\t"<<meanXYZList[phaseIndex][dim]<<"\t"<<stdXYZList[phaseIndex][dim];
+           general<<"\t"<<maxList[phaseIndex];
+           general<<"\t"<<maxXYZList[phaseIndex][0];
+           for(unsigned int dim=1;dim<Dimension;dim++)
+             general<<"\t"<<maxXYZList[phaseIndex][dim];
+           general<<std::endl;
+         }
+
+       // General
+       general<<std::endl;
+       general<<"@";
+       general<<"\t"<<mean<<"\t"<<std;
+       general<<"\t"<<meanXYZ[0]<<"\t"<<stdXYZ[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)
+         general<<"\t"<<meanXYZ[dim]<<"\t"<<stdXYZ[dim];
+       general<<"\t"<<max;
+       general<<"\t"<<maxXYZ[0];
+       for(unsigned int dim=1;dim<Dimension;dim++)
+         general<<"\t"<<maxXYZ[dim];
+       general<<std::endl;
+       general.close();
+      }
+
+    // Output original points
+    if( m_ArgsInfo.original_given)
+      {
+
+       std::vector<std::string> filenames;
+       for (unsigned int i=0;i<numberOfFields;i++)
+         {
+           std::ostringstream number_ostr;
+           number_ostr << i;
+           std::string number_str =  number_ostr.str();
+           filenames.push_back(m_ArgsInfo.original_arg+number_str);
+         }
+       originalDistanceLists.Write(filenames, m_Verbose );
+      }
+
+
+    // Output original magnitude points
+    if( m_ArgsInfo.originalMag_given)
+      {
+       clitk::Lists<itk::FixedArray<double,1> > originalDistanceListsMag=originalDistanceLists.Norm();
+       std::vector<std::string> filenames;
+       for (unsigned int i=0;i<numberOfFields;i++)
+         {
+           std::ostringstream number_ostr;
+           number_ostr << i;
+           std::string number_str =  number_ostr.str();
+           filenames.push_back(m_ArgsInfo.originalMag_arg+number_str);
+         }
+       originalDistanceListsMag.Write(filenames, m_Verbose );
+      }
+
+    // Output displacement
+    if( m_ArgsInfo.displacement_given)
+      {
+
+       std::vector<std::string> filenames;
+       for (unsigned int i=0;i<numberOfFields;i++)
+         {
+           std::ostringstream number_ostr;
+           number_ostr << i;
+           std::string number_str =  number_ostr.str();
+           filenames.push_back(m_ArgsInfo.displacement_arg+number_str);
+         }
+       displacementLists.Write(filenames, m_Verbose );
+      }
+
+
+    // Output displacement magnitude 
+    if( m_ArgsInfo.displacementMag_given)
+      {
+       clitk::Lists<itk::FixedArray<double,1> > displacementListsMag=displacementLists.Norm();
+       std::vector<std::string> filenames;
+       for (unsigned int i=0;i<numberOfFields;i++)
+         {
+           std::ostringstream number_ostr;
+           number_ostr << i;
+           std::string number_str =  number_ostr.str();
+           filenames.push_back(m_ArgsInfo.displacementMag_arg+number_str);
+         }
+       displacementListsMag.Write(filenames, m_Verbose );
+      }
+
+    // Output warped points
+    if( m_ArgsInfo.warp_given)
+      {
+
+       std::vector<std::string> filenames;
+       for (unsigned int i=0;i<m_ArgsInfo.warp_given;i++)
+         {
+           std::ostringstream number_ostr;
+           number_ostr << i;
+           std::string number_str =  number_ostr.str();
+           filenames.push_back(m_ArgsInfo.warp_arg+number_str);
+         }
+       warpedPointLists.Write(filenames, m_Verbose );
+      }
+
+    // Output tre 
+    if( m_ArgsInfo.tre_given)
+      {
+
+       std::vector<std::string> filenames;
+       for (unsigned int i=0;i<numberOfFields;i++)
+         {
+           std::ostringstream number_ostr;
+           number_ostr << i;
+           std::string number_str =  number_ostr.str();
+           filenames.push_back(m_ArgsInfo.tre_arg+number_str);
+         }
+       treLists.Write(filenames, m_Verbose );
+      }
+
+    // Output tre mag
+    if( m_ArgsInfo.treMag_given)
+      {
+       clitk::Lists<itk::FixedArray<double,1> > treMagLists=treLists.Norm();
+
+       std::vector<std::string> filenames;
+       for (unsigned int i=0;i<numberOfFields;i++)
+         {
+           std::ostringstream number_ostr;
+           number_ostr << i;
+           std::string number_str =  number_ostr.str();
+           filenames.push_back(m_ArgsInfo.treMag_arg+number_str);
+         }
+       treMagLists.Write(filenames, m_Verbose );
+      }
+       
+  }
+
+
+}//end clitk
+#endif //#define clitkCalculateTREGenericFilter_txx
diff --git a/registration/clitkConvertBSplineDeformableTransformToVF.cxx b/registration/clitkConvertBSplineDeformableTransformToVF.cxx
new file mode 100755 (executable)
index 0000000..7f7c739
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkConvertBSplineDeformableTransformToVF.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkConvertBSplineDeformableTransformToVF_ggo.h"
+#include "clitkIO.h"
+#include "clitkConvertBSplineDeformableTransformToVFGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkConvertBSplineDeformableTransformToVF, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::ConvertBSplineDeformableTransformToVFGenericFilter::Pointer genericFilter=clitk::ConvertBSplineDeformableTransformToVFGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkConvertBSplineDeformableTransformToVF.ggo b/registration/clitkConvertBSplineDeformableTransformToVF.ggo
new file mode 100755 (executable)
index 0000000..1ee3f8f
--- /dev/null
@@ -0,0 +1,25 @@
+#File clitkConvertBSplineDeformableTransformToVF.ggo
+Package "clitkConvertBSplineDeformableTransformToVF"
+version "1.0"
+purpose "Convert a BSpline transform to a DVF with given properties"
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+
+section "IO"
+option "input"         i       "Input coefficient image filename"                string        yes
+option "output"        o       "Output image filename"           string        yes
+
+
+section "Output Image Properties"
+option "like"                  -       "Make output like this image"                   string          no              
+option "origin"                        -       "Origin for the output image"                   double          multiple no     default="0.0"
+option "size"                  -       "Size for the output image"                     int             multiple no     default="100"       
+option "spacing"               -       "Spacing for the output image"                  double          multiple no     default="1.0"       
+
+
+section "Transform"
+option "order"         -       "Spline order"                  int             multiple        no 
+option "mask"          -       "Mask image filename"           string          no 
+option "shape"         -       "Transform shape: 0=egg, 1=diamond"             int             no              default="0"
diff --git a/registration/clitkConvertBSplineDeformableTransformToVFGenericFilter.cxx b/registration/clitkConvertBSplineDeformableTransformToVFGenericFilter.cxx
new file mode 100755 (executable)
index 0000000..0d3929a
--- /dev/null
@@ -0,0 +1,417 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkConvertBSplineDeformableTransformToVFGenericFilter_cxx
+#define clitkConvertBSplineDeformableTransformToVFGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkConvertBSplineDeformableTransformToVFGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkConvertBSplineDeformableTransformToVFGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  ConvertBSplineDeformableTransformToVFGenericFilter::ConvertBSplineDeformableTransformToVFGenericFilter()
+  {
+    m_Verbose=false;
+    m_InputFileName="";
+  }
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions
+  //-------------------------------------------------------------------
+  template<>
+  void 
+  ConvertBSplineDeformableTransformToVFGenericFilter::UpdateWithDim<3>(std::string PixelType, int Components)
+  {
+    // Components
+    if (Components !=3)
+      {
+       std::cerr<<"Number of components is "<<Components<<"! Only 3 components is supported."<<std::endl;
+       return;
+      }
+    if (PixelType != "double")
+      {
+       std::cerr<<"PixelType is  "<<PixelType<<"! Only double coefficient images are supported."<<std::endl;
+       std::cerr<<"Reading image as double..."<<std::endl;
+      }
+  
+    // ImageTypes
+    const unsigned int Dimension=3;
+    typedef itk::Vector<double, Dimension> InputPixelType;
+    typedef itk::Vector<float, Dimension> OutputPixelType;
+    typedef itk::Image<InputPixelType, Dimension> InputImageType;
+    typedef itk::Image<OutputPixelType, Dimension> OutputImageType;
+  
+    // Read the input
+    typedef itk::ImageFileReader<InputImageType> InputReaderType;
+    InputReaderType::Pointer reader = InputReaderType::New();
+    reader->SetFileName( m_InputFileName);
+    reader->Update();
+    InputImageType::Pointer input= reader->GetOutput();
+
+
+    // -----------------------------------------------
+    // Filter
+    // -----------------------------------------------
+    typedef itk::TransformToDeformationFieldSource<OutputImageType, double> ConvertorType;
+    ConvertorType::Pointer filter= ConvertorType::New();
+
+    //Output image info
+    if (m_ArgsInfo.like_given)
+      {
+       typedef itk::ImageFileReader<OutputImageType> ReaderType;
+       ReaderType::Pointer reader2=ReaderType::New();
+       reader2->SetFileName(m_ArgsInfo.like_arg);
+       reader2->Update();
+
+       OutputImageType::Pointer image=reader2->GetOutput();
+       filter->SetOutputParametersFromImage(image);
+      }
+    else
+      {
+       unsigned int i=0;
+       if(m_ArgsInfo.origin_given)
+         {
+           OutputImageType::PointType origin;
+           for(i=0;i<Dimension;i++)
+             origin[i]=m_ArgsInfo.origin_arg[i];
+           filter->SetOutputOrigin(origin);
+         }
+       if (m_ArgsInfo.spacing_given)
+         {
+           OutputImageType::SpacingType spacing;
+           for(i=0;i<Dimension;i++)
+             spacing[i]=m_ArgsInfo.spacing_arg[i];
+           filter->SetOutputSpacing(spacing);
+         }
+       if (m_ArgsInfo.spacing_given)
+         {
+           OutputImageType::SizeType size;
+           for(i=0;i<Dimension;i++)
+             size[i]=m_ArgsInfo.size_arg[i];
+           filter->SetOutputSize(size);
+         }
+      }
+
+    if (m_Verbose)
+      {
+       std::cout<< "Setting output origin to "<<filter->GetOutputOrigin()<<"..."<<std::endl;
+       std::cout<< "Setting output spacing to "<<filter->GetOutputSpacing()<<"..."<<std::endl;
+       std::cout<< "Setting output size to "<<filter->GetOutputSize()<<"..."<<std::endl;
+      }
+
+
+    // -----------------------------------------------
+    // Transform
+    // -----------------------------------------------
+    typedef clitk::BSplineDeformableTransform< double, Dimension, Dimension> TransformType; 
+    TransformType::Pointer transform=TransformType::New();
+
+    // Spline orders:  Default is cubic splines
+    InputImageType::RegionType::SizeType splineOrders ;
+    splineOrders.Fill(3);
+    if (m_ArgsInfo.order_given)
+      for(unsigned int i=0; i<Dimension;i++) 
+       splineOrders[i]=m_ArgsInfo.order_arg[i];
+    if (m_Verbose) std::cout<<"Setting the spline orders  to "<<splineOrders<<"..."<<std::endl;
+
+    // Mask
+    typedef itk::ImageMaskSpatialObject<  Dimension >   MaskType;
+    MaskType::Pointer  spatialObjectMask=NULL;
+    if (m_ArgsInfo.mask_given)
+      {
+       typedef itk::Image< unsigned char, Dimension >   ImageMaskType;
+       typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
+       MaskReaderType::Pointer  maskReader = MaskReaderType::New();
+       maskReader->SetFileName(m_ArgsInfo.mask_arg);
+       
+       try 
+         { 
+           maskReader->Update(); 
+         } 
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught while reading mask !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         } 
+       if (m_Verbose)std::cout <<"Mask was read..." <<std::endl;
+       
+       // Set the image to the spatialObject
+       spatialObjectMask = MaskType::New();
+       spatialObjectMask->SetImage( maskReader->GetOutput() );
+      }
+
+
+    // Samplingfactors
+    InputImageType::SizeType samplingFactors; 
+    for (unsigned int i=0; i< Dimension; i++)
+      {   
+       samplingFactors[i]= (int) ( input->GetSpacing()[i]/ filter->GetOutputSpacing()[i]);
+       if (m_Verbose) std::cout<<"Setting sampling factor "<<i<<" to "<<samplingFactors[i]<<"..."<<std::endl;
+      }
+
+
+    // Set
+    transform->SetSplineOrders(splineOrders);
+    transform->SetMask(spatialObjectMask);
+    transform->SetLUTSamplingFactors(samplingFactors);
+    transform->SetCoefficientImage(input);
+    filter->SetTransform(transform);
+
+
+    // -----------------------------------------------
+    // Update
+    // -----------------------------------------------
+    if (m_Verbose)std::cout<< "Converting the BSpline transform..."<<std::endl;
+    try
+      {
+       filter->Update();
+      }
+    catch (itk::ExceptionObject)
+      {
+       std::cerr<<"Error: Exception thrown during execution convertion filter!"<<std::endl;
+      }
+
+    OutputImageType::Pointer output=filter->GetOutput();
+
+
+    // -----------------------------------------------
+    // Output
+    // -----------------------------------------------
+    typedef itk::ImageFileWriter<OutputImageType> WriterType;
+    WriterType::Pointer writer = WriterType::New();
+    writer->SetFileName(m_ArgsInfo.output_arg);
+    writer->SetInput(output);
+    writer->Update();
+
+  }
+
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions
+  //-------------------------------------------------------------------
+  template<>
+  void 
+  ConvertBSplineDeformableTransformToVFGenericFilter::UpdateWithDim<4>(std::string PixelType, int Components)
+  {
+    // Components
+    if (Components !=3)
+      {
+       std::cerr<<"Number of components is "<<Components<<"! Only 3 components is supported."<<std::endl;
+       return;
+      }
+    if (PixelType != "double")
+      {
+       std::cerr<<"PixelType is  "<<PixelType<<"! Only double coefficient images are supported."<<std::endl;
+       std::cerr<<"Reading image as double..."<<std::endl;
+      }
+  
+    // ImageTypes
+    const unsigned int Dimension=4;
+    const unsigned int SpaceDimension=3;
+    typedef itk::Vector<double, SpaceDimension> InputPixelType;
+    typedef itk::Vector<float, SpaceDimension> OutputPixelType;
+    typedef itk::Image<InputPixelType, Dimension> InputImageType;
+    typedef itk::Image<OutputPixelType, Dimension> OutputImageType;
+  
+    // Read the input
+    typedef itk::ImageFileReader<InputImageType> InputReaderType;
+    InputReaderType::Pointer reader = InputReaderType::New();
+    reader->SetFileName( m_InputFileName);
+    reader->Update();
+    InputImageType::Pointer input= reader->GetOutput();
+
+
+    // -----------------------------------------------
+    // Filter
+    // -----------------------------------------------
+    typedef clitk::TransformToDeformationFieldSource<OutputImageType, double> ConvertorType;
+    ConvertorType::Pointer filter= ConvertorType::New();
+
+    //Output image info
+    if (m_ArgsInfo.like_given)
+      {
+       typedef itk::ImageFileReader<OutputImageType> ReaderType;
+       ReaderType::Pointer reader2=ReaderType::New();
+       reader2->SetFileName(m_ArgsInfo.like_arg);
+       reader2->Update();
+
+       OutputImageType::Pointer image=reader2->GetOutput();
+       filter->SetOutputParametersFromImage(image);
+      }
+    else
+      {
+       unsigned int i=0;
+       if(m_ArgsInfo.origin_given)
+         {
+           OutputImageType::PointType origin;
+           for(i=0;i<Dimension;i++)
+             origin[i]=m_ArgsInfo.origin_arg[i];
+           filter->SetOutputOrigin(origin);
+         }
+       if (m_ArgsInfo.spacing_given)
+         {
+           OutputImageType::SpacingType spacing;
+           for(i=0;i<Dimension;i++)
+             spacing[i]=m_ArgsInfo.spacing_arg[i];
+           filter->SetOutputSpacing(spacing);
+         }
+       if (m_ArgsInfo.spacing_given)
+         {
+           OutputImageType::SizeType size;
+           for(i=0;i<Dimension;i++)
+             size[i]=m_ArgsInfo.size_arg[i];
+           filter->SetOutputSize(size);
+         }
+      }
+    //Output image info
+    if (m_Verbose)
+      {
+       std::cout<< "Setting output origin to "<<filter->GetOutputOrigin()<<"..."<<std::endl;
+       std::cout<< "Setting output spacing to "<<filter->GetOutputSpacing()<<"..."<<std::endl;
+       std::cout<< "Setting output size to "<<filter->GetOutputSize()<<"..."<<std::endl;
+      }
+
+
+    // -----------------------------------------------
+    // Transform
+    // -----------------------------------------------
+    typedef clitk::ShapedBLUTSpatioTemporalDeformableTransform< double, Dimension, Dimension > TransformType; 
+    TransformType::Pointer transform=TransformType::New();
+    transform->SetTransformShape(m_ArgsInfo.shape_arg);
+
+    // Spline orders:  Default is cubic splines
+    InputImageType::RegionType::SizeType splineOrders ;
+    splineOrders.Fill(3);
+    if (m_ArgsInfo.order_given)
+      for(unsigned int i=0; i<Dimension;i++) 
+       splineOrders[i]=m_ArgsInfo.order_arg[i];
+    if (m_Verbose) std::cout<<"Setting the spline orders  to "<<splineOrders<<"..."<<std::endl;
+
+    // Mask
+    typedef itk::ImageMaskSpatialObject<  Dimension >   MaskType;
+    MaskType::Pointer  spatialObjectMask=NULL;
+    if (m_ArgsInfo.mask_given)
+      {
+       typedef itk::Image< unsigned char, Dimension >   ImageMaskType;
+       typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
+       MaskReaderType::Pointer  maskReader = MaskReaderType::New();
+       maskReader->SetFileName(m_ArgsInfo.mask_arg);
+       
+       try 
+         { 
+           maskReader->Update(); 
+         } 
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught while reading mask !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         } 
+       if (m_Verbose)std::cout <<"Mask was read..." <<std::endl;
+       
+       // Set the image to the spatialObject
+       spatialObjectMask = MaskType::New();
+       spatialObjectMask->SetImage( maskReader->GetOutput() );
+      }
+
+
+    // Samplingfactors
+    InputImageType::SizeType samplingFactors; 
+    for (unsigned int i=0; i< Dimension; i++)
+      {   
+       samplingFactors[i]= (int) ( input->GetSpacing()[i]/ filter->GetOutputSpacing()[i]);
+       if (m_Verbose) std::cout<<"Setting sampling factor "<<i<<" to "<<samplingFactors[i]<<"..."<<std::endl;
+      }
+    if( !(m_ArgsInfo.shape_arg%2) )samplingFactors[Dimension-1]=5;
+
+    // Set
+    transform->SetSplineOrders(splineOrders);
+    transform->SetMask(spatialObjectMask);
+    transform->SetLUTSamplingFactors(samplingFactors);
+    transform->SetCoefficientImage(input);
+    filter->SetTransform(transform);
+
+
+    // -----------------------------------------------
+    // Update
+    // -----------------------------------------------
+    if (m_Verbose)std::cout<< "Converting the BSpline transform..."<<std::endl;
+    try
+      {
+       filter->Update();
+      }
+    catch (itk::ExceptionObject)
+      {
+       std::cerr<<"Error: Exception thrown during execution convertion filter!"<<std::endl;
+      }
+
+    OutputImageType::Pointer output=filter->GetOutput();
+
+
+    // -----------------------------------------------
+    // Output
+    // -----------------------------------------------
+    typedef itk::ImageFileWriter<OutputImageType> WriterType;
+    WriterType::Pointer writer = WriterType::New();
+    writer->SetFileName(m_ArgsInfo.output_arg);
+    writer->SetInput(output);
+    writer->Update();
+
+  }
+
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void ConvertBSplineDeformableTransformToVFGenericFilter::Update()
+  {
+  
+    // Read the Dimension and PixelType
+    int Dimension, Components;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType, Components);
+
+    // Call UpdateWithDim
+    //if(Dimension==2) UpdateWithDim<2>(PixelType, Components);
+    if(Dimension==3) UpdateWithDim<3>(PixelType, Components);
+    else if (Dimension==4) UpdateWithDim<4>(PixelType, Components); 
+    else 
+      {
+       std::cout<<"Error, Only for 3 Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+} //end clitk
+
+#endif  //#define clitkConvertBSplineDeformableTransformToVFGenericFilter_cxx
diff --git a/registration/clitkConvertBSplineDeformableTransformToVFGenericFilter.h b/registration/clitkConvertBSplineDeformableTransformToVFGenericFilter.h
new file mode 100755 (executable)
index 0000000..318f0d3
--- /dev/null
@@ -0,0 +1,117 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkConvertBSplineDeformableTransformToVFGenericFilter_h
+#define clitkConvertBSplineDeformableTransformToVFGenericFilter_h
+
+/* =================================================
+ * @file   clitkConvertBSplineDeformableTransformToVFGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkImageCommon.h"
+#include "clitkConvertBSplineDeformableTransformToVF_ggo.h"
+#include "clitkBSplineDeformableTransform.h"
+#include "clitkShapedBLUTSpatioTemporalDeformableTransform.h"
+#include "clitkTransformToDeformationFieldSource.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkImageMaskSpatialObject.h"
+#include "itkTransformToDeformationFieldSource.h"
+
+
+namespace clitk 
+{
+
+  class ITK_EXPORT ConvertBSplineDeformableTransformToVFGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef ConvertBSplineDeformableTransformToVFGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( ConvertBSplineDeformableTransformToVFGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkConvertBSplineDeformableTransformToVF & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+      m_InputFileName=m_ArgsInfo.input_arg;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    ConvertBSplineDeformableTransformToVFGenericFilter();
+    ~ConvertBSplineDeformableTransformToVFGenericFilter() {};
+
+    
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <unsigned int Dimension>  void UpdateWithDim(std::string PixelType, int Components);
+    // template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkConvertBSplineDeformableTransformToVF m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_InputFileName;
+
+  };
+
+
+} // end namespace clitk
+
+
+#endif // #define clitkConvertBSplineDeformableTransformToVFGenericFilter_h
diff --git a/registration/clitkConvertPointList.cxx b/registration/clitkConvertPointList.cxx
new file mode 100755 (executable)
index 0000000..716de80
--- /dev/null
@@ -0,0 +1,81 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkConvertPointList.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkConvertPointList_ggo.h"
+#include "clitkIO.h"
+#include "clitkImageCommon.h"
+#include "clitkList.h"
+#include "clitkLists.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkConvertPointList, args_info);
+  CLITK_INIT;
+
+  // List
+  typedef itk::Point<double, 3> PointType;
+  typedef clitk::List<PointType> ListType;
+  typedef clitk::Lists<PointType> ListsType;
+  ListType refList;
+  ListsType targetLists;
+
+  // Image 
+  typedef itk::Image<signed short, 3> ImageType; 
+  ImageType::Pointer referenceImage=clitk::readImage<ImageType>(args_info.refIm_arg, args_info.verbose_flag);
+  
+  // Filenames
+  std::vector< std::string> fileNames;
+  for(unsigned int i=0; i< args_info.lists_given; i++)
+    {
+      fileNames.push_back(args_info.lists_arg[i]);
+      if (args_info.verbose_flag) std::cout<<"Adding input point list "<<fileNames[i]<<std::endl;
+    }
+
+  // Read and convert
+  targetLists.ReadAndConvertPointPairs(fileNames, refList, referenceImage, args_info.verbose_flag );
+
+  // Write  
+  if (args_info.ref_given)  refList.Write(args_info.ref_arg, args_info.verbose_flag); 
+  if (args_info.targets_given ==  args_info.lists_given) 
+    {
+      // output filenames
+      std::vector<std::string> oFileNames;
+      for(unsigned int i=0; i< args_info.targets_given; i++)
+       oFileNames.push_back(args_info.targets_arg[i]);
+      targetLists.Write(oFileNames, args_info.verbose_flag); 
+    }
+  
+  return EXIT_SUCCESS;
+
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkConvertPointList.ggo b/registration/clitkConvertPointList.ggo
new file mode 100755 (executable)
index 0000000..9c7ac9e
--- /dev/null
@@ -0,0 +1,15 @@
+#File clitkConvertPointList.ggo
+Package "clitkConvertPointList"
+version "1.0"
+purpose "Convert IX point pair lists (generated using the software described in Murphy2008,MICCAI) to a vv point pair lists"
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+section "I/O" 
+
+option "lists"         l       "Input IX lists filenames"                        string        yes     multiple
+option "refIm"         i       "Input reference image filename"                  string        yes
+option "ref"           r       "Output reference list filename"                  string        yes
+option "targets"       c       "Output target lists filenames"                   string        yes     multiple
+
diff --git a/registration/clitkDeformationFieldTransform.h b/registration/clitkDeformationFieldTransform.h
new file mode 100644 (file)
index 0000000..273376b
--- /dev/null
@@ -0,0 +1,86 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkDeformationFieldTransform_h
+#define __clitkDeformationFieldTransform_h
+#include "clitkList.h"
+#include "clitkLists.h"
+
+// itk
+#include "itkTransform.h"
+#include "itkVectorInterpolateImageFunction.h"
+#include "itkVectorLinearInterpolateImageFunction.h"
+
+namespace clitk
+{
+
+  template < class TScalarType=double, unsigned int InputDimension=4,unsigned int OutputDimension=4, unsigned int SpaceDimension=3 >        
+  class ITK_EXPORT DeformationFieldTransform : public itk::Transform< TScalarType, InputDimension, OutputDimension >
+  {
+  public:
+    /** Standard class typedefs. */
+    typedef DeformationFieldTransform                                      Self;
+    typedef itk::Transform< TScalarType, InputDimension, OutputDimension > Superclass;
+    typedef itk::SmartPointer<Self>                                 Pointer;
+    typedef itk::SmartPointer<const Self>                           ConstPointer;
+      
+    /** New macro for creation of through the object factory. */
+    itkNewMacro( Self );
+
+    /** Run-time type information (and related methods). */
+    itkTypeMacro( DeformationFieldTransform, Transform );
+
+    /** Standard coordinate point type for this class. */
+    typedef itk::Point<TScalarType, InputDimension> InputPointType;
+    typedef itk::Point<TScalarType, OutputDimension> OutputPointType;
+
+    // typedef 
+    typedef  itk::Point<double, SpaceDimension> SpacePointType;
+    typedef itk::Vector<double, SpaceDimension> DisplacementType;
+    typedef itk::Image<DisplacementType, InputDimension> DeformationFieldType; 
+    typedef itk::VectorInterpolateImageFunction<DeformationFieldType, double> InterpolatorType;
+    typedef itk::VectorLinearInterpolateImageFunction<DeformationFieldType, double> DefaultInterpolatorType;
+
+    // Members
+    void SetDeformationField (typename DeformationFieldType::Pointer p){m_DeformationField=p; m_Interpolator->SetInputImage(m_DeformationField);}
+    void SetInterpolator (typename InterpolatorType::Pointer i){ m_Interpolator=i; m_Interpolator->SetInputImage(m_DeformationField);}
+    OutputPointType TransformPoint(const InputPointType  &point ) const;
+   
+  protected:
+    DeformationFieldTransform();
+    ~DeformationFieldTransform(){;}
+
+  private:
+    DeformationFieldTransform(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+
+    typename DeformationFieldType::Pointer m_DeformationField;
+    typename InterpolatorType::Pointer m_Interpolator;
+
+
+  }; //class DeformationFieldTransform
+
+
+
+}  // namespace itk
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkDeformationFieldTransform.txx"
+#endif
+
+#endif /* __clitkDeformationFieldTransform_h */
diff --git a/registration/clitkDeformationFieldTransform.txx b/registration/clitkDeformationFieldTransform.txx
new file mode 100644 (file)
index 0000000..af003f4
--- /dev/null
@@ -0,0 +1,61 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkDeformationFieldTransform_txx
+#define __clitkDeformationFieldTransform_txx
+#include "clitkDeformationFieldTransform.h"
+
+
+namespace clitk
+{
+
+  // Constructor
+  template<class TScalarType, unsigned int InputDimension, unsigned int OutputDimension, unsigned int SpaceDimension>
+  DeformationFieldTransform<TScalarType, InputDimension, OutputDimension, SpaceDimension>
+  ::DeformationFieldTransform():Superclass(OutputDimension,1)
+  {
+     m_DeformationField=NULL;
+     m_Interpolator=DefaultInterpolatorType::New();
+  }
+    
+   // Transform a point
+  template<class TScalarType, unsigned int InputDimension,unsigned int OutputDimension, unsigned int SpaceDimension>
+  typename DeformationFieldTransform<TScalarType,  InputDimension, OutputDimension, SpaceDimension>::OutputPointType
+  DeformationFieldTransform<TScalarType, InputDimension, OutputDimension, SpaceDimension>::
+  TransformPoint(const InputPointType &inputPoint) const 
+  {
+    OutputPointType outputPoint;
+    outputPoint.Fill(0.);
+    for (unsigned int i=0;i<min(OutputDimension,InputDimension); i++) outputPoint[i]=inputPoint[i];
+    DisplacementType displacement;
+    if (m_Interpolator->IsInsideBuffer(inputPoint) )
+      {
+       displacement=m_Interpolator->Evaluate(inputPoint);
+       for (unsigned int i=0;i<min(OutputDimension,SpaceDimension); i++) 
+         outputPoint[i]+=displacement[i];
+       return outputPoint;
+      }
+
+    // No displacement
+    else return outputPoint;
+       
+  }
+
+  
+} // namespace clitk
+
+#endif
diff --git a/registration/clitkDeformationListStatisticsFilter.h b/registration/clitkDeformationListStatisticsFilter.h
new file mode 100644 (file)
index 0000000..4921bb0
--- /dev/null
@@ -0,0 +1,86 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkDeformationListStatistics_h
+#define __clitkDeformationListStatistics_h
+#include "clitkImageCommon.h"
+#include "clitkList.h"
+#include "clitkLists.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkImage.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionIteratorWithIndex.h"
+#include "itkNumericTraits.h"
+#include "itkSimpleFastMutexLock.h"
+#include "itkImageMaskSpatialObject.h"
+
+namespace clitk
+{
+  
+  template < class ListItemType >  
+  class ITK_EXPORT DeformationListStatisticsFilter : public itk::LightObject
+  
+  {
+  public:
+    typedef DeformationListStatisticsFilter     Self;
+    typedef itk::LightObject    Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+
+   
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);  
+    
+     //====================================
+    //Typedefs
+    typedef typename ListItemType::ValueType ValueType;
+    itkStaticConstMacro(Dimension, unsigned int, ListItemType::Dimension);
+    //typedef itk::Vector<ValueType, Dimension> ListItemType;
+    typedef std::vector<ValueType> ValueListType;
+    typedef clitk::List<ListItemType> ListType;
+    typedef clitk::Lists<ListItemType> ListsType;  
+
+    //====================================
+    //Get
+    void GetStatistics( const ListType &,  ValueType & mean, ValueType & sd, ValueType & max);
+    void GetStatistics( const ListsType &,  ValueListType & mean, ValueListType & sd, ValueListType & max);
+    void GetStatistics( const ListsType &,  ValueType & mean , ValueType & sd, ValueType & max, ValueListType & meanList, ValueListType & sdList, ValueListType & maxList);
+    void GetStatistics( const ListType &, ListItemType & meanXYZ, ListItemType & sdXYZ, ListItemType & maxXYZ );
+    void GetStatistics( const ListsType &, ListType & meanXYZ, ListType & sdXYZ, ListType & maxXYZ );
+    void GetStatistics( const ListsType &, ListItemType & mean , ListItemType & sd, ListItemType & max, ListType & meanXYZList, ListType & sdXYZList, ListType & maxXYZList );
+    
+  protected:
+    DeformationListStatisticsFilter(){};
+    ~DeformationListStatisticsFilter() {};
+    
+  private:
+
+  };
+
+
+
+
+
+} // end namespace clitk
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkDeformationListStatisticsFilter.txx"
+#endif
+
+#endif // #define __clitkDeformationListStatistics_h
diff --git a/registration/clitkDeformationListStatisticsFilter.txx b/registration/clitkDeformationListStatisticsFilter.txx
new file mode 100644 (file)
index 0000000..21911a0
--- /dev/null
@@ -0,0 +1,205 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkDeformationFieldStatisticsFilter_txx
+#define __clitkDeformationFieldStatisticsFilter_txx
+#include "clitkDeformationListStatisticsFilter.h"
+
+
+namespace clitk
+{
+
+  //------------------------------------------------------
+  //Magnitude
+  //------------------------------------------------------
+  template <class ListItemType> 
+  void 
+  DeformationListStatisticsFilter<ListItemType>::GetStatistics(const ListType& list, ValueType & mean,  ValueType & sd,  ValueType & max)
+  {
+    // Initialize
+    ValueType norm;
+    mean=0;
+    sd=0;
+    max=0;
+
+    // loop over the list of displacements
+    for (unsigned int i=0;i<list.size();i++)
+      {
+       norm=list[i].GetNorm();
+       mean+=norm;
+       sd+=norm*norm;
+       if (max<norm)max=norm;
+      }
+       
+    // Normalize
+    mean/=list.size();
+    sd/=list.size();
+    sd-=mean*mean;
+    sd=sqrt(sd);
+    
+  }
+
+
+
+  //------------------------------------------------------
+  // For multiple lists        
+  //------------------------------------------------------
+  template <class ListItemType> 
+  void 
+  DeformationListStatisticsFilter<ListItemType>::GetStatistics(const ListsType& list, ValueListType & mean,  ValueListType & sd,  ValueListType & max)
+  {
+
+    mean.resize(list.size());
+    sd.resize(list.size());
+    max.resize(list.size());
+
+    for (unsigned int i=0;i<list.size();i++)
+      {
+       // call function per list
+       GetStatistics(list[i], mean[i], sd[i], max[i]);
+      }
+  }
+
+
+  //------------------------------------------------------
+  // Magnitude AND General statistics for magnitude    
+  //------------------------------------------------------
+  template <class ListItemType> 
+  void 
+  DeformationListStatisticsFilter<ListItemType>::GetStatistics(const ListsType& list, ValueType&  mean, ValueType &sd, ValueType & max,  ValueListType & meanList, ValueListType & sdList,  ValueListType & maxList)
+  {
+    // Calculate statistics per list
+    GetStatistics(list, meanList, sdList, maxList);
+
+    // Initialize
+    mean=0;
+    sd=0;
+    max=0;
+    
+    // Loop
+    for (unsigned int i=0;i<list.size();i++)
+      {
+       mean+=meanList[i];
+       sd+=sdList[i]*sdList[i];
+       if(max<maxList[i])max=maxList[i];
+      }
+
+    // Normalize
+    mean/=list.size();
+    sd/=list.size();
+    sd=sqrt(sd);
+  }
+
+
+  //------------------------------------------------------
+  // Per component     
+  //------------------------------------------------------
+  template <class ListItemType> 
+  void 
+  DeformationListStatisticsFilter<ListItemType>::GetStatistics(const ListType& list, ListItemType & mean,  ListItemType & sd,  ListItemType & max)
+  {
+    // Initialize
+    ListItemType displacement;
+    mean.Fill(itk::NumericTraits<ValueType>::Zero);
+    sd.Fill(itk::NumericTraits<ValueType>::Zero);
+    max.Fill(itk::NumericTraits<ValueType>::Zero);
+
+    // Loop over the list of displacements
+    for (unsigned int i=0;i<list.size();i++)
+      {
+       displacement=list[i];
+       mean+=displacement;
+       for (unsigned int dim=0; dim<list[0].Size(); dim++)
+         {
+           sd[dim]+=displacement[dim]*displacement[dim];
+           if (fabs(max[dim])<fabs(displacement[dim])) max[dim]=displacement[dim];
+         }
+      }
+       
+    // Normalize
+    for (unsigned int dim=0; dim<list[0].Size(); dim++)
+      {
+       mean[dim]/=list.size();
+       sd[dim]/=list.size();
+       sd[dim]-=mean[dim]*mean[dim];
+       sd[dim]=sqrt(sd[dim]);
+      }
+  }
+
+  //------------------------------------------------------
+  // For multiple lists        
+  //------------------------------------------------------
+  template <class ListItemType> 
+  void 
+  DeformationListStatisticsFilter<ListItemType>::GetStatistics(const ListsType& list, ListType & mean,  ListType & sd,  ListType & max)
+  {
+    mean.resize(list.size());
+    sd.resize(list.size());
+    max.resize(list.size());
+
+    for (unsigned int i=0;i<list.size();i++)
+      {
+       // call function per list
+       GetStatistics(list[i], mean[i], sd[i], max[i]);
+      }
+  }
+
+
+
+  //------------------------------------------------------
+  // Magnitude AND General statistics per component    
+  //------------------------------------------------------
+  template <class ListItemType> 
+  void 
+  DeformationListStatisticsFilter<ListItemType>::GetStatistics(const ListsType& list, ListItemType&  mean, ListItemType &sd, ListItemType & max,  ListType & meanList, ListType & sdList,  ListType & maxList)
+  {
+    // Calculate statistics par list
+    GetStatistics(list, meanList, sdList, maxList);
+
+    // Initialize
+    mean.Fill(itk::NumericTraits<ValueType>::Zero);
+    sd.Fill(itk::NumericTraits<ValueType>::Zero);
+    max.Fill(itk::NumericTraits<ValueType>::Zero);
+    ListItemType displacement;
+
+    // Loop
+    for (unsigned int i=0;i<list.size();i++)
+      {
+
+       mean +=meanList[i];
+       
+       for (unsigned int dim=0; dim<mean.Size(); dim++)
+         {
+            sd[dim]+=sdList[i][dim]*sdList[i][dim];
+            if (fabs(max[dim])<fabs(maxList[i][dim])) max[dim]=maxList[i][dim];
+         }
+      }
+
+    // Normalize
+    for (unsigned int dim=0; dim<mean.Size(); dim++)
+      {
+       mean[dim]/=list.size();
+       sd[dim]/=list.size();
+       //sd[dim]-=mean[dim]*mean[dim];
+       sd[dim]=sqrt(sd[dim]);
+      }
+  }
+
+
+}
+
+#endif
diff --git a/registration/clitkDemonsDeformableRegistration.cxx b/registration/clitkDemonsDeformableRegistration.cxx
new file mode 100755 (executable)
index 0000000..9cc57ec
--- /dev/null
@@ -0,0 +1,47 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+/**
+ * @file   clitkDemonsDeformableRegistration.cxx
+ * @author Jef Vandemeulebroucke <jefvdmb@gmail.com>
+ * @date   April 24  10:14:53 2009
+ * 
+ * @brief  Demons deformable registration 
+ * 
+ */
+
+
+// clitk include
+//#include "clitkDemonsDeformableRegistration_ggo.h"
+#include "clitkIO.h"
+#include "clitkDemonsDeformableRegistrationGenericFilter.h"
+//#include "clitkImageCommon.h"
+
+
+int main( int argc, char *argv[] )
+{
+  
+  GGO(clitkDemonsDeformableRegistration,args_info);
+  CLITK_INIT;
+  
+  //generic Filter
+  clitk::DemonsDeformableRegistrationGenericFilter::Pointer genericFilter = clitk::DemonsDeformableRegistrationGenericFilter::New();
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+  
+  return EXIT_SUCCESS; 
+}
diff --git a/registration/clitkDemonsDeformableRegistration.ggo b/registration/clitkDemonsDeformableRegistration.ggo
new file mode 100755 (executable)
index 0000000..bb58207
--- /dev/null
@@ -0,0 +1,48 @@
+#File clitkDemonsDeformableRegistration.ggo
+#Author: Jef Vandemeulebroucke <jefvdmb@gmail.com>
+#Date : Tue 13 Februari 2009 16.35 
+
+Package "clitk"
+Version "Apply Demons registration between (2D or 3D) images..."
+
+
+option "config"                -       "Config file"                   string          no
+
+
+section "Run Time"
+
+option "verbose"       v       "Verbose"                       flag            off
+option "threads"       -       "Number of threads to use for intensive algorithms (default=min(cores,8))"      int      no
+option "debug"         -       "Give debug info"               flag            off
+
+
+section "Input"
+
+option "reference"     r       "Input reference image"                 string          yes
+option "target"                t       "Input target image"                    string          yes
+option "init"          -       "Input initial deformation field"       string          no
+
+section "Output"
+
+option "vf"            -       "Result DVF"                            string          yes
+option "output"                o       "Deformed target image"                 string          yes
+option "before"                -       "Difference image before "              string          no
+option "after"         -       "Difference image after "               string          no
+
+section "Demons"
+
+option "demons"                -       "Type: 0=normal, 1=symm, 2=fast symm, 3=diffeomorphic"          int             no      default="3"
+option "levels"                -       "Number of resolution levels"                                   int             no      default="1"     
+option "maxIter"       -       "Maximum number of iterations at each resolution level"         int             no      multiple default="50"
+option "maxRMSError"   -       "Maximum RMS error at each resolution level"                    double          no      multiple default="1"    
+option "stop"          -       "Maximum oscillations at each resolution level (-1=unset)"      int             no      multiple default="-1"                                   
+option "sd"            -       "SD (in mm) for smoothing in each dimension"                    double          no      multiple default="2.0"
+option "maxStep"       -       "2,3: Maximum step size (mm)"                                   double          no      default="2"     
+option "scaleSD"       -       "Scale SD to coarse resolution levels"                          flag            off     
+option "scaleStep"     -       "2,3: Scale maximum step size to coarse resolution levels"      flag            off     
+option "fluid"         -       "Smooth update field instead of deformation field"              flag            off     
+option "spacing"       -       "Use image spacing for derivatives (non-isotropic voxels)"      flag            off
+option "intThreshold"  -       "0,1,2: Intensity threshold to consider intensity equal"        double          no      default="0.001" 
+option "movGrad"       -       "1: Use moving image gradient"                                  flag            off     
+option "gradType"      -       "2,3: 0=Symmetric, 1=fixed, 2=warpedMoving, 3=mappedMoving"     int             no      default="0"     
+option "firstOrder"    -       "3: Use first order approx for exponential"                     flag            off     
diff --git a/registration/clitkDemonsDeformableRegistrationGenericFilter.cxx b/registration/clitkDemonsDeformableRegistrationGenericFilter.cxx
new file mode 100755 (executable)
index 0000000..899ab8c
--- /dev/null
@@ -0,0 +1,52 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef _clitkDemonsDeformableRegistrationGenericFilter_cxx
+#define _clitkDemonsDeformableRegistrationGenericFilter_cxx
+#include "clitkDemonsDeformableRegistrationGenericFilter.h"
+
+
+namespace clitk {
+
+  clitk::DemonsDeformableRegistrationGenericFilter::DemonsDeformableRegistrationGenericFilter()
+  {
+    m_Verbose=false;
+  }
+  
+  
+  void clitk::DemonsDeformableRegistrationGenericFilter::Update()
+  {
+    //Get the image Dimension and PixelType
+    int Dimension;
+    std::string PixelType;
+    
+    clitk::ReadImageDimensionAndPixelType(m_ReferenceFileName, Dimension, PixelType);
+    
+    // if(Dimension==2) UpdateWithDim<2>(PixelType);
+    // else 
+    if(Dimension==3) UpdateWithDim<3>(PixelType);
+    // else if (Dimension==4)UpdateWithDim<4>(PixelType); 
+    else 
+      {
+       std::cout<<"Error, Only for 2 or 3  Dimensions!!!"<<std::endl ;
+       return;
+      }
+
+  }
+} //end namespace
+
+#endif
diff --git a/registration/clitkDemonsDeformableRegistrationGenericFilter.h b/registration/clitkDemonsDeformableRegistrationGenericFilter.h
new file mode 100755 (executable)
index 0000000..26059e7
--- /dev/null
@@ -0,0 +1,112 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef _clitkDemonsDeformableRegistrationGenericFilter_h
+#define _clitkDemonsDeformableRegistrationGenericFilter_h
+/**
+   =================================================
+   * @file   clitkDemonsDeformableRegistrationGenericFilter.h
+   * @author Jef Vandemeulebroucke <jef@creatis.insa-lyon.fr>
+   * @date   14 March 2009
+   * 
+   * @brief 
+   * 
+   =================================================*/
+
+// clitk
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkDemonsDeformableRegistration_ggo.h"
+#include "clitkDifferenceImageFilter.h"
+#include "clitkMultiResolutionPDEDeformableRegistration.h"
+
+// itk include
+#include "itkMultiResolutionPDEDeformableRegistration.h"
+#include "itkPDEDeformableRegistrationFilter.h"
+#include "itkDemonsRegistrationFilter.h"
+#include "itkSymmetricForcesDemonsRegistrationFilter.h"
+#include "itkFastSymmetricForcesDemonsRegistrationFilter.h"
+#include "itkDiffeomorphicDemonsRegistrationFilter.h"
+#include "itkRecursiveMultiResolutionPyramidImageFilter.h"
+#include "itkImageFileReader.h"
+#include "itkImageFileWriter.h"
+#include "itkCommand.h"
+#include "itkWarpImageFilter.h"
+#include "itkLightObject.h"
+
+
+namespace clitk
+{
+
+  class ITK_EXPORT DemonsDeformableRegistrationGenericFilter : public itk::LightObject
+  
+  {
+  public:
+    typedef DemonsDeformableRegistrationGenericFilter  Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+    
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);  
+    
+    /** Run-time type information (and related methods) */
+    itkTypeMacro( DemonsDeformableRegistrationGenericFilter, LightObject );
+    
+    
+    //====================================================================
+    // Set methods
+    void SetArgsInfo(const args_info_clitkDemonsDeformableRegistration a)
+    {
+      m_ArgsInfo=a;
+      m_ReferenceFileName=m_ArgsInfo.reference_arg;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+    }
+    
+    //====================================================================
+    // Update
+    virtual void Update();
+    
+  protected:
+    //const char * GetNameOfClass() const { return "DemonsDeformableRegistrationGenericFilter"; }
+    
+    //====================================================================
+    // Constructor & Destructor
+    DemonsDeformableRegistrationGenericFilter();
+    ~DemonsDeformableRegistrationGenericFilter(){;}
+    
+    //====================================================================
+    //Protected member functions
+    template <unsigned int Dimension>  void UpdateWithDim(std::string PixelType);
+    template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+    
+    args_info_clitkDemonsDeformableRegistration m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_ReferenceFileName;
+    
+  };
+  
+} // end namespace clitk
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkDemonsDeformableRegistrationGenericFilter.txx"
+#endif
+  
+#endif //#define _clitkDemonsDeformableRegistrationGenericFilter_h
+
+
+
+
diff --git a/registration/clitkDemonsDeformableRegistrationGenericFilter.txx b/registration/clitkDemonsDeformableRegistrationGenericFilter.txx
new file mode 100755 (executable)
index 0000000..55406bb
--- /dev/null
@@ -0,0 +1,691 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkDemonsDeformableRegistrationGenericFilter_txx
+#define __clitkDemonsDeformableRegistrationGenericFilter_txx
+#include "clitkDemonsDeformableRegistrationGenericFilter.h"
+
+
+namespace clitk
+{
+
+  //==============================================================================
+  //Creating an observer class that allows us to change parameters at subsequent levels
+  //==============================================================================
+  template <typename MultiRegistrationFilterType>
+  class CommandResolutionLevelUpdate : public itk::Command
+  {
+  public:
+    typedef  CommandResolutionLevelUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<Self>  Pointer;
+    itkNewMacro( Self );
+
+    //Typedefs
+    itkStaticConstMacro(ImageDimension, unsigned int, MultiRegistrationFilterType::ImageDimension); 
+    typedef typename MultiRegistrationFilterType::FixedImageType FixedImageType;
+    typedef typename MultiRegistrationFilterType::MovingImageType MovingImageType;
+    typedef typename MultiRegistrationFilterType::DeformationFieldType DeformationFieldType;
+    typedef typename MultiRegistrationFilterType::RegistrationType RegistrationType;
+    typedef typename RegistrationType::FixedImageType InternalImageType;
+    typedef itk::DiffeomorphicDemonsRegistrationFilter<InternalImageType, InternalImageType, DeformationFieldType> DiffFilterType;
+    typedef itk::FastSymmetricForcesDemonsRegistrationFilter<InternalImageType, InternalImageType, DeformationFieldType> SymFilterType;
+
+  protected:
+    CommandResolutionLevelUpdate()
+    {
+      m_CurrentLevel=0;
+      m_MaxStep=2;
+      m_ScaleStep=false;
+      m_ScaleSD=false;
+    }
+
+  public:
+
+    //Set 
+    void SetMaxRMSError(double* m){m_MaxRMSError=m;}
+    void SetSD(double* m){m_SD=m;}
+    void SetMaxStep(double m){m_MaxStep=m;}
+    void SetScaleSD(bool m){m_ScaleSD=m;}
+    void SetScaleStep(bool m){m_ScaleStep=m;}
+    void SetRegistrationType(unsigned int i){m_RegistrationType=i;}
+
+    //Execute
+    void Execute(const itk::Object * caller, const itk::EventObject & event )
+    {
+      std::cout << "Warning: The const Execute method shouldn't be called" << std::endl;
+    }
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+    {
+      
+      // Check event
+      if( !(itk::IterationEvent().CheckEvent( &event )) )
+       {
+         return;
+       }
+      
+      //Cast caller
+      MultiRegistrationFilterType * filter = dynamic_cast<  MultiRegistrationFilterType * >( caller );
+     
+      // Get the level
+      m_CurrentLevel=filter->GetCurrentLevel();
+      unsigned int numberOfLevels=filter->GetNumberOfLevels();
+      unsigned int expandFactor=1<< (numberOfLevels-m_CurrentLevel-1);
+      double * sd = m_SD;
+      double maxStep=m_MaxStep;
+
+      // Scale the SD
+      if (m_ScaleSD)
+       {
+         for (unsigned int i=0 ; i<ImageDimension ; i++) sd[i]*=(double)expandFactor;
+         filter->GetRegistrationFilter()->SetStandardDeviations(sd);
+         filter->GetRegistrationFilter()->SetUpdateFieldStandardDeviations(sd);
+       }
+
+      // Scale max step: 2 & 3 only!
+      if (m_ScaleStep)
+       {
+         maxStep= m_MaxStep*expandFactor;
+         if (m_RegistrationType==2)
+           {
+             SymFilterType* symFilter=dynamic_cast< SymFilterType* >(filter->GetRegistrationFilter());
+             symFilter->SetMaximumUpdateStepLength(maxStep);
+           }
+         else if (m_RegistrationType==3)
+           {
+             DiffFilterType* diffFilter=dynamic_cast< DiffFilterType* >(filter->GetRegistrationFilter());
+             diffFilter->SetMaximumUpdateStepLength(maxStep);
+           }
+       }
+      
+      // Set maxRMS
+      filter->GetRegistrationFilter()->SetMaximumRMSError(m_MaxRMSError[m_CurrentLevel]);
+
+      //Print All
+      std::cout << "--------------------------------------------------" << std::endl;
+      std::cout << "Starting resolution level "<<m_CurrentLevel+1<<" of "<<filter->GetNumberOfLevels()<<"..."<<std::endl;
+      std::cout << "Setting the standard deviations to [ "<<sd[0];
+      for (unsigned int i=1; i<3; i++) std::cout<<", "<< sd[i];
+      std::cout <<" ]..."<<std::endl;
+      if ( (m_RegistrationType==2) || (m_RegistrationType==3) ) std::cout <<"Setting the maximum step size to "<< maxStep<<"..."<<std::endl;
+      std::cout <<"Setting the maximum RMS field change to "<< m_MaxRMSError[m_CurrentLevel]<<"..."<<std::endl;
+      std::cout << "--------------------------------------------------" << std::endl;
+    }
+    
+    double *m_MaxRMSError,*m_SD;
+    double  m_MaxStep;
+    unsigned int m_CurrentLevel, m_RegistrationType;
+    bool m_ScaleSD, m_ScaleStep;
+  };
+
+
+  //==============================================================================
+  // Creating an observer class that allows output at each iteration
+  //==============================================================================
+  template <typename RegistrationFilterType, typename FixedImageType, typename MovingImageType>
+  class CommandIterationUpdate : public itk::Command 
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<Self>  Pointer;
+    typedef  itk::SmartPointer<const Self>  ConstPointer;
+    itkNewMacro( Self );
+    
+    
+    //find the multiresolution filter
+    //     typedef typename  RegistrationFilterType::FixedImageType InternalImageType;
+    //     typedef typename  RegistrationFilterType::MovingImageType MovingImageType;
+    typedef typename  RegistrationFilterType::DeformationFieldType DeformationFieldType;
+    typedef clitk::MultiResolutionPDEDeformableRegistration<FixedImageType, MovingImageType, DeformationFieldType> MultiResolutionRegistrationType; 
+    typedef CommandResolutionLevelUpdate<MultiResolutionRegistrationType> LevelObserver;
+    
+  protected:
+    CommandIterationUpdate(){};
+
+  public:
+
+    // Sets
+    void SetStop( int* s){m_Stop=s;}
+    void SetLevelObserver(LevelObserver* o ){m_LevelObserver=o;}
+
+
+    //Execute
+    void Execute(const itk::Object *, const itk::EventObject & )
+    {
+      std::cout << "Warning: The const Execute method shouldn't be called" << std::endl;
+    } 
+
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+    {
+      if( !(itk::IterationEvent().CheckEvent( &event )) )
+        {
+         return;
+        }
+
+      //Cast 
+      RegistrationFilterType * filter =  dynamic_cast<  RegistrationFilterType * >( caller );
+      
+      if(filter)
+        {
+         // Get info
+         m_Iteration=filter->GetElapsedIterations();
+         m_Metric=filter->GetMetric();
+         
+         // Output
+         std::cout << m_Iteration<<"\t Field Tolerance= "<<filter->GetMaximumRMSError();
+         std::cout <<"\t DVF Change= " << filter->GetRMSChange()<<"\t RMS= "<<m_Metric;
+
+         // Using stop criterion?
+         if (m_Stop[m_LevelObserver->m_CurrentLevel]>=0)
+           {
+             // First iteration
+             if(m_Iteration==1)
+               {
+                 m_Minimum=m_Metric;
+                 m_StopCounter=0;
+               }
+             
+             // Less then minimum
+             else if(m_Metric<m_Minimum)
+               {
+                 m_StopCounter=0; 
+                 m_Minimum=m_Metric;
+               }
+
+             //Not less then minimum
+             else 
+               {
+                 m_StopCounter++;
+                 if (m_StopCounter>=m_Stop[m_LevelObserver->m_CurrentLevel])
+                   filter->StopRegistration();
+               }
+             
+             // Output
+             std::cout <<"\t Stop= "<<m_StopCounter<<" / "<<m_Stop[m_LevelObserver->m_CurrentLevel]<<std::endl;
+           }
+
+         // Not using stop criterion 
+         else std::cout <<std::endl;
+       }
+    }
+
+    double m_Minimum, m_Metric;
+    int m_StopCounter, m_Iteration;
+    int * m_Stop;
+    LevelObserver* m_LevelObserver; 
+  };
+
+
+  //==============================================================================
+  // Update with the number of dimensions
+  //==============================================================================
+  template<unsigned int Dimension>
+  void DemonsDeformableRegistrationGenericFilter::UpdateWithDim(std::string PixelType)
+  {
+    if(PixelType == "short"){  
+      if (m_Verbose) std::cout  << "Launching warp in "<< Dimension <<"D and signed short..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, signed short>(); 
+    }
+    //    else if(PixelType == "unsigned_short"){  
+    //       if (m_Verbose) std::cout  << "Launching warp in "<< Dimension <<"D and unsigned_short..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, unsigned short>(); 
+    //     }
+    
+    //     else if (PixelType == "unsigned_char"){ 
+    //       if (m_Verbose) std::cout  << "Launching warp in "<< Dimension <<"D and unsigned_char..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, unsigned char>();
+    //     }
+    
+    //     else if (PixelType == "char"){ 
+    //       if (m_Verbose) std::cout  << "Launching warp in "<< Dimension <<"D and signed_char..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, signed char>();
+    //    }
+    else {
+      if (m_Verbose) std::cout  << "Launching warp in "<< Dimension <<"D and float..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, float>();
+    }
+  }
+
+  
+
+  //==============================================================================
+  // Update with the number of dimensions and pixeltype
+  //==============================================================================
+  //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+  template<unsigned int ImageDimension, class PixelType>
+  void DemonsDeformableRegistrationGenericFilter::UpdateWithDimAndPixelType()
+  {
+    //=======================================================
+    // Run-time
+    //=======================================================
+    bool threadsGiven=m_ArgsInfo.threads_given;
+    int threads=m_ArgsInfo.threads_arg;
+    
+    typedef itk::Image< PixelType, ImageDimension >  FixedImageType;
+    typedef itk::Image< PixelType, ImageDimension >  MovingImageType;
+    typedef itk::Image< float, ImageDimension >  InternalImageType;
+    typedef double TCoordRep;
+
+
+    //=======================================================
+    //Input
+    //=======================================================
+    typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
+    typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;
+
+    typename FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
+    typename MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();
+
+    fixedImageReader->SetFileName(  m_ArgsInfo.reference_arg );
+    movingImageReader->SetFileName( m_ArgsInfo.target_arg );
+    if (m_Verbose) std::cout<<"Reading images..."<<std::endl;
+    fixedImageReader->Update();
+    movingImageReader->Update();
+
+    typename FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+    typename MovingImageType::Pointer movingImage =movingImageReader->GetOutput();
+    typename FixedImageType::RegionType fixedRegion = fixedImage->GetBufferedRegion();
+   
+
+    //=======================================================
+    //Output
+    //=======================================================
+    typedef itk::Vector< float, ImageDimension >    VectorPixelType;
+    typedef itk::Image<  VectorPixelType, ImageDimension > DeformationFieldType;
+
+
+    //=======================================================
+    //Pyramids
+    //=======================================================
+    typedef itk::RecursiveMultiResolutionPyramidImageFilter< FixedImageType, InternalImageType>    FixedImagePyramidType;
+    typedef itk::RecursiveMultiResolutionPyramidImageFilter< MovingImageType, InternalImageType>    MovingImagePyramidType;
+    // typedef itk::MultiResolutionPyramidImageFilter< FixedImageType, FixedImageType>    FixedImagePyramidType;
+    // typedef itk::MultiResolutionPyramidImageFilter< MovingImageType, MovingImageType>    MovingImagePyramidType;
+    typename FixedImagePyramidType::Pointer fixedImagePyramid = FixedImagePyramidType::New();
+    typename MovingImagePyramidType::Pointer movingImagePyramid = MovingImagePyramidType::New();
+
+    
+    // =======================================================
+    // Define the registation filters
+    // =======================================================
+    typedef itk::PDEDeformableRegistrationFilter< InternalImageType, InternalImageType, DeformationFieldType>   RegistrationFilterType;
+    typename RegistrationFilterType::Pointer pdeFilter;
+    typedef clitk::MultiResolutionPDEDeformableRegistration<FixedImageType,MovingImageType,DeformationFieldType >  MultiResolutionRegistrationFilterType;
+    typename MultiResolutionRegistrationFilterType::Pointer multiResolutionFilter =  MultiResolutionRegistrationFilterType::New();
+    typedef itk::ESMDemonsRegistrationFunction<InternalImageType, InternalImageType, DeformationFieldType> RegistrationFunctionType;
+
+
+    // =======================================================
+    // The multiresolution scheme
+    // =======================================================
+    if (threadsGiven) multiResolutionFilter->SetNumberOfThreads(threads);
+    unsigned int nLevels=m_ArgsInfo.levels_arg;
+    if (m_Verbose) std::cout<<"Setting the number of resolution levels to "<<nLevels<<"..."<<std::endl;
+    multiResolutionFilter->SetFixedImage( fixedImage );
+    multiResolutionFilter->SetMovingImage( movingImage );
+    multiResolutionFilter->SetNumberOfLevels( nLevels );
+    multiResolutionFilter->SetFixedImagePyramid( fixedImagePyramid );
+    multiResolutionFilter->SetMovingImagePyramid( movingImagePyramid );
+    if (threadsGiven) multiResolutionFilter->SetNumberOfThreads( threads );
+    
+    //------------------------------------
+    //Set the number of iterations
+    //------------------------------------
+    unsigned int nIterations[nLevels];
+    for (unsigned int i=0 ; i<nLevels; i++)
+      {
+       if (m_ArgsInfo.maxIter_given==nLevels)
+         {
+           nIterations[i] =m_ArgsInfo.maxIter_arg[i];
+         }
+       else
+         nIterations[i]=m_ArgsInfo.maxIter_arg[0];
+      }
+    multiResolutionFilter->SetNumberOfIterations( nIterations );
+    if(m_Verbose) {
+      std::cout<<"Setting the number of iterations to: "<<nIterations[0];
+      for (unsigned int i=1; i<nLevels; i++)
+       std::cout<<", "<<nIterations [i];
+      std::cout<<std::endl;
+    }
+    
+    //------------------------------------
+    //Set the max RMS error for the field update
+    //------------------------------------
+    double maxRMSError[nLevels];
+    for (unsigned int i=0 ; i<nLevels; i++)
+      {
+       if (m_ArgsInfo.maxRMSError_given==nLevels)      
+         maxRMSError[i] =m_ArgsInfo.maxRMSError_arg[i];
+       else
+         maxRMSError[i]=m_ArgsInfo.maxRMSError_arg[0];
+      }
+    if(m_Verbose) {
+      std::cout<<"Setting the max root mean squared error to: "<<maxRMSError[0];
+      for (unsigned int i=1; i<nLevels; i++)
+       std::cout<<", "<<maxRMSError[i];
+      std::cout<<std::endl;
+    }
+
+    //------------------------------------
+    //Get the stop criterion
+    //------------------------------------
+    int stop[nLevels];
+    for (unsigned int i=0; i<nLevels; i++)
+      if (m_ArgsInfo.stop_given==nLevels)
+       stop[i]=m_ArgsInfo.stop_arg[i];
+      else
+       stop[i]=m_ArgsInfo.stop_arg[0];
+    if(m_Verbose) {
+      std::cout<<"Setting the stop criterion to : "<<stop[0];
+      for (unsigned int i=1; i<nLevels; i++)
+       std::cout<<", "<<stop[i];
+      std::cout<<std::endl;
+    }
+    
+    //------------------------------------
+    //Grad type
+    //------------------------------------
+    typename RegistrationFunctionType::GradientType grad=RegistrationFunctionType::Symmetric;
+    switch (m_ArgsInfo.gradType_arg)
+      {
+      case 0:
+       grad= RegistrationFunctionType::Symmetric;
+       break;
+      case 1:
+       grad= RegistrationFunctionType::Fixed;
+       break;
+      case 2:
+       grad= RegistrationFunctionType::WarpedMoving;
+       break;
+      case 3:
+       grad= RegistrationFunctionType::MappedMoving;
+       break;
+      }
+
+    //------------------------------------
+    // Set smoothing standard deviations
+    //------------------------------------
+    double sd [ImageDimension];
+    for (unsigned int i=0; i<ImageDimension; i++)
+      if (m_ArgsInfo.sd_given==ImageDimension)
+       sd[i]=m_ArgsInfo.sd_arg[i];
+      else
+       sd[i]=m_ArgsInfo.sd_arg[0];
+    if(m_Verbose) {
+      std::cout<<"Setting the final standard deviations for smoothing to: "<<sd[0];
+      for (unsigned int i=1; i<ImageDimension; i++)
+       std::cout<<", "<<sd[i];
+      std::cout<<std::endl;
+    }
+    
+    // =======================================================
+    // The level observer: adjust settings at each level
+    // =======================================================
+    typename CommandResolutionLevelUpdate<MultiResolutionRegistrationFilterType>::Pointer levelObserver = 
+      CommandResolutionLevelUpdate<MultiResolutionRegistrationFilterType>::New();
+    multiResolutionFilter->AddObserver( itk::IterationEvent(), levelObserver );
+    levelObserver->SetMaxRMSError(maxRMSError);
+    levelObserver->SetMaxStep(m_ArgsInfo.maxStep_arg);
+    levelObserver->SetSD(sd);
+    levelObserver->SetScaleStep(m_ArgsInfo.scaleStep_flag);
+    levelObserver->SetScaleSD(m_ArgsInfo.scaleSD_flag);
+    levelObserver->SetRegistrationType(m_ArgsInfo.demons_arg);
+
+
+    // =======================================================
+    // The type of filter
+    // =======================================================
+    switch (m_ArgsInfo.demons_arg){
+      
+    case 0:
+      {
+       typedef itk::DemonsRegistrationFilter< InternalImageType, InternalImageType, DeformationFieldType > DemonsFilterType;
+       typename DemonsFilterType::Pointer m =DemonsFilterType::New();
+       
+       //Set Parameters for this filter
+       m->SetIntensityDifferenceThreshold( m_ArgsInfo.intThreshold_arg);
+       m->SetUseMovingImageGradient( m_ArgsInfo.movGrad_flag);
+       typename CommandIterationUpdate<DemonsFilterType, FixedImageType, MovingImageType>::Pointer observer = CommandIterationUpdate<DemonsFilterType, FixedImageType, MovingImageType>::New();
+       observer->SetStop(stop);
+       observer->SetLevelObserver(levelObserver);
+       m->AddObserver( itk::IterationEvent(), observer );
+       if (m_Verbose)  std::cout<<"Using the demons registration filter..."<<std::endl;
+         pdeFilter=m;
+         break;
+       }
+    
+    case 1:
+      {
+       typedef itk::SymmetricForcesDemonsRegistrationFilter< InternalImageType, InternalImageType, DeformationFieldType > DemonsFilterType; 
+       typename DemonsFilterType::Pointer m =DemonsFilterType::New();
+       
+       //Set Parameters for this filter
+       m->SetIntensityDifferenceThreshold( m_ArgsInfo.intThreshold_arg);
+       typename CommandIterationUpdate<DemonsFilterType, FixedImageType, MovingImageType>::Pointer observer = CommandIterationUpdate<DemonsFilterType, FixedImageType, MovingImageType>::New();
+       observer->SetStop(stop);
+       observer->SetLevelObserver(levelObserver);
+       m->AddObserver( itk::IterationEvent(), observer );
+       if (m_Verbose) std::cout<<"Using the symmetric forces demons registration filter..."<<std::endl;
+       pdeFilter=m;
+       break;
+      }
+      
+    case 2:
+      {
+       typedef itk::FastSymmetricForcesDemonsRegistrationFilter< InternalImageType, InternalImageType, DeformationFieldType > DemonsFilterType;
+       typename DemonsFilterType::Pointer m = DemonsFilterType::New();
+       
+       //Set Parameters for this filter
+       m->SetIntensityDifferenceThreshold( m_ArgsInfo.intThreshold_arg);
+       m->SetMaximumUpdateStepLength( m_ArgsInfo.maxStep_arg);
+       m->SetUseGradientType(grad);
+       typename CommandIterationUpdate<DemonsFilterType, FixedImageType, MovingImageType>::Pointer observer = CommandIterationUpdate<DemonsFilterType, FixedImageType, MovingImageType>::New();
+       observer->SetStop(stop);
+       observer->SetLevelObserver(levelObserver);
+       m->AddObserver( itk::IterationEvent(), observer );
+       if (m_Verbose) std::cout<<"Using the fast symmetric forces demons registration filter..."<<std::endl;
+       pdeFilter=m;
+       break;
+      }
+
+    case 3:
+      {
+       typedef itk::DiffeomorphicDemonsRegistrationFilter< InternalImageType, InternalImageType, DeformationFieldType > DemonsFilterType;
+       typename DemonsFilterType::Pointer m =  DemonsFilterType::New();
+       
+       //Set Parameters for this filter
+       m->SetMaximumUpdateStepLength( m_ArgsInfo.maxStep_arg);
+       m->SetUseFirstOrderExp(m_ArgsInfo.firstOrder_flag);
+       m->SetUseGradientType(grad);
+       typename CommandIterationUpdate<DemonsFilterType, FixedImageType, MovingImageType>::Pointer observer = CommandIterationUpdate<DemonsFilterType, FixedImageType, MovingImageType>::New();
+       observer->SetStop(stop);
+       observer->SetLevelObserver(levelObserver);
+       m->AddObserver( itk::IterationEvent(), observer );
+       if (m_Verbose) std::cout<<"Using the diffeomorphic demons registration filter..."<<std::endl;
+       pdeFilter=m;
+       break;
+      }
+    }
+
+
+
+    //Set common options
+    pdeFilter->SetStandardDeviations( sd );
+    pdeFilter->SetUpdateFieldStandardDeviations( sd );
+    //JV TODO
+    // pdeFilter->SetMaximumError(m_ArgsInfo.maxError_arg);
+    // pdeFilter->SetMaximumKernelWidth(m_ArgsInfo.maxError_arg);
+    pdeFilter->SetSmoothDeformationField(!m_ArgsInfo.fluid_flag);
+    pdeFilter->SetSmoothUpdateField(m_ArgsInfo.fluid_flag);
+    pdeFilter->SetUseImageSpacing( m_ArgsInfo.spacing_flag );
+
+    //Pass to the multi resolution scheme
+    multiResolutionFilter->SetRegistrationFilter( pdeFilter );
+   
+    
+    // =======================================================
+    // The initial solution
+    // =======================================================
+    if (m_ArgsInfo.init_given)
+      {
+       typedef itk::ImageFileReader<DeformationFieldType> DeformationFieldReaderType;      
+       typename DeformationFieldReaderType::Pointer defReader=DeformationFieldReaderType::New();
+       defReader->SetFileName(m_ArgsInfo.init_arg);
+       defReader->Update();
+       multiResolutionFilter->SetArbitraryInitialDeformationField(defReader->GetOutput());
+      }
+   
+  
+    // =======================================================
+    // Execute
+    // =======================================================
+    try
+      {
+       multiResolutionFilter->Update();
+      }
+    catch( itk::ExceptionObject & excp )
+      {
+       std::cerr <<"Error executing the demons filter: "<< excp << std::endl;
+       return;
+      }
+
+    
+    //=======================================================
+    // Get the output
+    //=======================================================
+    typename DeformationFieldType::Pointer deformationField=multiResolutionFilter->GetOutput();
+
+
+    //=======================================================
+    // Write the DVF
+    //=======================================================
+    typedef itk::ImageFileWriter< DeformationFieldType >  FieldWriterType;
+    typename FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+    fieldWriter->SetInput( deformationField );
+    fieldWriter->SetFileName( m_ArgsInfo.vf_arg );
+    try
+      {
+       fieldWriter->Update();
+      }
+    catch( itk::ExceptionObject & excp )
+      {
+       std::cerr << "Exception thrown writing the DVF" << std::endl;
+       std::cerr << excp << std::endl;
+       return;
+      }
+    
+  
+    //=======================================================
+    // Warp the moving image
+    //=======================================================
+    typedef itk::WarpImageFilter< MovingImageType, FixedImageType, DeformationFieldType >    WarpFilterType;
+    typename WarpFilterType::Pointer warp = WarpFilterType::New();
+
+    warp->SetDeformationField( deformationField );
+    warp->SetInput( movingImageReader->GetOutput() );
+    warp->SetOutputOrigin(  fixedImage->GetOrigin() );
+    warp->SetOutputSpacing( fixedImage->GetSpacing() );
+    warp->SetOutputDirection( fixedImage->GetDirection() );
+    warp->SetEdgePaddingValue( 0.0 );
+    warp->Update();
+
+    //=======================================================
+    // Write the warped image
+    //=======================================================
+    typedef itk::ImageFileWriter< FixedImageType >  WriterType;
+    typename WriterType::Pointer      writer =  WriterType::New();
+    writer->SetFileName( m_ArgsInfo.output_arg );
+    writer->SetInput( warp->GetOutput()    );
+
+    try
+      {
+       writer->Update();
+      }
+    catch( itk::ExceptionObject & err ) 
+      { 
+       std::cerr << "ExceptionObject caught !" << std::endl; 
+       std::cerr << err << std::endl; 
+       return;
+      } 
+
+    //=======================================================
+    // Calculate the difference after the deformable transform
+    //=======================================================
+    typedef clitk::DifferenceImageFilter<  FixedImageType, FixedImageType> DifferenceFilterType;
+    if (m_ArgsInfo.after_given)
+      {
+       typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
+       difference->SetValidInput( fixedImage );
+       difference->SetTestInput( warp->GetOutput() );
+      
+       try
+         {
+           difference->Update();
+         }
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught calculating the difference !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         }
+      
+       typename WriterType::Pointer differenceWriter=WriterType::New();
+       differenceWriter->SetInput(difference->GetOutput());
+       differenceWriter->SetFileName(m_ArgsInfo.after_arg);
+       differenceWriter->Update(); 
+      
+      }
+
+
+    //=======================================================
+    // Calculate the difference before the deformable transform
+    //=======================================================
+    if( m_ArgsInfo.before_given )
+      {
+       typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
+       difference->SetValidInput( fixedImage );
+       difference->SetTestInput( movingImage );
+    
+       try
+         {
+           difference->Update();
+         }
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught calculating the difference !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         }
+
+       typename WriterType::Pointer differenceWriter=WriterType::New();
+       writer->SetFileName( m_ArgsInfo.before_arg  );
+       writer->SetInput( difference->GetOutput()  );
+       writer->Update( );
+      }
+
+    return;
+  }
+}//end namespace
+
+#endif // __clitkDemonsDeformableRegistrationGenericFilter_txx
diff --git a/registration/clitkDifferenceImageFilter.h b/registration/clitkDifferenceImageFilter.h
new file mode 100755 (executable)
index 0000000..29b2844
--- /dev/null
@@ -0,0 +1,73 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkDifferenceImageFilter_h
+#define __clitkDifferenceImageFilter_h
+#include "clitkImageCommon.h"
+
+//itk include
+#include "itkImageToImageFilter.h"
+#include "itkImage.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkNumericTraits.h"
+
+namespace clitk
+{
+  
+  template <  class InputImageType , class OutputImageType>  
+  class DifferenceImageFilter : public itk::ImageToImageFilter<InputImageType, OutputImageType>
+  
+  {
+  public:
+    typedef DifferenceImageFilter     Self;
+    typedef itk::ImageToImageFilter<InputImageType,OutputImageType>     Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+
+   
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);  
+  
+    /** Determine the image dimension. */
+    itkStaticConstMacro(ImageDimension, unsigned int,
+                       InputImageType::ImageDimension );
+  
+    /** Inherit some types from the superclass. */
+    typedef typename OutputImageType::RegionType OutputImageRegionType;
+        
+    //Set
+    void SetValidInput(const typename InputImageType::Pointer input);
+    void SetTestInput( const typename InputImageType::Pointer input);
+  
+  protected:
+    DifferenceImageFilter();
+    ~DifferenceImageFilter() {};
+    void ThreadedGenerateData(const OutputImageRegionType& threadRegion, int threadId);
+    
+       
+  };
+
+
+
+
+
+} // end namespace clitk
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkDifferenceImageFilter.txx"
+#endif
+
+#endif // #define __clitkDifferenceImageFilter_h
diff --git a/registration/clitkDifferenceImageFilter.txx b/registration/clitkDifferenceImageFilter.txx
new file mode 100755 (executable)
index 0000000..9c267e3
--- /dev/null
@@ -0,0 +1,85 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkDifferenceImageFilter_txx
+#define __clitkDifferenceImageFilter_txx
+#include "clitkDifferenceImageFilter.h"
+
+
+namespace clitk
+{
+
+  //=========================================================================================================================
+  // DifferenceImageFilter
+  //=========================================================================================================================
+
+  //=========================================================================================================================
+  //constructor
+  template <class InputImageType, class OutputImageType> 
+  DifferenceImageFilter<InputImageType, OutputImageType>::DifferenceImageFilter()
+  {
+    this->SetNumberOfRequiredInputs(2);
+  }
+
+  //=========================================================================================================================
+  //set input
+  template <class InputImageType, class OutputImageType> 
+  void DifferenceImageFilter<InputImageType, OutputImageType>::SetValidInput(const typename InputImageType::Pointer input)
+  {
+    this->SetNthInput(0,input);
+  }
+
+  template <class InputImageType, class OutputImageType> 
+  void DifferenceImageFilter<InputImageType, OutputImageType>::SetTestInput(const typename InputImageType::Pointer input)
+  {
+    this->SetNthInput(1,input);
+  }
+
+
+  //=========================================================================================================================
+  //Update
+  template <class InputImageType, class OutputImageType> 
+  void DifferenceImageFilter<InputImageType, OutputImageType>::ThreadedGenerateData(const OutputImageRegionType &threadRegion, int threadId)
+  {
+    //Pointers to input and output
+    typename InputImageType::ConstPointer input1=this->GetInput(0);
+    typename InputImageType::ConstPointer input2=this->GetInput(1);
+    typename OutputImageType::Pointer output=this->GetOutput();
+
+    //Iterator over input1, input0 and output
+    typedef itk::ImageRegionConstIterator<InputImageType> InputIteratortype;
+    typedef itk::ImageRegionIterator<OutputImageType> OutputIteratortype;
+    InputIteratortype input1Iterator (input1, threadRegion);
+    InputIteratortype input2Iterator (input2, threadRegion);
+    OutputIteratortype outputIterator (output, threadRegion);
+    input1Iterator.GoToBegin();
+    input2Iterator.GoToBegin();
+    outputIterator.GoToBegin();
+
+    while (!outputIterator.IsAtEnd())
+      {
+       outputIterator.Set(input1Iterator.Get()-input2Iterator.Get());
+       ++input1Iterator;
+       ++input2Iterator;
+       ++outputIterator;        
+      }
+  }
+      
+}
+
+
+#endif
diff --git a/registration/clitkExtractImageFilter.h b/registration/clitkExtractImageFilter.h
new file mode 100644 (file)
index 0000000..12880ac
--- /dev/null
@@ -0,0 +1,113 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkExtractImageFilter_h
+#define __clitkExtractImageFilter_h
+#include "itkImageToImageFilter.h"
+#include "itkSmartPointer.h"
+#include "itkExtractImageFilterRegionCopier.h"
+
+namespace clitk
+{
+
+template <class TInputImage, class TOutputImage>
+class ITK_EXPORT ExtractImageFilter:
+    public itk::ImageToImageFilter<TInputImage,TOutputImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef ExtractImageFilter         Self;
+  typedef itk::ImageToImageFilter<TInputImage,TOutputImage>  Superclass;
+  typedef itk::SmartPointer<Self>  Pointer;
+  typedef itk::SmartPointer<const Self>  ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);  
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(ExtractImageFilter, ImageToImageFilter);
+
+  /** Image type information. */
+  typedef TInputImage  InputImageType;
+  typedef TOutputImage OutputImageType;
+
+  /** Typedef to describe the output and input image region types. */
+  typedef typename TOutputImage::RegionType OutputImageRegionType;
+  typedef typename TInputImage::RegionType InputImageRegionType;
+
+  /** Typedef to describe the type of pixel. */
+  typedef typename TOutputImage::PixelType OutputImagePixelType;
+  typedef typename TInputImage::PixelType InputImagePixelType;
+
+  /** Typedef to describe the output and input image index and size types. */
+  typedef typename TOutputImage::IndexType OutputImageIndexType;
+  typedef typename TInputImage::IndexType InputImageIndexType;
+  typedef typename TOutputImage::SizeType OutputImageSizeType;
+  typedef typename TInputImage::SizeType InputImageSizeType;
+
+  /** ImageDimension enumeration */
+  itkStaticConstMacro(InputImageDimension, unsigned int,
+                      TInputImage::ImageDimension);
+  itkStaticConstMacro(OutputImageDimension, unsigned int,
+                      TOutputImage::ImageDimension);
+
+  typedef itk::ImageToImageFilterDetail::ExtractImageFilterRegionCopier<
+    itkGetStaticConstMacro(InputImageDimension), 
+    itkGetStaticConstMacro(OutputImageDimension)> ExtractImageFilterRegionCopierType;
+
+  void SetExtractionRegion(InputImageRegionType extractRegion);
+  itkGetMacro(ExtractionRegion, InputImageRegionType);
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+  /** Begin concept checking */
+  itkConceptMacro(InputCovertibleToOutputCheck,
+                 (itk::Concept::Convertible<InputImagePixelType, OutputImagePixelType>));
+  /** End concept checking */
+#endif
+
+protected:
+  ExtractImageFilter();
+  ~ExtractImageFilter() {};
+  void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+
+  virtual void GenerateOutputInformation();
+
+
+  virtual void CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion,
+                                                 const OutputImageRegionType &srcRegion);
+
+
+  void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+                            int threadId );
+  InputImageRegionType m_ExtractionRegion;
+  OutputImageRegionType m_OutputImageRegion;
+
+private:
+  ExtractImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+};
+
+  
+} // end namespace itk
+  
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkExtractImageFilter.txx"
+#endif
+  
+#endif
diff --git a/registration/clitkExtractImageFilter.txx b/registration/clitkExtractImageFilter.txx
new file mode 100644 (file)
index 0000000..f4aa402
--- /dev/null
@@ -0,0 +1,274 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef _clitkExtractImageFilter_txx
+#define _clitkExtractImageFilter_txx
+#include "clitkExtractImageFilter.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkObjectFactory.h"
+#include "itkExtractImageFilterRegionCopier.h"
+#include "itkProgressReporter.h"
+
+
+namespace clitk
+{
+
+/**
+ *
+ */
+template <class TInputImage, class TOutputImage>
+ExtractImageFilter<TInputImage,TOutputImage>
+::ExtractImageFilter() 
+{
+}
+
+
+/**
+ *
+ */
+template <class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os,indent);
+
+  os << indent << "ExtractionRegion: " << m_ExtractionRegion << std::endl;
+  os << indent << "OutputImageRegion: " << m_OutputImageRegion << std::endl;
+}
+
+
+template<class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::CallCopyOutputRegionToInputRegion(InputImageRegionType &destRegion,
+                                    const OutputImageRegionType &srcRegion)
+{
+  ExtractImageFilterRegionCopierType extractImageRegionCopier;
+  extractImageRegionCopier(destRegion, srcRegion, m_ExtractionRegion);
+}
+
+
+template <class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::SetExtractionRegion(InputImageRegionType extractRegion)
+{
+  m_ExtractionRegion = extractRegion;
+
+  unsigned int nonzeroSizeCount = 0;
+  InputImageSizeType inputSize = extractRegion.GetSize();
+  OutputImageSizeType outputSize;
+  OutputImageIndexType outputIndex;
+
+  /**
+   * check to see if the number of non-zero entries in the extraction region
+   * matches the number of dimensions in the output image.  
+   **/
+  for (unsigned int i = 0; i < InputImageDimension; ++i)
+    {
+    if (inputSize[i])
+      { 
+      outputSize[nonzeroSizeCount] = inputSize[i];    
+      outputIndex[nonzeroSizeCount] = extractRegion.GetIndex()[i];
+      nonzeroSizeCount++;
+      }
+    }
+    
+  if (nonzeroSizeCount != OutputImageDimension)
+    {
+    itkExceptionMacro("Extraction Region not consistent with output image");
+    }
+
+  m_OutputImageRegion.SetSize(outputSize);
+  m_OutputImageRegion.SetIndex(outputIndex);
+  this->Modified();
+}
+
+
+
+/** 
+ * ExtractImageFilter can produce an image which is a different resolution
+ * than its input image.  As such, ExtractImageFilter needs to provide an
+ * implementation for GenerateOutputInformation() in order to inform
+ * the pipeline execution model.  The original documentation of this
+ * method is below.
+ *
+ * \sa ProcessObject::GenerateOutputInformaton() 
+ */
+template <class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::GenerateOutputInformation()
+{
+  // do not call the superclass' implementation of this method since
+  // this filter allows the input and the output to be of different dimensions
+  // get pointers to the input and output
+  typename Superclass::OutputImagePointer      outputPtr = this->GetOutput();
+  typename Superclass::InputImageConstPointer  inputPtr  = this->GetInput();
+
+  if ( !outputPtr || !inputPtr)
+    {
+    return;
+    }
+
+  // Set the output image size to the same value as the extraction region.
+  outputPtr->SetLargestPossibleRegion( m_OutputImageRegion );
+
+  // Set the output spacing and origin
+  const itk::ImageBase<InputImageDimension> *phyData;
+
+  phyData
+    = dynamic_cast<const itk::ImageBase<InputImageDimension>*>(this->GetInput());
+
+  if (phyData)
+    {
+    // Copy what we can from the image from spacing and origin of the input
+    // This logic needs to be augmented with logic that select which
+    // dimensions to copy
+
+    unsigned int i;
+    const typename InputImageType::SpacingType& 
+      inputSpacing = inputPtr->GetSpacing();
+    const typename InputImageType::DirectionType&
+      inputDirection = inputPtr->GetDirection();
+    const typename InputImageType::PointType&
+      inputOrigin = inputPtr->GetOrigin();
+
+    typename OutputImageType::SpacingType outputSpacing;
+    typename OutputImageType::DirectionType outputDirection;
+    typename OutputImageType::PointType outputOrigin;
+
+    if ( static_cast<unsigned int>(OutputImageDimension) > 
+         static_cast<unsigned int>(InputImageDimension )    )
+      {
+      // copy the input to the output and fill the rest of the
+      // output with zeros.
+      for (i=0; i < InputImageDimension; ++i)
+        {
+        outputSpacing[i] = inputSpacing[i];
+        outputOrigin[i] = inputOrigin[i];
+        for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
+          {
+          outputDirection[i][dim] = inputDirection[i][dim];
+          }
+        }
+      for (; i < OutputImageDimension; ++i)
+        {
+        outputSpacing[i] = 1.0;
+        outputOrigin[i] = 0.0;
+        for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
+          {
+          outputDirection[i][dim] = 0.0;
+          }
+        outputDirection[i][i] = 1.0;
+        }
+      }
+    else
+      {
+      // copy the non-collapsed part of the input spacing and origing to the output
+      int nonZeroCount = 0;
+      for (i=0; i < InputImageDimension; ++i)
+        {
+        if (m_ExtractionRegion.GetSize()[i])
+          {
+          outputSpacing[nonZeroCount] = inputSpacing[i];
+          outputOrigin[nonZeroCount] = inputOrigin[i];
+          int nonZeroCount2 = 0;
+          for (unsigned int dim = 0; dim < InputImageDimension; ++dim)
+            {
+            if (m_ExtractionRegion.GetSize()[dim])
+              {
+              outputDirection[nonZeroCount][nonZeroCount2] =
+                inputDirection[i][dim];
+              ++nonZeroCount2;
+              }
+            }
+          nonZeroCount++;
+          }
+        }
+      }
+
+    // set the spacing and origin
+    outputPtr->SetSpacing( outputSpacing );
+    outputPtr->SetDirection( outputDirection );
+    outputPtr->SetOrigin( outputOrigin );
+    outputPtr->SetNumberOfComponentsPerPixel(inputPtr->GetNumberOfComponentsPerPixel() );
+    }
+  else
+    {
+    // pointer could not be cast back down
+    itkExceptionMacro(<< "itk::ExtractImageFilter::GenerateOutputInformation "
+                      << "cannot cast input to "
+                      << typeid(itk::ImageBase<InputImageDimension>*).name() );
+    }
+}
+
+/** 
+   * ExtractImageFilter can be implemented as a multithreaded filter.
+   * Therefore, this implementation provides a ThreadedGenerateData()
+   * routine which is called for each processing thread. The output
+   * image data is allocated automatically by the superclass prior to
+   * calling ThreadedGenerateData().  ThreadedGenerateData can only
+   * write to the portion of the output image specified by the
+   * parameter "outputRegionForThread"
+   *
+   * \sa ImageToImageFilter::ThreadedGenerateData(),
+   *     ImageToImageFilter::GenerateData() 
+   */
+template <class TInputImage, class TOutputImage>
+void 
+ExtractImageFilter<TInputImage,TOutputImage>
+::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+                       int threadId)
+{
+  itkDebugMacro(<<"Actually executing");
+
+  // Get the input and output pointers
+  typename Superclass::InputImageConstPointer  inputPtr = this->GetInput();
+  typename Superclass::OutputImagePointer outputPtr = this->GetOutput();
+
+  // support progress methods/callbacks
+ itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+  
+  // Define the portion of the input to walk for this thread
+  InputImageRegionType inputRegionForThread;
+  this->CallCopyOutputRegionToInputRegion(inputRegionForThread, outputRegionForThread);
+  
+  // Define the iterators.
+  typedef itk::ImageRegionIterator<TOutputImage> OutputIterator;
+  typedef itk::ImageRegionConstIterator<TInputImage> InputIterator;
+
+  OutputIterator outIt(outputPtr, outputRegionForThread);
+  InputIterator inIt(inputPtr, inputRegionForThread);
+
+  // walk the output region, and sample the input image
+  while( !outIt.IsAtEnd() )
+    {
+    // copy the input pixel to the output
+    outIt.Set( static_cast<OutputImagePixelType>(inIt.Get()));
+    ++outIt; 
+    ++inIt; 
+    progress.CompletedPixel();
+    }
+}
+
+} // end namespace clitk
+
+#endif
diff --git a/registration/clitkGenericVectorInterpolator.h b/registration/clitkGenericVectorInterpolator.h
new file mode 100755 (executable)
index 0000000..557d419
--- /dev/null
@@ -0,0 +1,93 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkGenericVectorInterpolator_h
+#define __clitkGenericVectorInterpolator_h
+#include "clitkImageCommon.h"
+
+//itk include
+#include "itkVectorNearestNeighborInterpolateImageFunction.h"
+#include "itkVectorLinearInterpolateImageFunction.h"
+#include "clitkVectorBSplineInterpolateImageFunction.h"
+#include "clitkVectorBSplineInterpolateImageFunctionWithLUT.h"
+
+/*
+
+Requires at least the following section is the .ggo file
+
+option "interpVF"              -       "Interpolation: 0=NN, 1=Linear, 2=BSpline, 3=BLUT"      int     no  default="1"
+option "interpVFOrder" -       "Order if BLUT or BSpline (0-5)"                        int     no  default="3"
+option "interpVFSF"    -       "Sampling factor if BLUT"                               int     no  default="20"
+
+The use will look something like
+
+typedef clitk::GenericVectorInterpolator<InputImageType, double> GenericVectorInterpolatorType;
+typename GenericVectorInterpolatorType::Pointer genericInterpolator=GenericVectorInterpolatorType::New();
+genericInterpolator->SetArgsInfo(m_ArgsInfo);
+typedef itk::VectorInterpolateImageFunction<InputImageType, double> InterpolatorType; 
+typename InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
+
+*/
+
+namespace clitk
+{
+  
+  template <class args_info_type,   class ImageType,  class TCoordRep >  
+  class GenericVectorInterpolator : public itk::LightObject
+  {
+  public:
+    //==============================================
+    typedef GenericVectorInterpolator     Self;
+    typedef itk::LightObject     Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+
+    typedef itk::VectorInterpolateImageFunction<ImageType, TCoordRep> InterpolatorType;
+    typedef typename InterpolatorType::Pointer InterpolatorPointer;   
+     
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);  
+  
+    //============================================== 
+    //Set members
+    void SetArgsInfo(args_info_type args_info)
+    {
+      m_ArgsInfo= args_info;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+    }
+
+    //============================================== 
+    //Get members
+    InterpolatorPointer GetInterpolatorPointer(void);
+    
+    //==============================================
+  protected:
+    GenericVectorInterpolator();
+    ~GenericVectorInterpolator() {};
+
+  private:
+    args_info_type m_ArgsInfo;
+    InterpolatorPointer m_Interpolator;
+    bool m_Verbose;
+  };
+
+} // end namespace clitk
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkGenericVectorInterpolator.txx"
+#endif
+
+#endif // #define __clitkGenericVectorInterpolator_h
diff --git a/registration/clitkGenericVectorInterpolator.txx b/registration/clitkGenericVectorInterpolator.txx
new file mode 100755 (executable)
index 0000000..9fd6892
--- /dev/null
@@ -0,0 +1,90 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkGenericVectorInterpolator_txx   
+#define __clitkGenericVectorInterpolator_txx
+#include "clitkGenericVectorInterpolator.h"
+
+
+namespace clitk
+{
+
+  //=========================================================================================================================
+  //constructor
+  template <class args_info_type, class ImageType, class TCoordRep> 
+  GenericVectorInterpolator<args_info_type, ImageType, TCoordRep>::GenericVectorInterpolator()
+  {
+    m_Interpolator=NULL;
+    m_Verbose=false;
+  }
+  
+  
+  //=========================================================================================================================
+  //Get the pointer
+  template <class args_info_type, class ImageType, class TCoordRep> 
+  typename GenericVectorInterpolator<args_info_type, ImageType, TCoordRep>::InterpolatorPointer 
+  GenericVectorInterpolator<args_info_type, ImageType, TCoordRep>::GetInterpolatorPointer()
+  {
+    //============================================================================
+    // We retrieve the type of interpolation from the command line
+    //============================================================================
+    typename InterpolatorType::Pointer interpolator;  
+  
+    switch ( m_ArgsInfo.interpVF_arg )
+      {
+      case 0: 
+
+       interpolator= itk::VectorNearestNeighborInterpolateImageFunction< ImageType,TCoordRep >::New();
+       if (m_Verbose) std::cout<<"Using nearestneighbor interpolation..."<<std::endl;
+       break;
+      case 1:
+
+       interpolator = itk::VectorLinearInterpolateImageFunction< ImageType,TCoordRep >::New();
+       if (m_Verbose) std::cout<<"Using linear interpolation..."<<std::endl;
+       break;  
+      
+      case 2:
+       {
+         typename clitk::VectorBSplineInterpolateImageFunction< ImageType,TCoordRep >::Pointer m =clitk::VectorBSplineInterpolateImageFunction< ImageType,TCoordRep >::New();
+         m->SetSplineOrder(m_ArgsInfo.interpVFOrder_arg);
+         interpolator=m;
+         if (m_Verbose) std::cout<<"Using Bspline interpolation..."<<std::endl;
+         break; 
+       }
+       
+      case 3:
+       {
+         typename clitk::VectorBSplineInterpolateImageFunctionWithLUT< ImageType,TCoordRep >::Pointer m =clitk::VectorBSplineInterpolateImageFunctionWithLUT< ImageType,TCoordRep >::New();
+         m->SetSplineOrder(m_ArgsInfo.interpVFOrder_arg);
+         m->SetLUTSamplingFactor(m_ArgsInfo.interpVFSF_arg);
+         interpolator=m;
+         if (m_Verbose) std::cout<<"Using BLUT interpolation..."<<std::endl;
+         break;
+       } 
+
+      }//end of switch
+    
+    
+    //============================================================================
+    //return the pointer
+    return interpolator;
+  }
+  
+}
+
+#endif
index 8767eae4be7d3f1012b4e4860ff347fe0e895326..be859d809763a8853fd9e02562f0aa1ba4a05fc0 100644 (file)
@@ -1,7 +1,7 @@
 /*=========================================================================
   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
 
-  Authors belong to:
+  Authors belong to: 
   - University of LYON              http://www.universite-lyon.fr/
   - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
   - BSD        See included LICENSE.txt file
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
 ======================================================================-====*/
-
-/*=========================================================================
-
-  Program:   Insight Segmentation & Registration Toolkit
-  Module:    $RCSfile: clitkLBFGSBOptimizer.cxx,v $
-  Language:  C++
-  Date:      $Date: 2010/06/14 17:32:06 $
-  Version:   $Revision: 1.1 $
-
-  Copyright (c) Insight Software Consortium. All rights reserved.
-  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
-
-     This software is distributed WITHOUT ANY WARRANTY; without even
-     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-     PURPOSE.  See the above copyright notices for more information.
-
-=========================================================================*/
 #ifndef __clitkLBFGSBOptimizer_cxx
 #define __clitkLBFGSBOptimizer_cxx
-
 #include "clitkLBFGSBOptimizer.h"
 #include "vnl/algo/vnl_lbfgsb.h"
 #include <vnl/vnl_math.h>
 
+extern "C" {
+  extern double v3p_netlib_dpmeps_();
+}
 
 namespace clitk
 {
@@ -51,7 +36,7 @@ namespace clitk
  * vnl_lbfgsb into iteration events in ITK.
  */
 class ITK_EXPORT LBFGSBOptimizerHelper :
-  public vnl_lbfgsb
+    public vnl_lbfgsb
 {
 public:
   typedef LBFGSBOptimizerHelper               Self;
@@ -68,7 +53,7 @@ private:
   LBFGSBOptimizer* m_ItkObj;
 };
 
-
+  
 
 
 /**
@@ -81,7 +66,7 @@ LBFGSBOptimizer
   m_VnlOptimizer         = 0;
 
   m_LowerBound       = InternalBoundValueType(0);
-  m_UpperBound       = InternalBoundValueType(0);
+  m_UpperBound       = InternalBoundValueType(0); 
   m_BoundSelection   = InternalBoundSelectionType(0);
 
   m_CostFunctionConvergenceFactor   = 1e+7;
@@ -92,7 +77,8 @@ LBFGSBOptimizer
   m_CurrentIteration                = 0;
   m_Value                           = 0.0;
   m_InfinityNormOfProjectedGradient = 0.0;
-
+  m_StopConditionDescription.str("");
 }
 
 
@@ -111,41 +97,42 @@ LBFGSBOptimizer
 void
 LBFGSBOptimizer
 ::PrintSelf( std::ostream& os, itk::Indent indent) const
-{
+{  
   Superclass::PrintSelf(os, indent);
 
   os << indent << "LowerBound: " << m_LowerBound << std::endl;
   os << indent << "UpperBound: " << m_UpperBound << std::endl;
   os << indent << "BoundSelection: " << m_BoundSelection << std::endl;
 
-  os << indent << "CostFunctionConvergenceFactor: " <<
-     m_CostFunctionConvergenceFactor << std::endl;
+  os << indent << "CostFunctionConvergenceFactor: " << 
+    m_CostFunctionConvergenceFactor << std::endl;
 
   os << indent << "ProjectedGradientTolerance: " <<
-     m_ProjectedGradientTolerance << std::endl;
+    m_ProjectedGradientTolerance << std::endl;
 
   os << indent << "MaximumNumberOfIterations: " <<
-     m_MaximumNumberOfIterations << std::endl;
+    m_MaximumNumberOfIterations << std::endl;
 
   os << indent << "MaximumNumberOfEvaluations: " <<
-     m_MaximumNumberOfEvaluations << std::endl;
+    m_MaximumNumberOfEvaluations << std::endl;
 
-  os << indent << "MaximumNumberOfCorrections: " <<
-     m_MaximumNumberOfCorrections << std::endl;
+  os << indent << "MaximumNumberOfCorrections: " << 
+    m_MaximumNumberOfCorrections << std::endl;
 
-  os << indent << "CurrentIteration: " <<
-     m_CurrentIteration << std::endl;
+  os << indent << "CurrentIteration: " << 
+    m_CurrentIteration << std::endl;
 
   os << indent << "Value: " <<
-     m_Value << std::endl;
+    m_Value << std::endl;
 
   os << indent << "InfinityNormOfProjectedGradient: " <<
-     m_InfinityNormOfProjectedGradient << std::endl;
+    m_InfinityNormOfProjectedGradient << std::endl;
 
-  if( this->m_VnlOptimizer ) {
-    os << indent << "Vnl LBFGSB Failure Code: " <<
-       this->m_VnlOptimizer->get_failure_code() << std::endl;
-  }
+  if( this->m_VnlOptimizer )
+    {
+    os << indent << "Vnl LBFGSB Failure Code: " << 
+      this->m_VnlOptimizer->get_failure_code() << std::endl;
+    }
 }
 
 /**
@@ -154,12 +141,13 @@ LBFGSBOptimizer
 void
 LBFGSBOptimizer
 ::SetLowerBound(
-  const BoundValueType& value )
+const BoundValueType& value )
 {
   m_LowerBound = value;
-  if( m_OptimizerInitialized ) {
+  if( m_OptimizerInitialized )
+    {
     m_VnlOptimizer->set_lower_bound( m_LowerBound );
-  }
+    }
 
   this->Modified();
 }
@@ -168,13 +156,13 @@ LBFGSBOptimizer
  * Get lower bound
  */
 const
-LBFGSBOptimizer
+LBFGSBOptimizer 
 ::BoundValueType &
 LBFGSBOptimizer
 ::GetLowerBound()
 {
   return m_LowerBound;
-}
+} 
 
 /**
  * Set upper bound
@@ -182,12 +170,13 @@ LBFGSBOptimizer
 void
 LBFGSBOptimizer
 ::SetUpperBound(
-  const BoundValueType& value )
+const BoundValueType& value )
 {
   m_UpperBound = value;
-  if( m_OptimizerInitialized ) {
+  if( m_OptimizerInitialized )
+    {
     m_VnlOptimizer->set_upper_bound( m_UpperBound );
-  }
+    }
 
   this->Modified();
 }
@@ -196,13 +185,13 @@ LBFGSBOptimizer
  * Get upper bound
  */
 const
-LBFGSBOptimizer
+LBFGSBOptimizer 
 ::BoundValueType &
 LBFGSBOptimizer
 ::GetUpperBound()
 {
   return m_UpperBound;
-}
+} 
 
 
 /**
@@ -211,12 +200,13 @@ LBFGSBOptimizer
 void
 LBFGSBOptimizer
 ::SetBoundSelection(
-  const BoundSelectionType& value )
+const BoundSelectionType& value )
 {
   m_BoundSelection = value;
-  if( m_OptimizerInitialized ) {
+  if( m_OptimizerInitialized )
+    {
     m_VnlOptimizer->set_bound_selection( m_BoundSelection );
-  }
+    }
   this->Modified();
 }
 
@@ -224,35 +214,37 @@ LBFGSBOptimizer
  * Get bound selection array
  */
 const
-LBFGSBOptimizer
+LBFGSBOptimizer 
 ::BoundSelectionType &
 LBFGSBOptimizer
 ::GetBoundSelection()
 {
   return m_BoundSelection;
-}
+} 
 
 
 /** Set/Get the CostFunctionConvergenceFactor. Algorithm terminates
  * when the reduction in cost function is less than factor * epsmcj
  * where epsmch is the machine precision.
- * Typical values for factor: 1e+12 for low accuracy;
+ * Typical values for factor: 1e+12 for low accuracy; 
  * 1e+7 for moderate accuracy and 1e+1 for extremely high accuracy.
  */
 void
 LBFGSBOptimizer
 ::SetCostFunctionConvergenceFactor( double value )
 {
-  if( value < 1.0 ) {
-    itkExceptionMacro("Value " << value
-                      << " is too small for SetCostFunctionConvergenceFactor()"
-                      << "a typical range would be from 1.0 to 1e+12");
-  }
+  if( value < 1.0 )
+    {
+    itkExceptionMacro("Value " << value 
+      << " is too small for SetCostFunctionConvergenceFactor()"
+      << "a typical range would be from 1.0 to 1e+12");
+    }
   m_CostFunctionConvergenceFactor = value;
-  if( m_OptimizerInitialized ) {
+  if( m_OptimizerInitialized )
+    {
     m_VnlOptimizer->set_cost_function_convergence_factor(
       m_CostFunctionConvergenceFactor );
-  }
+    }
   this->Modified();
 }
 
@@ -266,10 +258,11 @@ LBFGSBOptimizer
 ::SetProjectedGradientTolerance( double value )
 {
   m_ProjectedGradientTolerance = value;
-  if( m_OptimizerInitialized ) {
+  if( m_OptimizerInitialized )
+    {
     m_VnlOptimizer->set_projected_gradient_tolerance(
       m_ProjectedGradientTolerance );
-  }
+    }
   this->Modified();
 }
 
@@ -290,9 +283,10 @@ LBFGSBOptimizer
 ::SetMaximumNumberOfEvaluations( unsigned int value )
 {
   m_MaximumNumberOfEvaluations = value;
-  if( m_OptimizerInitialized ) {
+  if( m_OptimizerInitialized )
+    {
     m_VnlOptimizer->set_max_function_evals( m_MaximumNumberOfEvaluations );
-  }
+    }
   this->Modified();
 }
 
@@ -303,10 +297,11 @@ LBFGSBOptimizer
 ::SetMaximumNumberOfCorrections( unsigned int value )
 {
   m_MaximumNumberOfCorrections = value;
-  if( m_OptimizerInitialized ) {
+  if( m_OptimizerInitialized )
+    {
     m_VnlOptimizer->set_max_variable_metric_corrections(
       m_MaximumNumberOfCorrections );
-  }
+    }
   this->Modified();
 }
 
@@ -320,18 +315,19 @@ SetCostFunction( itk::SingleValuedCostFunction * costFunction )
 {
   m_CostFunction = costFunction;
 
-  const unsigned int numberOfParameters =
+  const unsigned int numberOfParameters = 
     costFunction->GetNumberOfParameters();
 
-  CostFunctionAdaptorType * adaptor =
+  CostFunctionAdaptorType * adaptor = 
     new CostFunctionAdaptorType( numberOfParameters );
-
+       
   adaptor->SetCostFunction( costFunction );
 
-  if( m_OptimizerInitialized ) {
+  if( m_OptimizerInitialized )
+    { 
     delete m_VnlOptimizer;
-  }
-
+    }
+    
   this->SetCostFunctionAdaptor( adaptor );
 
   m_VnlOptimizer = new InternalOptimizerType( *adaptor, this );
@@ -342,7 +338,7 @@ SetCostFunction( itk::SingleValuedCostFunction * costFunction )
   m_VnlOptimizer->set_bound_selection( m_BoundSelection );
   m_VnlOptimizer->set_cost_function_convergence_factor(
     m_CostFunctionConvergenceFactor );
-  m_VnlOptimizer->set_projected_gradient_tolerance(
+  m_VnlOptimizer->set_projected_gradient_tolerance( 
     m_ProjectedGradientTolerance );
   m_VnlOptimizer->set_max_function_evals( m_MaximumNumberOfEvaluations );
   m_VnlOptimizer->set_max_variable_metric_corrections(
@@ -361,43 +357,52 @@ void
 LBFGSBOptimizer
 ::StartOptimization( void )
 {
-
+  
   // Check if all the bounds parameters are the same size as the initial parameters.
   unsigned int numberOfParameters = m_CostFunction->GetNumberOfParameters();
 
-  if ( this->GetInitialPosition().Size() < numberOfParameters ) {
+  if ( this->GetInitialPosition().Size() < numberOfParameters )
+    {
     itkExceptionMacro( << "InitialPosition array does not have sufficient number of elements" );
-  }
+    }
 
-  if ( m_LowerBound.size() < numberOfParameters ) {
+  if ( m_LowerBound.size() < numberOfParameters )
+    {
     itkExceptionMacro( << "LowerBound array does not have sufficient number of elements" );
-  }
+    }
 
-  if ( m_UpperBound.size() < numberOfParameters ) {
+  if ( m_UpperBound.size() < numberOfParameters )
+    {
     itkExceptionMacro( << "UppperBound array does not have sufficient number of elements" );
-  }
+    }
 
-  if ( m_BoundSelection.size() < numberOfParameters ) {
+  if ( m_BoundSelection.size() < numberOfParameters )
+    {
     itkExceptionMacro( << "BoundSelection array does not have sufficient number of elements" );
-  }
+    }
 
-  if( this->GetMaximize() ) {
+  if( this->GetMaximize() )
+    {
     this->GetNonConstCostFunctionAdaptor()->NegateCostFunctionOn();
-  }
+    }
 
   this->SetCurrentPosition( this->GetInitialPosition() );
 
   ParametersType parameters( this->GetInitialPosition() );
 
-  // vnl optimizers return the solution by reference
+  // Clear the description
+  m_StopConditionDescription.str("");
+
+  // vnl optimizers return the solution by reference 
   // in the variable provided as initial position
   m_VnlOptimizer->minimize( parameters );
 
-  if ( parameters.size() != this->GetInitialPosition().Size() ) {
+  if ( parameters.size() != this->GetInitialPosition().Size() )
+    {
     // set current position to initial position and throw an exception
     this->SetCurrentPosition( this->GetInitialPosition() );
     itkExceptionMacro( << "Error occured in optimization" );
-  }
+    }
 
   this->SetCurrentPosition( parameters );
 
@@ -440,13 +445,81 @@ LBFGSBOptimizerHelper
 
 
   // Return true to terminate the optimization loop.
-  if( this->num_iterations_ > m_ItkObj->m_MaximumNumberOfIterations ) {
+  if( this->num_iterations_ > m_ItkObj->m_MaximumNumberOfIterations )
+    {
+    m_ItkObj->m_StopConditionDescription <<
+      "Too many iterations. Iterations = " <<
+      m_ItkObj->m_MaximumNumberOfIterations;
     return true;
-  } else {
+    }
+  else
+    {
     return false;
-  }
+    }
 }
 
+const std::string
+LBFGSBOptimizer::
+GetStopConditionDescription() const
+{
+  if (m_VnlOptimizer)
+    {
+    m_StopConditionDescription.str("");
+    m_StopConditionDescription << this->GetNameOfClass() << ": ";
+    switch (m_VnlOptimizer->get_failure_code())
+      {
+      case vnl_nonlinear_minimizer::ERROR_FAILURE:
+        m_StopConditionDescription << "Failure";
+        break;
+      case vnl_nonlinear_minimizer::ERROR_DODGY_INPUT:
+        m_StopConditionDescription << "Dodgy input";
+        break;
+      case vnl_nonlinear_minimizer::CONVERGED_FTOL:
+        m_StopConditionDescription << "Function tolerance reached after "
+                                   << m_CurrentIteration
+                                   << " iterations. "
+                                   << "The relative reduction of the cost function <= "
+                                   << m_CostFunctionConvergenceFactor * v3p_netlib_dpmeps_()
+                                   << " = CostFunctionConvergenceFactor ("
+                                   << m_CostFunctionConvergenceFactor
+                                   << ") * machine precision ("
+                                   << v3p_netlib_dpmeps_()
+                                   << ").";
+        break;
+      case vnl_nonlinear_minimizer::CONVERGED_XTOL:
+        m_StopConditionDescription << "Solution tolerance reached";
+        break;
+      case vnl_nonlinear_minimizer::CONVERGED_XFTOL:
+        m_StopConditionDescription << "Solution and Function tolerance both reached";
+        break;
+      case vnl_nonlinear_minimizer::CONVERGED_GTOL:
+        m_StopConditionDescription << "Gradient tolerance reached. "
+                                   << "Projected gradient tolerance is "
+                                   << m_ProjectedGradientTolerance;
+        break;
+      case vnl_nonlinear_minimizer::FAILED_TOO_MANY_ITERATIONS:
+        m_StopConditionDescription << "Too many iterations. Iterations = "
+                                   << m_MaximumNumberOfEvaluations;
+        break;
+      case vnl_nonlinear_minimizer::FAILED_FTOL_TOO_SMALL:
+        m_StopConditionDescription << "Function tolerance too small";
+        break;
+      case vnl_nonlinear_minimizer::FAILED_XTOL_TOO_SMALL:
+        m_StopConditionDescription << "Solution tolerance too small";
+        break;
+      case vnl_nonlinear_minimizer::FAILED_GTOL_TOO_SMALL:
+        m_StopConditionDescription << "Gradient tolerance too small";
+        break;
+      case vnl_nonlinear_minimizer::FAILED_USER_REQUEST:
+        break;
+      }
+    return m_StopConditionDescription.str();
+    }
+  else
+    {
+    return std::string("");
+    }
+}
 
 } // end namespace clitk
 
index 5485b7652b9b334218210727ce2007765019954c..cfc8007d54631528368865f2e2298bdef53fefea 100644 (file)
@@ -1,7 +1,7 @@
 /*=========================================================================
   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
 
-  Authors belong to:
+  Authors belong to: 
   - University of LYON              http://www.universite-lyon.fr/
   - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
   - BSD        See included LICENSE.txt file
   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
 ======================================================================-====*/
-
-/*=========================================================================
-
-  Program:   Insight Segmentation & Registration Toolkit
-  Module:    $RCSfile: clitkLBFGSBOptimizer.h,v $
-  Language:  C++
-  Date:      $Date: 2010/06/14 17:32:07 $
-  Version:   $Revision: 1.1 $
-
-  Copyright (c) Insight Software Consortium. All rights reserved.
-  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
-
-     This software is distributed WITHOUT ANY WARRANTY; without even
-     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-     PURPOSE.  See the above copyright notices for more information.
-
-=========================================================================*/
 #ifndef __clitkLBFGSBOptimizer_h
 #define __clitkLBFGSBOptimizer_h
-
 #include "itkSingleValuedNonLinearVnlOptimizer.h"
 
 namespace clitk
@@ -61,21 +43,21 @@ class ITK_EXPORT LBFGSBOptimizerHelper;
  *
  * References:
  *
- * [1] R. H. Byrd, P. Lu and J. Nocedal.
- * A Limited Memory Algorithm for Bound Constrained Optimization, (1995),
- * SIAM Journal on Scientific and Statistical Computing ,
- * 16, 5, pp. 1190-1208.
+ * [1] R. H. Byrd, P. Lu and J. Nocedal. 
+ * A Limited Memory Algorithm for Bound Constrained Optimization, (1995), 
+ * SIAM Journal on Scientific and Statistical Computing , 
+ * 16, 5, pp. 1190-1208. 
  *
- * [2] C. Zhu, R. H. Byrd and J. Nocedal.
- * L-BFGS-B: Algorithm 778: L-BFGS-B, FORTRAN routines for large scale
- * bound constrained optimization (1997),
- * ACM Transactions on Mathematical Software,
- * Vol 23, Num. 4, pp. 550 - 560.
+ * [2] C. Zhu, R. H. Byrd and J. Nocedal. 
+ * L-BFGS-B: Algorithm 778: L-BFGS-B, FORTRAN routines for large scale 
+ * bound constrained optimization (1997), 
+ * ACM Transactions on Mathematical Software, 
+ * Vol 23, Num. 4, pp. 550 - 560. 
  *
  * \ingroup Numerics Optimizers
  */
-class ITK_EXPORT LBFGSBOptimizer :
-  public itk::SingleValuedNonLinearVnlOptimizer
+class ITK_EXPORT LBFGSBOptimizer : 
+    public itk::SingleValuedNonLinearVnlOptimizer
 {
 public:
   /** Standard "Self" typedef. */
@@ -83,7 +65,7 @@ public:
   typedef itk::SingleValuedNonLinearVnlOptimizer   Superclass;
   typedef itk::SmartPointer<Self>                  Pointer;
   typedef itk::SmartPointer<const Self>            ConstPointer;
-
+  
   /** Method for creation through the object factory. */
   itkNewMacro(Self);
 
@@ -91,12 +73,12 @@ public:
   itkTypeMacro( LBFGSBOptimizer, SingleValuedNonLinearVnlOptimizer );
 
   /**  BoundValue type.
-   *  Use for defining the lower and upper bounds on the variables.
+   *  Use for defining the lower and upper bounds on the variables. 
    */
   typedef itk::Array<double>             BoundValueType;
 
   /** BoundSelection type
-   * Use for defining the boundary condition for each variables.
+   * Use for defining the boundary condition for each variables. 
    */
   typedef itk::Array<long>                BoundSelectionType;
 
@@ -136,7 +118,7 @@ public:
   /** Set/Get the CostFunctionConvergenceFactor. Algorithm terminates
    * when the reduction in cost function is less than factor * epsmcj
    * where epsmch is the machine precision.
-   * Typical values for factor: 1e+12 for low accuracy;
+   * Typical values for factor: 1e+12 for low accuracy; 
    * 1e+7 for moderate accuracy and 1e+1 for extremely high accuracy.
    */
   virtual void SetCostFunctionConvergenceFactor( double );
@@ -162,9 +144,10 @@ public:
   itkGetMacro( MaximumNumberOfCorrections, unsigned int );
 
   /** This optimizer does not support scaling of the derivatives. */
-  void SetScales( const ScalesType & ) {
+  void SetScales( const ScalesType & )
+    {
     itkExceptionMacro( << "This optimizer does not support scales." );
-  }
+    }
 
   /** Get the current iteration number. */
   itkGetConstReferenceMacro( CurrentIteration, unsigned int );
@@ -176,6 +159,9 @@ public:
    * function. */
   itkGetConstReferenceMacro( InfinityNormOfProjectedGradient, double );
 
+  /** Get the reason for termination */
+  const std::string GetStopConditionDescription() const;
+
 protected:
   LBFGSBOptimizer();
   virtual ~LBFGSBOptimizer();
@@ -193,7 +179,7 @@ private:
 
   bool                     m_OptimizerInitialized;
   InternalOptimizerType  * m_VnlOptimizer;
-
+  mutable itk::OStringStream    m_StopConditionDescription;
   BoundValueType           m_LowerBound;
   BoundValueType           m_UpperBound;
   BoundSelectionType       m_BoundSelection;
diff --git a/registration/clitkLinearCombinationImageFilter.h b/registration/clitkLinearCombinationImageFilter.h
new file mode 100644 (file)
index 0000000..eaa16dd
--- /dev/null
@@ -0,0 +1,94 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __itkLinearCombinationImageFilter_h
+#define __itkLinearCombinationImageFilter_h
+#include "itkImageToImageFilter.h"
+#include "itkNumericTraits.h"
+
+
+namespace clitk
+{
+  
+
+  template <class TInputImage, class TOutputImage>
+  class ITK_EXPORT LinearCombinationImageFilter :
+    public    itk::ImageToImageFilter<TInputImage, TOutputImage >
+  {
+  public:
+    //-----------------------------------
+    /** Standard class typedefs. */
+    //-----------------------------------
+    typedef LinearCombinationImageFilter                      Self;
+    typedef itk::ImageToImageFilter<TInputImage,TOutputImage> Superclass;
+    typedef itk::SmartPointer<Self>                           Pointer;
+    typedef itk::SmartPointer<const Self>                     ConstPointer;
+
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self);
+    
+    /** Runtime information support. */
+    itkTypeMacro(LinearCombinationImageFilter, ImageToImageFilter);
+    
+    //-----------------------------------
+    //Typedefs
+    //-----------------------------------
+    typedef typename TInputImage::Pointer InputPointer;
+    typedef typename TInputImage::ConstPointer InputConstPointer;
+    typedef typename TInputImage::PixelType InputPixelType;
+    
+    typedef typename TOutputImage::Pointer OutputPointer;
+    typedef typename TOutputImage::PixelType OutputPixelType;
+    typedef typename TOutputImage::RegionType OutputImageRegionType;
+    //-----------------------------------
+    //Set/Get
+    //----------------------------------
+    void SetFirstInput (const InputPointer i);
+    void SetFirstInput ( const InputConstPointer i);
+    void SetSecondInput (const InputPointer i);
+    void SetSecondInput (const InputConstPointer i);
+
+    itkSetMacro(A, double);
+    itkGetMacro(A, double);
+    itkSetMacro(B, double);
+    itkGetMacro(B, double);
+    itkSetMacro(C, double);
+    itkGetMacro(C, double);
+
+  protected:
+    LinearCombinationImageFilter();
+    virtual ~LinearCombinationImageFilter(){};
+
+    virtual void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, int threadId);
+    
+  private:
+    LinearCombinationImageFilter(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+    
+    double m_A;
+    double m_B;
+    double m_C;
+    
+  };
+  
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkLinearCombinationImageFilter.txx"
+#endif
+
+#endif
diff --git a/registration/clitkLinearCombinationImageFilter.txx b/registration/clitkLinearCombinationImageFilter.txx
new file mode 100644 (file)
index 0000000..b2ec7d9
--- /dev/null
@@ -0,0 +1,210 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkLinearCombinationImageFilter_txx
+#define __clitkLinearCombinationImageFilter_txx
+#include "clitkLinearCombinationImageFilter.h"
+
+
+namespace clitk
+{
+
+  //=========================================================================================================================
+  // LinearCombinationImageFilter
+  //=========================================================================================================================
+
+  //=========================================================================================================================
+  //constructor
+  template <class InputImageType, class OutputImageType> 
+  LinearCombinationImageFilter<InputImageType, OutputImageType>
+  ::LinearCombinationImageFilter()
+  {
+    this->SetNumberOfRequiredInputs(2);
+    m_A=1.;
+    m_B=1.;
+    m_C=0.;
+    
+  }
+
+  //=========================================================================================================================
+  //set input
+  template <class InputImageType, class OutputImageType> 
+  void LinearCombinationImageFilter<InputImageType, OutputImageType>::SetFirstInput(const typename InputImageType::Pointer input)
+  {
+    this->SetInput(0,input);
+  }
+  template <class InputImageType, class OutputImageType> 
+  void LinearCombinationImageFilter<InputImageType, OutputImageType>::SetSecondInput(const typename InputImageType::Pointer input)
+  {
+    this->SetInput(1,input);
+  }
+
+
+  template <class InputImageType, class OutputImageType> 
+  void LinearCombinationImageFilter<InputImageType, OutputImageType>::SetFirstInput(const typename InputImageType::ConstPointer input)
+  {
+    this->SetInput(0,input);
+  }
+  template <class InputImageType, class OutputImageType> 
+  void LinearCombinationImageFilter<InputImageType, OutputImageType>::SetSecondInput(const typename InputImageType::ConstPointer input)
+  {
+    this->SetInput(1,input);
+  }
+
+
+  //=========================================================================================================================
+  //Update
+  template <class InputImageType, class OutputImageType> 
+  void 
+  LinearCombinationImageFilter<InputImageType, OutputImageType>
+  ::ThreadedGenerateData(const OutputImageRegionType &threadRegion, int threadId)
+  {
+    //Pointers to input and output
+    typename InputImageType::ConstPointer input1=this->GetInput(0);
+    typename InputImageType::ConstPointer input2=this->GetInput(1);
+    typename OutputImageType::Pointer output=this->GetOutput();
+
+    //Iterator over input1, input0 and output
+    typedef itk::ImageRegionConstIterator<InputImageType> InputIteratortype;
+    typedef itk::ImageRegionIterator<OutputImageType> OutputIteratortype;
+    InputIteratortype input1Iterator (input1, threadRegion);
+    InputIteratortype input2Iterator (input2, threadRegion);
+    OutputIteratortype outputIterator (output, threadRegion);
+    input1Iterator.GoToBegin();
+    input2Iterator.GoToBegin();
+    outputIterator.GoToBegin();
+
+    //Find which coefficient should be applied
+
+    if (m_C==0.)
+      {
+       if (m_B==1.)
+         {
+           if (m_A==1.)
+             {
+               while (!outputIterator.IsAtEnd())
+                 {
+                   // outputIterator.Set(static_cast<OutputPixelType>(input1Iterator.Get()+input2Iterator.Get()));
+                   outputIterator.Set(input1Iterator.Get()+input2Iterator.Get());
+                   ++input1Iterator;
+                   ++input2Iterator;
+                   ++outputIterator;    
+                 }
+             }
+           else 
+             {
+               while (!outputIterator.IsAtEnd())
+                 {
+                   // outputIterator.Set(static_cast<OutputPixelType>(m_A* input1Iterator.Get()+input2Iterator.Get()));
+                   outputIterator.Set(m_A* input1Iterator.Get()+input2Iterator.Get());
+                   ++input1Iterator;
+                   ++input2Iterator;
+                   ++outputIterator;    
+                 }
+             }
+         }
+       // case B not 1
+       else
+         {
+           if (m_A==1.)
+             {
+               
+               while (!outputIterator.IsAtEnd())
+                 {
+                   //outputIterator.Set(static_cast<OutputPixelType>(input1Iterator.Get()+m_B *input2Iterator.Get()));
+                   outputIterator.Set(input1Iterator.Get()+m_B *input2Iterator.Get());
+                   ++input1Iterator;
+                   ++input2Iterator;
+                   ++outputIterator;    
+                 }
+             }
+           else 
+             {
+               while (!outputIterator.IsAtEnd())
+                 {
+                   //outputIterator.Set(static_cast<OutputPixelType>(m_A* input1Iterator.Get()+ m_B*input2Iterator.Get()));
+                   outputIterator.Set(m_A* input1Iterator.Get()+ m_B*input2Iterator.Get());
+                   ++input1Iterator;
+                   ++input2Iterator;
+                   ++outputIterator;    
+                 }
+             }
+         }
+
+      }
+
+    //Case C not 0
+    else
+      {
+       if (m_B==1.)
+         {
+           if (m_A==1.)
+             {
+               
+               while (!outputIterator.IsAtEnd())
+                 {
+                   outputIterator.Set(static_cast<OutputPixelType>(input1Iterator.Get()+input2Iterator.Get())+ m_C);
+                   ++input1Iterator;
+                   ++input2Iterator;
+                   ++outputIterator;    
+                 }
+             }
+           else 
+             {
+               while (!outputIterator.IsAtEnd())
+                 {
+                   outputIterator.Set(static_cast<OutputPixelType>(m_A* input1Iterator.Get()+input2Iterator.Get()+ m_C) );
+                   ++input1Iterator;
+                   ++input2Iterator;
+                   ++outputIterator;    
+                 }
+             }
+         }
+       // case B not 1
+       else
+         {
+           if (m_A==1.)
+             {
+             
+               while (!outputIterator.IsAtEnd())
+                 {
+                   outputIterator.Set(static_cast<OutputPixelType>(input1Iterator.Get()+m_B *input2Iterator.Get()+ m_C) );
+                   ++input1Iterator;
+                   ++input2Iterator;
+                   ++outputIterator;    
+                 }
+             }
+           else 
+             {
+               while (!outputIterator.IsAtEnd())
+                 {
+                   outputIterator.Set(static_cast<OutputPixelType>(m_A* input1Iterator.Get()+ m_B*input2Iterator.Get()+ m_C) );
+                   ++input1Iterator;
+                   ++input2Iterator;
+                   ++outputIterator;    
+                 }
+             }
+         }
+      }
+
+  }
+
+}// end of namespace clitk
+
+  
+
+#endif
diff --git a/registration/clitkList.h b/registration/clitkList.h
new file mode 100644 (file)
index 0000000..c98ecc5
--- /dev/null
@@ -0,0 +1,85 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef CLITKLIST_H
+#define CLITKLIST_H
+/**
+   =================================================
+   * @file   clitkList.h
+   * @author Jef Vandemeulebroucke <jef@creatis.insa-lyon.fr>
+   * @date   30 April 2008
+   * 
+   * @brief 
+   * 
+   =================================================*/
+
+#include "clitkCommon.h"
+#include "clitkIO.h"
+
+// itk include
+#include "itkLightObject.h"
+
+using namespace std;
+
+namespace clitk{
+
+  template <class ListItemType > 
+  class List: public std::vector<ListItemType >
+  {
+
+  public:
+    //=====================================================================================
+    //Typedefs
+    typedef typename ListItemType::ValueType ValueType;
+    itkStaticConstMacro(Dimension, unsigned int, ListItemType::Dimension);
+    typedef List<ListItemType> ListType;
+    typedef itk::ContinuousIndex<ValueType, Dimension> IndexType;
+    typedef itk::Image<signed short, Dimension> ImageType;
+
+    //=====================================================================================  
+    // IO
+    void Read(const string& fileName, bool verbose=false);
+    void ReadAndConvertPointPairs(const string& fileName, List& correspList, const typename ImageType::Pointer referenceImage , bool verbose=false);
+    bool ReadPointPair(const string& fileName, const unsigned int& pointNumber, IndexType& item1, IndexType& item2, bool& veryUnsure);
+    void Write(const string fileName, const bool verbose);
+    void Print();
+  
+    //=====================================================================================
+    // Members
+    List<itk::FixedArray<double, 1> > Norm(void);
+
+    //=====================================================================================
+    //Constructors - Destructors
+    List(){};
+    List(const string fileName, bool verbose=false ){Read(fileName, verbose);}
+    List(unsigned int size) { this->resize(size); };
+    ~List(){};
+
+  protected:
+
+
+  };
+
+
+} // namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkList.txx"
+#endif
+
+#endif
+
diff --git a/registration/clitkList.txx b/registration/clitkList.txx
new file mode 100644 (file)
index 0000000..208a4c5
--- /dev/null
@@ -0,0 +1,363 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef CLITKLIST_TXX
+#define CLITKLIST_TXX
+#include "clitkList.h"
+
+using namespace std; 
+
+namespace clitk 
+{
+  
+
+  //---------------------------------------------------------------------
+  // Read
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  void List< ListItemType>::Read(const string& filename, bool verbose)
+  {
+    std::ifstream is;
+    openFileForReading(is, filename);
+
+    this->resize(0);
+    ListItemType item;
+    ValueType x;
+   
+    if(verbose)std::cout<<"Reading "<<filename<<"..."<<std::endl;
+    for (unsigned int dim=0; dim<Dimension; dim++)
+      {
+       skipComment(is);
+       is >> x;
+       item[dim]=x;
+      }
+   
+    while (!is.eof()) 
+      {
+       this->push_back(item);
+       for (unsigned int dim=0; dim<Dimension; dim++)
+         {
+           skipComment(is);
+           is >> x;
+           item[dim]=x;
+         }
+      }
+  }
+
+
+  //---------------------------------------------------------------------
+  // ReadPointPairs (specific for DARS- IX point list format)
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  void 
+  List<ListItemType>::ReadAndConvertPointPairs(const std::string& fileName, List& correspList, const typename ImageType::Pointer referenceImage, bool verbose)
+  {
+    // Init
+    this->resize(0);
+    correspList.resize(0);
+
+    // Tags
+    IndexType item1, item2;
+    itk::Point<ValueType, Dimension> point1,point2;
+    unsigned int pointNumber=0;
+    bool veryUnsure=false;
+
+    // Read first point
+    bool pointWasFound=ReadPointPair(fileName, pointNumber, item1, item2, veryUnsure);
+
+    // Loop over all points 
+    while (pointWasFound)
+      {
+       // Store the values
+       if(veryUnsure)
+         {
+           if (verbose) std::cout<<"Omitting item "<<pointNumber<<" (very unsure): "<<item1<<" ; "<<item2<<std::endl;
+         }
+       else
+         {
+           if (verbose) std::cout<<"Adding item "<<pointNumber<<": "<<item1<<" ; "<<item2<<std::endl;
+           referenceImage->TransformContinuousIndexToPhysicalPoint(item1, point1);
+           referenceImage->TransformContinuousIndexToPhysicalPoint(item2, point2);
+           if (verbose) std::cout<<"Converted items "<<pointNumber<<" to points: "<<point1<<" ; "<<point2<<std::endl;
+           this->push_back(point1);
+           correspList.push_back(point2);
+         }
+
+       // Next point
+       pointNumber++;
+       pointWasFound=ReadPointPair(fileName, pointNumber, item1, item2, veryUnsure);
+      }
+  }
+  
+  //---------------------------------------------------------------------
+  // Read one point
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  bool
+  List< ListItemType>::ReadPointPair(const std::string& fileName, const unsigned int& pointNumber, IndexType& item1, IndexType& item2, bool& veryUnsure)
+  {
+    // bool
+    bool pointWasFound=false;
+    veryUnsure=false;
+    item1.Fill(0.0);
+    item2.Fill(0.0);
+    
+    // Open the file
+    ifstream listStream(fileName.c_str());
+    string line;
+    if(!listStream.is_open()){
+      std::cerr << "ERROR: Couldn't open file " << fileName << " in List::Read" << std::endl;
+      return false;
+    }
+    
+    // Skip the configuration lines
+    while ( !listStream.eof())
+      {
+       // Get the line
+       skipComment(listStream);
+       getline(listStream, line);
+       
+       // Get the line type
+       unsigned int endIndexItemType= line.find_first_of ("_",0)-1;
+       string typeString= line.substr(0 , endIndexItemType+1);
+       
+       // Check
+       if  (typeString=="Point")
+         break;
+      }
+
+    // Get the point number
+    unsigned int beginIndexItemNumber= line.find_first_of ("_",0)+1; 
+    unsigned int endIndexItemNumber= line.find_first_of ("->",0)-1;
+    stringstream numberString( line.substr(beginIndexItemNumber , endIndexItemNumber-beginIndexItemNumber+1) );
+    unsigned int itemNumber;
+    numberString>> itemNumber;
+
+    // FF to the pointNumber
+    while ( (itemNumber != pointNumber) && (!listStream.eof()) )
+      {
+       // Skipcomment
+       skipComment(listStream);
+       
+       // Get Line
+       getline(listStream, line);
+       
+       // Get the point number
+       beginIndexItemNumber= line.find_first_of ("_",0)+1; 
+       endIndexItemNumber= line.find_first_of ("->",0)-1;
+       stringstream numberString( line.substr(beginIndexItemNumber , endIndexItemNumber-beginIndexItemNumber+1) );
+       numberString>> itemNumber;
+      }
+    
+    // Go over all fields of the pointNumber
+    while (itemNumber == pointNumber && (!listStream.eof()) )
+      {
+       // point found
+       pointWasFound=true;
+
+       // Get the tag
+       unsigned int beginIndexItemTag= line.find_first_of ("->",0)+2; 
+       unsigned int endIndexItemTag= line.find_first_of ("=",0)-1;
+       string itemTag= line.substr(beginIndexItemTag , endIndexItemTag-beginIndexItemTag+1);
+       
+       // Get the point Value
+       unsigned int beginIndexItemValue= line.find_first_of ("=",0)+1; 
+       stringstream valueString( line.substr(beginIndexItemValue) );
+       double itemValue;
+       valueString>> itemValue;
+       
+       // Fill the items
+       if (itemTag=="X")
+         item1[0]=itemValue;
+       if (itemTag=="Y")
+         item1[1]=itemValue;
+       if (itemTag=="Z")
+         item1[2]=itemValue;
+       if (itemTag=="X_Corresp")
+         item2[0]=itemValue;
+       if (itemTag=="Y_Corresp")
+         item2[1]=itemValue;
+       if (itemTag=="Z_Corresp")
+         item2[2]=itemValue;
+       if (itemTag=="VeryUnsure")
+         veryUnsure=itemValue;
+       
+       // Get the next line
+       skipComment(listStream);
+       getline(listStream, line);
+       
+       // Get the point number
+       unsigned int beginIndexItemNumber= line.find_first_of ("_",0)+1; 
+       unsigned int endIndexItemNumber= line.find_first_of ("->",0)-1;
+       stringstream numberString( line.substr(beginIndexItemNumber , endIndexItemNumber-beginIndexItemNumber+1) );
+       numberString >> itemNumber;
+      }
+
+    return pointWasFound;
+  }
+
+
+ //---------------------------------------------------------------------
+  // Print
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  void List< ListItemType>::Print()
+  {
+    for (unsigned int i=0; i< this->size(); i++)
+      std::cout<<this->at(i)<<std::endl;
+  }
+
+
+  //---------------------------------------------------------------------
+  // Write
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  void List<ListItemType>::Write(const string fileName, const bool verbose)
+  {
+    ofstream listStream(fileName.c_str());
+    if(!listStream.is_open()){
+      cerr << "ERROR: Couldn't open file " << fileName << " in List::Write" << endl;
+      return;
+    }
+
+    typename ListType::iterator it=this->begin();
+    while(it!=this->end()) {
+      listStream << (*it)[0];
+      for (unsigned int i=1; i< this->at(0).Size(); i++)
+       listStream <<" "<< (*it)[i];
+      listStream<< endl;      
+      it++;
+    }
+    listStream.close();
+  }
+
+  //---------------------------------------------------------------------
+  // Norm
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  List<itk::FixedArray<double, 1> > List< ListItemType>::Norm()
+  {
+    List<itk::FixedArray<double, 1> > norm;
+    itk::FixedArray<double, 1> n;
+    unsigned int d;
+    for (unsigned int i=0; i< this->size(); i++)
+      {
+       n[0]=0;
+       for (d=0; d< Dimension; d++)
+         n[0]+=this->at(i)[d] * this->at(i)[d];
+       n[0]=sqrt(n[0]);
+       norm.push_back(n);
+      }
+    return norm;
+  }
+
+  
+
+}
+
+#endif //#define CLITKLIST
+
+
+    //    // Open the file
+    //     ifstream listStream(fileName.c_str());
+    //     ListItemType item;
+    //     string line;
+    //     if(!listStream.is_open()){
+    //       std::cerr << "ERROR: Couldn't open file " << fileName << " in List::Read" << std::endl;
+    //       return;
+    //     }
+    //     skipComment(listStream);
+    
+    //     // Skip the configuration lines
+    //     while (true)
+    //       {
+    //         // Get the line
+    //         skipComment(listStream);
+    //         getline(listStream, line);
+    
+    //         // Get the line type
+    //         unsigned int endIndexItemType= line.find_first_of ("_",0)-1;
+    //         string typeString= line.substr(0 , endIndexItemType+1);
+    
+    //         // Check
+    //         if  (typeString=="Point")
+    //           break;
+    //       }
+    
+    //     // Get the point number
+    //     unsigned int beginIndexItemNumber= line.find_first_of ("_",0)+1; 
+    //     unsigned int endIndexItemNumber= line.find_first_of ("->",0)-1;
+    //     stringstream numberString( line.substr(beginIndexItemNumber , endIndexItemNumber-beginIndexItemNumber+1) );
+    //     unsigned int itemNumber;
+    //     numberString>> itemNumber;
+    
+    //     // Go over all the lines
+    //     while(!listStream.eof()) 
+    //       {
+    //         // Stored data
+    //         itk::Point<ValueType, Dimension> point1, point2;
+    //         point1.Fill(0.);
+    //         point2.Fill(0.);
+    //         bool veryUnsure=false;
+    
+    //         // Retrieved data
+    //         itk::ContinuousIndex<ValueType, Dimension> item1, item2;
+    //         item1.Fill(0.);
+    //         item2.Fill(0.);
+    
+    //         // Go over all lines corresponding to this point
+    //         unsigned int currentNumber=itemNumber;
+    //         while (itemNumber == currentNumber && (!listStream.eof()) )
+    //           {
+    //             // Get the tag
+    //             unsigned int beginIndexItemTag= line.find_first_of ("->",0)+2; 
+    //             unsigned int endIndexItemTag= line.find_first_of ("=",0)-1;
+    //             string itemTag= line.substr(beginIndexItemTag , endIndexItemTag-beginIndexItemTag+1);
+    
+    //             // Get the point Value
+    //             unsigned int beginIndexItemValue= line.find_first_of ("=",0)+1; 
+    //             stringstream valueString( line.substr(beginIndexItemValue) );
+    //             double itemValue;
+    //             valueString>> itemValue;
+    
+    //             // Fill the items
+    //             if (itemTag=="X")
+    //               item1[0]=itemValue;
+    //             if (itemTag=="Y")
+    //               item1[1]=itemValue;
+    //             if (itemTag=="Z")
+    //               item1[2]=itemValue;
+    //             if (itemTag=="X_Corresp")
+    //               item2[0]=itemValue;
+    //             if (itemTag=="Y_Corresp")
+    //               item2[1]=itemValue;
+    //             if (itemTag=="Z_Corresp")
+    //                item2[2]=itemValue;
+    //             if (itemTag=="VeryUnsure")
+    //               veryUnsure=itemValue;
+    
+    //             // Get the next line
+    //             skipComment(listStream);
+    //             getline(listStream, line);
+    
+    //             // Get the point number
+    //             unsigned int beginIndexItemNumber= line.find_first_of ("_",0)+1; 
+    //             unsigned int endIndexItemNumber= line.find_first_of ("->",0)-1;
+    //             stringstream numberString( line.substr(beginIndexItemNumber , endIndexItemNumber-beginIndexItemNumber+1) );
+    //             numberString>> itemNumber;
+    //           }
diff --git a/registration/clitkLists.h b/registration/clitkLists.h
new file mode 100644 (file)
index 0000000..ada58de
--- /dev/null
@@ -0,0 +1,83 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkLists_h
+#define clitkLists_h
+/**
+   =================================================
+   * @file   clitkLists.h
+   * @author Jef Vandemeulebroucke <jef@creatis.insa-lyon.fr>
+   * @date   30 April 2008
+   * 
+   * @brief 
+   * 
+   =================================================*/
+
+#include "clitkCommon.h"
+#include "clitkIO.h"
+#include "clitkList.h"
+
+// itk include
+#include "itkLightObject.h"
+
+using namespace std;
+
+namespace clitk{
+
+  template <class ListItemType > 
+  class Lists: public std::vector<clitk::List<ListItemType> >
+  {
+  public:
+    //=====================================================================================
+    //Typedefs
+    typedef typename ListItemType::ValueType ValueType;
+    itkStaticConstMacro(Dimension, unsigned int, ListItemType::Dimension);
+    typedef List<ListItemType> ListType;
+    typedef itk::Image<signed short, Dimension> ImageType;
+
+    //=====================================================================================  
+    // IO
+    void Read(const std::vector<std::string>& fileNames, bool verbose=false);
+    void ReadAndConvertPointPairs(const std::vector<std::string>& fileNames, ListType& refList, const typename ImageType::Pointer referenceImage , bool verbose=false);
+    void Write(const std::vector<std::string> fileNames, const bool verbose);
+    void Print();
+  
+    //=====================================================================================
+    // Members
+    Lists< itk::FixedArray<double,1> > Norm(void);
+          
+    //=====================================================================================
+    //Constructors - Destructors
+    Lists(){};
+    Lists(unsigned int size){this->resize(size);};
+    Lists(const std::vector<std::string> fileNames, bool verbose=false ){Read(fileNames, verbose);}
+    ~Lists(){};
+  
+
+  protected:
+
+
+  };
+
+
+} // namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkLists.txx"
+#endif
+
+#endif
diff --git a/registration/clitkLists.txx b/registration/clitkLists.txx
new file mode 100644 (file)
index 0000000..bd404c6
--- /dev/null
@@ -0,0 +1,180 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkLists_txx
+#define clitkLists_txx
+#include "clitkLists.h"
+
+using namespace std; 
+
+namespace clitk 
+{
+  
+  //---------------------------------------------------------------------
+  // Read
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  void Lists< ListItemType>::Read(const std::vector<string>& filenames, bool verbose)
+  {
+
+    // Make the lists
+    this->resize(filenames.size());
+
+    // Read the lists   
+    for (unsigned int i=0; i<filenames.size();i++)
+      this->at(i).Read(filenames[i],verbose);
+    
+  }
+
+  //---------------------------------------------------------------------
+  // Norm
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  Lists<itk::FixedArray<double,1> > Lists<ListItemType>::Norm(void)
+  {
+    Lists<itk::FixedArray<double,1> > norm;
+
+    // Normalize the lists   
+    for (unsigned int i=0; i<this->size();i++)
+      norm.push_back(this->at(i).Norm());
+  
+    return norm;
+  }
+
+  //---------------------------------------------------------------------
+  // ReadPointPairs (specific for DARS- IX point list format)
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  void 
+  Lists<ListItemType>::ReadAndConvertPointPairs(const std::vector<std::string>& fileNames, ListType& refList, const typename ImageType::Pointer referenceImage, bool verbose)
+  {
+
+    // Init
+    this->resize(fileNames.size());
+    refList.resize(0);
+    bool pointWasFound=true;
+    unsigned int pointNumber=0;
+    itk::ContinuousIndex<ValueType, Dimension> item1;
+    std::vector<itk::ContinuousIndex<ValueType, Dimension> > item2(fileNames.size());
+    itk::Point<ValueType, Dimension> point1, point2;
+    unsigned int totalNumberOfPoints=0;
+    std::vector<unsigned int> addedNumberOfPoints,ommittedNumberOfPoints;
+    std::vector<bool> pointIsUnsure(fileNames.size());
+    std::vector<std::vector<bool> > ommittedNumberOfPointsUnsure;
+    
+    // Loop over the points
+    while (pointWasFound)
+      {
+
+       if (verbose) std::cout<<std::endl<<"Processing point number: "<<pointNumber<<"..."<<std::endl;
+       if (verbose) std::cout<<"Point number: "<<pointNumber<<" was found in list number: ";
+       
+       // Loop over lists
+       bool veryUnsure=false;
+       for (unsigned int i =0; i< fileNames.size(); i++)
+         {
+           // Get the point
+           pointWasFound=this->at(i).ReadPointPair(fileNames[i],pointNumber,item1,item2[i],veryUnsure);
+           if (verbose && pointWasFound) std::cout<<" "<<i;
+                   
+           // Set unsure
+           pointIsUnsure[i]= veryUnsure;
+
+           // point not found
+           if(!pointWasFound) break;
+         }
+       if (verbose) std::cout<<std::endl;
+
+       // The point was found
+       if (pointWasFound)
+         {
+           totalNumberOfPoints++;
+
+           // Point unsure?
+           bool unsure=false;
+           for (unsigned int i =0; i< fileNames.size(); i++)
+             if (pointIsUnsure[i])
+               {
+                 unsure=true;
+                 break;
+               }
+
+           // At least one of the lists had it tagged as veryUnsure
+           if (unsure)
+             {
+               ommittedNumberOfPoints.push_back(pointNumber);
+               ommittedNumberOfPointsUnsure.push_back(pointIsUnsure);
+               if (verbose) std::cout<<"Omitting item "<<pointNumber<<" (very unsure): "<<item1<<" ; "<<item2[0]<<std::endl;
+             }
+           else 
+             {
+               addedNumberOfPoints.push_back(pointNumber);
+               // Add the point to all the lists 
+               for (unsigned int i =0; i< fileNames.size(); i++)
+                 {
+                   if (verbose) std::cout<<"Adding item "<<pointNumber<<": "<<item1<<" ; "<<item2[i]<<std::endl;
+                   if (i==0)
+                     {
+                       referenceImage->TransformContinuousIndexToPhysicalPoint(item1, point1);
+                       refList.push_back(point1);
+                     }
+                   referenceImage->TransformContinuousIndexToPhysicalPoint(item2[i], point2);
+                   if (verbose) std::cout<<"Converted items "<<pointNumber<<" to points: "<<point1<<" ; "<<point2<<std::endl;
+                   this->at(i).push_back(point2);
+                 }
+             }
+         }
+       
+       // Next point 
+       pointNumber++;
+
+      }
+
+    if (verbose)
+      {
+       std::cout<<std::endl<<totalNumberOfPoints<<" points processed, "<< ommittedNumberOfPoints.size() <<" points omitted, "<< addedNumberOfPoints.size()<<" points added."<<std::endl;
+       std::cout<<"Added point numbers: "<< std::endl;
+       for (unsigned int i=0; i< addedNumberOfPoints.size();i++)
+         std::cout<<addedNumberOfPoints[i] <<std::endl;
+       std::cout<<"Omitted point numbers: "<< std::endl;
+           for (unsigned int i=0; i< ommittedNumberOfPoints.size();i++)
+             {
+               std::cout<<ommittedNumberOfPoints[i] <<"\t";
+               for (unsigned int j=0; j< fileNames.size();j++)
+                 std::cout<<ommittedNumberOfPointsUnsure[i][j]<<" ";
+               std::cout<<std::endl;
+             }
+      }
+  }
+
+    
+
+
+  //---------------------------------------------------------------------
+  // Write
+  //---------------------------------------------------------------------
+  template<class ListItemType>
+  void Lists<ListItemType>::Write(const std::vector<std::string> fileNames, const bool verbose)
+  {
+    for (unsigned int i =0; i< fileNames.size(); i++)
+      this->at(i).Write(fileNames[i], verbose);
+  }
+
+
+} // namespace 
+
+#endif
diff --git a/registration/clitkMatrixTransformToVF.cxx b/registration/clitkMatrixTransformToVF.cxx
new file mode 100755 (executable)
index 0000000..40af4d3
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkMatrixTransformToVF.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkMatrixTransformToVF_ggo.h"
+#include "clitkIO.h"
+#include "clitkMatrixTransformToVFGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkMatrixTransformToVF, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::MatrixTransformToVFGenericFilter::Pointer genericFilter=clitk::MatrixTransformToVFGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkMatrixTransformToVF.ggo b/registration/clitkMatrixTransformToVF.ggo
new file mode 100755 (executable)
index 0000000..e30742f
--- /dev/null
@@ -0,0 +1,18 @@
+#File clitkMatrixTransformToVF.ggo
+Package "clitkMatrixTransformToVF"
+version "1.0"
+purpose "Convert a matrix to a DVF with given properties"
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+option "matrix"                i       "Input matrix filename"           string        yes
+option "output"                o       "Output image filename"           string        yes
+option "dim"           d       "Dimension"               int   no      default="3"
+
+section "Output Image Properties"
+option "like"                  -       "Make output like this image"                   string          no              
+option "origin"                        -       "Origin for the output image"                   double          multiple no     default="0.0"
+option "size"                  -       "Size for the output image"                     int             multiple no     default="100"       
+option "spacing"               -       "Spacing for the output image"                  double          multiple no     default="1.0"       
+
diff --git a/registration/clitkMatrixTransformToVFGenericFilter.cxx b/registration/clitkMatrixTransformToVFGenericFilter.cxx
new file mode 100755 (executable)
index 0000000..2d49066
--- /dev/null
@@ -0,0 +1,71 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkMatrixTransformToVFGenericFilter_cxx
+#define clitkMatrixTransformToVFGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkMatrixTransformToVFGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkMatrixTransformToVFGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  MatrixTransformToVFGenericFilter::MatrixTransformToVFGenericFilter()
+  {
+    m_Verbose=false;
+   
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void MatrixTransformToVFGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension=m_ArgsInfo.dim_arg;
+    //std::string PixelType;
+    //ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType);
+    
+    // Call UpdateWithDim
+    if(Dimension==2) UpdateWithDim<2>();
+    else if(Dimension==3) UpdateWithDim<3>();
+    // else if (Dimension==4)UpdateWithDim<4>(PixelType); 
+    else 
+      {
+       std::cout<<"Error, Only for 2 or 3  Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkMatrixTransformToVFGenericFilter_cxx
diff --git a/registration/clitkMatrixTransformToVFGenericFilter.h b/registration/clitkMatrixTransformToVFGenericFilter.h
new file mode 100755 (executable)
index 0000000..af5468f
--- /dev/null
@@ -0,0 +1,115 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkMatrixTransformToVFGenericFilter_h
+#define clitkMatrixTransformToVFGenericFilter_h
+
+/* =================================================
+ * @file   clitkMatrixTransformToVFGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkTransformUtilities.h"
+#include "clitkMatrixTransformToVF_ggo.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkTransformToDeformationFieldSource.h"
+#include "itkAffineTransform.h"
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT MatrixTransformToVFGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef MatrixTransformToVFGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( MatrixTransformToVFGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkMatrixTransformToVF & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    MatrixTransformToVFGenericFilter();
+    ~MatrixTransformToVFGenericFilter() {};
+
+    
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <unsigned int Dimension>  void UpdateWithDim();
+    //template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkMatrixTransformToVF m_ArgsInfo;
+    bool m_Verbose;
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkMatrixTransformToVFGenericFilter.txx"
+#endif
+
+#endif // #define clitkMatrixTransformToVFGenericFilter_h
diff --git a/registration/clitkMatrixTransformToVFGenericFilter.txx b/registration/clitkMatrixTransformToVFGenericFilter.txx
new file mode 100755 (executable)
index 0000000..df1ed8a
--- /dev/null
@@ -0,0 +1,145 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkMatrixTransformToVFGenericFilter_txx
+#define clitkMatrixTransformToVFGenericFilter_txx
+
+/* =================================================
+ * @file   clitkMatrixTransformToVFGenericFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+namespace clitk
+{
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions
+  //-------------------------------------------------------------------
+  template<unsigned int Dimension>
+  void 
+  MatrixTransformToVFGenericFilter::UpdateWithDim()
+  {
+ //    if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<< PixelType<<"..."<<std::endl;
+
+//     if(PixelType == "short"){  
+//       if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
+//       UpdateWithDimAndPixelType<Dimension, signed short>(); 
+//     }
+//     //    else if(PixelType == "unsigned_short"){  
+//     //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
+//     //       UpdateWithDimAndPixelType<Dimension, unsigned short>(); 
+//     //     }
+    
+//     else if (PixelType == "unsigned_char"){ 
+//       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
+//       UpdateWithDimAndPixelType<Dimension, unsigned char>();
+//     }
+    
+//     //     else if (PixelType == "char"){ 
+//     //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
+//     //       UpdateWithDimAndPixelType<Dimension, signed char>();
+//     //     }
+//     else {
+//       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
+//       UpdateWithDimAndPixelType<Dimension, float>();
+//     }
+//   }
+
+
+//   //-------------------------------------------------------------------
+//   // Update with the number of dimensions and the pixeltype
+//   //-------------------------------------------------------------------
+//   template <unsigned int Dimension, class  PixelType> 
+//   void 
+//   MatrixTransformToVFGenericFilter::UpdateWithDimAndPixelType()
+//   {
+
+    // ImageTypes
+    typedef itk::Vector<float,Dimension> Displacement;
+    typedef itk::Image<Displacement, Dimension> OutputImageType;
+    
+    // Filter
+    typedef itk::TransformToDeformationFieldSource<OutputImageType, double> ConvertorType;
+    typename   ConvertorType::Pointer filter= ConvertorType::New();
+
+    // Output image info
+    if (m_ArgsInfo.like_given)
+      {
+       typedef itk::ImageFileReader<OutputImageType> ReaderType;
+       typename ReaderType::Pointer reader2=ReaderType::New();
+       reader2->SetFileName(m_ArgsInfo.like_arg);
+       reader2->Update();
+
+       typename OutputImageType::Pointer image=reader2->GetOutput();
+       filter->SetOutputParametersFromImage(image);
+      }
+    else
+      {
+       unsigned int i=0;
+       if(m_ArgsInfo.origin_given)
+         {
+           typename OutputImageType::PointType origin;
+           for(i=0;i<Dimension;i++)
+             origin[i]=m_ArgsInfo.origin_arg[i];
+           filter->SetOutputOrigin(origin);
+         }
+       if (m_ArgsInfo.spacing_given)
+         {
+           typename OutputImageType::SpacingType spacing;
+           for(i=0;i<Dimension;i++)
+             spacing[i]=m_ArgsInfo.spacing_arg[i];
+           filter->SetOutputSpacing(spacing);
+         }
+       if (m_ArgsInfo.size_given)
+         {
+           typename OutputImageType::SizeType size;
+           for(i=0;i<Dimension;i++)
+             size[i]=m_ArgsInfo.size_arg[i];
+           filter->SetOutputSize(size);
+         }
+      }
+    
+    // Transform
+    typedef itk::AffineTransform<double, Dimension> TransformType;
+    typename TransformType::Pointer transform =TransformType::New();
+    itk::Matrix<double, Dimension+1, Dimension+1> homMatrix= ReadMatrix<Dimension>( m_ArgsInfo.matrix_arg);
+    itk::Matrix<double, Dimension, Dimension> matrix =GetRotationalPartMatrix( homMatrix);
+    itk::Vector<double, Dimension> offset= GetTranslationPartMatrix( homMatrix);
+    transform->SetMatrix(matrix);
+    transform->SetOffset(offset);
+    filter->SetTransform(transform);
+    filter->Update();
+    typename OutputImageType::Pointer output=filter->GetOutput();
+
+    // Output
+    typedef itk::ImageFileWriter<OutputImageType> WriterType;
+    typename WriterType::Pointer writer = WriterType::New();
+    writer->SetFileName(m_ArgsInfo.output_arg);
+    writer->SetInput(output);
+    writer->Update();
+
+  }
+
+
+}//end clitk
+#endif //#define clitkMatrixTransformToVFGenericFilter_txx
diff --git a/registration/clitkMultiResolutionPDEDeformableRegistration.h b/registration/clitkMultiResolutionPDEDeformableRegistration.h
new file mode 100755 (executable)
index 0000000..3487208
--- /dev/null
@@ -0,0 +1,235 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkMultiResolutionPDEDeformableRegistration_h
+#define __clitkMultiResolutionPDEDeformableRegistration_h
+#include "itkImage.h"
+#include "itkImageToImageFilter.h"
+#include "itkPDEDeformableRegistrationFilter.h"
+#include "itkDemonsRegistrationFilter.h"
+#include "itkMultiResolutionPyramidImageFilter.h"
+#include "itkVectorResampleImageFilter.h"
+#include "itkRecursiveGaussianImageFilter.h"
+#include <vector>
+
+namespace clitk
+{
+
+template <class TFixedImage, class TMovingImage, class TDeformationField, class  TRealType = float>
+class ITK_EXPORT MultiResolutionPDEDeformableRegistration :
+    public itk::ImageToImageFilter <TDeformationField, TDeformationField>
+{
+public:
+  /** Standard class typedefs */
+  typedef MultiResolutionPDEDeformableRegistration Self;
+  typedef itk::ImageToImageFilter<TDeformationField, TDeformationField>  Superclass;
+  typedef itk::SmartPointer<Self>  Pointer;
+  typedef itk::SmartPointer<const Self>  ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( MultiResolutionPDEDeformableRegistration, 
+                ImageToImageFilter );
+
+  /** Fixed image type. */
+  typedef TFixedImage FixedImageType;
+  typedef typename FixedImageType::Pointer FixedImagePointer;
+  typedef typename FixedImageType::ConstPointer FixedImageConstPointer;
+
+  /** Moving image type. */
+  typedef TMovingImage MovingImageType;
+  typedef typename MovingImageType::Pointer MovingImagePointer;
+  typedef typename MovingImageType::ConstPointer MovingImageConstPointer;
+
+  /** Deformation field image type. */
+  typedef TDeformationField DeformationFieldType;
+  typedef typename DeformationFieldType::Pointer DeformationFieldPointer;
+
+  /** ImageDimension. */
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      FixedImageType::ImageDimension);
+
+  /** Internal float image type. */
+  typedef itk::Image<TRealType,itkGetStaticConstMacro(ImageDimension)> FloatImageType;
+
+  /** The internal registration type. */
+  typedef itk::PDEDeformableRegistrationFilter<
+    FloatImageType, FloatImageType, DeformationFieldType > RegistrationType;
+  typedef typename RegistrationType::Pointer RegistrationPointer;
+
+  /** The default registration type. */
+  typedef itk::DemonsRegistrationFilter<
+    FloatImageType, FloatImageType, DeformationFieldType > DefaultRegistrationType;
+
+  /** The fixed multi-resolution image pyramid type. */
+  typedef itk::MultiResolutionPyramidImageFilter<
+    FixedImageType, FloatImageType > FixedImagePyramidType;
+  typedef typename FixedImagePyramidType::Pointer FixedImagePyramidPointer;
+
+  /** The moving multi-resolution image pyramid type. */
+typedef itk::MultiResolutionPyramidImageFilter<
+    MovingImageType, FloatImageType > MovingImagePyramidType;
+  typedef typename MovingImagePyramidType::Pointer MovingImagePyramidPointer;
+   
+  /** The deformation field expander type. */
+typedef itk::VectorResampleImageFilter<
+    DeformationFieldType, DeformationFieldType > FieldExpanderType;
+  typedef typename FieldExpanderType::Pointer  FieldExpanderPointer;
+
+  /** Set the fixed image. */
+  virtual void SetFixedImage( const FixedImageType * ptr );
+
+  /** Get the fixed image. */
+  const FixedImageType * GetFixedImage(void) const;
+
+  /** Set the moving image. */
+  virtual void SetMovingImage( const MovingImageType * ptr );
+
+  /** Get the moving image. */
+  const MovingImageType * GetMovingImage(void) const;
+
+  /** Set initial deformation field to be used as is (no smoothing, no
+   *  subsampling at the coarsest level of the pyramid. */
+  virtual void SetInitialDeformationField( DeformationFieldType * ptr )
+  {
+    this->m_InitialDeformationField=ptr;
+  }
+
+  /** Set initial deformation field. No assumption is made on the
+   *  input. It will therefore be smoothed and resampled to match the
+   *  images characteristics at the coarsest level of the pyramid. */
+  virtual void SetArbitraryInitialDeformationField( DeformationFieldType * ptr )
+  {
+    this->SetInput( ptr ); 
+  }
+  
+  /** Get output deformation field. */
+  const DeformationFieldType * GetDeformationField(void)
+  { return this->GetOutput(); }
+
+  /** Get the number of valid inputs.  For
+   * MultiResolutionPDEDeformableRegistration, this checks whether the
+   * fixed and moving images have been set. While
+   * MultiResolutionPDEDeformableRegistration can take a third input
+   * as an initial deformation field, this input is not a required input.
+   */
+  virtual std::vector<itk::SmartPointer<itk::DataObject> >::size_type GetNumberOfValidRequiredInputs() const;
+
+  /** Set the internal registrator. */
+  itkSetObjectMacro( RegistrationFilter, RegistrationType );
+
+  /** Get the internal registrator. */
+  itkGetObjectMacro( RegistrationFilter, RegistrationType );
+  
+  /** Set the fixed image pyramid. */
+  itkSetObjectMacro( FixedImagePyramid, FixedImagePyramidType );
+
+  /** Get the fixed image pyramid. */
+  itkGetObjectMacro( FixedImagePyramid, FixedImagePyramidType );
+
+  /** Set the moving image pyramid. */
+  itkSetObjectMacro( MovingImagePyramid, MovingImagePyramidType );
+
+  /** Get the moving image pyramid. */
+  itkGetObjectMacro( MovingImagePyramid, MovingImagePyramidType );
+
+  /** Set number of multi-resolution levels. */
+  virtual void SetNumberOfLevels( unsigned int num );
+
+  /** Get number of multi-resolution levels. */
+  itkGetConstReferenceMacro( NumberOfLevels, unsigned int );
+
+  /** Get the current resolution level being processed. */
+  itkGetConstReferenceMacro( CurrentLevel, unsigned int );
+
+  /** Set number of iterations per multi-resolution levels. */
+  itkSetVectorMacro( NumberOfIterations, unsigned int, m_NumberOfLevels );
+
+  /** Set the moving image pyramid. */
+  itkSetObjectMacro( FieldExpander, FieldExpanderType );
+
+  /** Get the moving image pyramid. */
+  itkGetObjectMacro( FieldExpander, FieldExpanderType );
+
+  /** Get number of iterations per multi-resolution levels. */
+  virtual const unsigned int * GetNumberOfIterations() const
+  { return &(m_NumberOfIterations[0]); }
+
+  /** Stop the registration after the current iteration. */
+  virtual void StopRegistration();
+
+protected:
+  MultiResolutionPDEDeformableRegistration();
+  ~MultiResolutionPDEDeformableRegistration() {}
+void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+  /** Generate output data by performing the registration
+   * at each resolution level. */
+  virtual void GenerateData();
+
+  /** The current implementation of this class does not support
+   * streaming. As such it requires the largest possible region
+   * for the moving, fixed and input deformation field. */
+  virtual void GenerateInputRequestedRegion();
+
+  /** By default, the output deformation field has the same
+   * spacing, origin and LargestPossibleRegion as the input/initial
+   * deformation field.
+   *
+   * If the initial deformation field is not set, the output
+   * information is copied from the fixed image. */
+  virtual void GenerateOutputInformation();
+
+  /** The current implementation of this class does not supprot
+   * streaming. As such it produces the output for the largest
+   * possible region. */
+  virtual void EnlargeOutputRequestedRegion( itk::DataObject *ptr );
+
+  /** This method returns true to indicate that the registration should
+   * terminate at the current resolution level. */
+  virtual bool Halt();
+
+private:
+  MultiResolutionPDEDeformableRegistration(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+  RegistrationPointer        m_RegistrationFilter;
+  FixedImagePyramidPointer   m_FixedImagePyramid;
+  MovingImagePyramidPointer  m_MovingImagePyramid;
+  FieldExpanderPointer       m_FieldExpander;
+  DeformationFieldPointer    m_InitialDeformationField;
+
+  unsigned int               m_NumberOfLevels;
+  unsigned int               m_CurrentLevel;
+  std::vector<unsigned int>  m_NumberOfIterations;
+
+  /** Flag to indicate user stop registration request. */
+  bool                      m_StopRegistrationFlag;
+
+};
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkMultiResolutionPDEDeformableRegistration.txx"
+#endif
+
+
+#endif
diff --git a/registration/clitkMultiResolutionPDEDeformableRegistration.txx b/registration/clitkMultiResolutionPDEDeformableRegistration.txx
new file mode 100755 (executable)
index 0000000..933f169
--- /dev/null
@@ -0,0 +1,574 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef _clitkMultiResolutionPDEDeformableRegistration_txx
+#define _clitkMultiResolutionPDEDeformableRegistration_txx
+#include "clitkMultiResolutionPDEDeformableRegistration.h"
+
+#include "itkRecursiveMultiResolutionPyramidImageFilter.h"
+#include "itkImageRegionIterator.h"
+#include "vnl/vnl_math.h"
+
+namespace clitk {
+
+/*
+ * Default constructor
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::MultiResolutionPDEDeformableRegistration()
+{
+  this->SetNumberOfRequiredInputs(2);
+
+  typename DefaultRegistrationType::Pointer registrator =
+    DefaultRegistrationType::New();
+  m_RegistrationFilter = static_cast<RegistrationType*>(
+    registrator.GetPointer() );
+
+  m_MovingImagePyramid  = MovingImagePyramidType::New();
+  m_FixedImagePyramid     = FixedImagePyramidType::New();
+  m_FieldExpander     = FieldExpanderType::New();
+  m_InitialDeformationField = NULL;
+
+  m_NumberOfLevels = 3;
+  m_NumberOfIterations.resize( m_NumberOfLevels );
+  m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+  m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+
+  unsigned int ilevel;
+  for( ilevel = 0; ilevel < m_NumberOfLevels; ilevel++ )
+    {
+    m_NumberOfIterations[ilevel] = 10;
+    }
+  m_CurrentLevel = 0;
+
+  m_StopRegistrationFlag = false;
+
+}
+
+
+/*
+ * Set the moving image image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+void
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::SetMovingImage(
+const MovingImageType * ptr )
+{
+  this->itk::ProcessObject::SetNthInput( 2, const_cast< MovingImageType * >( ptr ) );
+}
+
+
+/*
+ * Get the moving image image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+const typename MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::MovingImageType *
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::GetMovingImage(void) const
+{
+  return dynamic_cast< const MovingImageType * >
+    ( this->itk::ProcessObject::GetInput( 2 ) );
+}
+
+
+/*
+ * Set the fixed image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+void
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::SetFixedImage(
+const FixedImageType * ptr )
+{
+  this->itk::ProcessObject::SetNthInput( 1, const_cast< FixedImageType * >( ptr ) );
+}
+
+
+/*
+ * Get the fixed image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+const typename MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::FixedImageType *
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::GetFixedImage(void) const
+{
+  return dynamic_cast< const FixedImageType * >
+    ( this->itk::ProcessObject::GetInput( 1 ) );
+}
+
+/*
+ * 
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+std::vector<itk::SmartPointer<itk::DataObject> >::size_type
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::GetNumberOfValidRequiredInputs() const
+{
+  typename std::vector<itk::SmartPointer<itk::DataObject> >::size_type num = 0;
+
+  if (this->GetFixedImage())
+    {
+    num++;
+    }
+
+  if (this->GetMovingImage())
+    {
+    num++;
+    }
+  
+  return num;
+}
+
+
+/*
+ * Set the number of multi-resolution levels
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+void
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::SetNumberOfLevels(
+unsigned int num )
+{
+  if( m_NumberOfLevels != num )
+    {
+    this->Modified();
+    m_NumberOfLevels = num;
+    m_NumberOfIterations.resize( m_NumberOfLevels );
+    }
+
+  if( m_MovingImagePyramid && m_MovingImagePyramid->GetNumberOfLevels() != num )
+    {
+    m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+    }
+  if( m_FixedImagePyramid && m_FixedImagePyramid->GetNumberOfLevels() != num )
+    {
+    m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+    }  
+}
+
+
+/*
+ * Standard PrintSelf method.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+void
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+  os << indent << "NumberOfLevels: " << m_NumberOfLevels << std::endl;
+  os << indent << "CurrentLevel: " << m_CurrentLevel << std::endl;
+
+  os << indent << "NumberOfIterations: [";
+  unsigned int ilevel;
+  for( ilevel = 0; ilevel < m_NumberOfLevels - 1; ilevel++ )
+    {
+    os << m_NumberOfIterations[ilevel] << ", ";
+    }
+  os << m_NumberOfIterations[ilevel] << "]" << std::endl;
+  
+  os << indent << "RegistrationFilter: ";
+  os << m_RegistrationFilter.GetPointer() << std::endl;
+  os << indent << "MovingImagePyramid: ";
+  os << m_MovingImagePyramid.GetPointer() << std::endl;
+  os << indent << "FixedImagePyramid: ";
+  os << m_FixedImagePyramid.GetPointer() << std::endl;
+
+  os << indent << "FieldExpander: ";
+  os << m_FieldExpander.GetPointer() << std::endl;
+
+  os << indent << "StopRegistrationFlag: ";
+  os << m_StopRegistrationFlag << std::endl;
+
+}
+
+/*
+ * Perform a the deformable registration using a multiresolution scheme
+ * using an internal mini-pipeline
+ *
+ *  ref_pyramid ->  registrator  ->  field_expander --|| tempField
+ * test_pyramid ->           |                              |
+ *                           |                              |
+ *                           --------------------------------    
+ *
+ * A tempField image is used to break the cycle between the
+ * registrator and field_expander.
+ *
+ */                              
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+void
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::GenerateData()
+{
+  // Check for NULL images and pointers
+  MovingImageConstPointer movingImage = this->GetMovingImage();
+  FixedImageConstPointer  fixedImage = this->GetFixedImage();
+
+  if( !movingImage || !fixedImage )
+    {
+    itkExceptionMacro( << "Fixed and/or moving image not set" );
+    }
+
+  if( !m_MovingImagePyramid || !m_FixedImagePyramid )
+    {
+    itkExceptionMacro( << "Fixed and/or moving pyramid not set" );
+    }
+
+  if( !m_RegistrationFilter )
+    {
+    itkExceptionMacro( << "Registration filter not set" );
+    }
+  
+  if( this->m_InitialDeformationField && this->GetInput(0) )
+    {
+    itkExceptionMacro( << "Only one initial deformation can be given. "
+                       << "SetInitialDeformationField should not be used in "
+                       << "cunjunction with SetArbitraryInitialDeformationField "
+                       << "or SetInput.");
+    }
+
+  //Update the number of levels for the pyramids
+  this->SetNumberOfLevels(m_NumberOfLevels);
+
+  // Create the image pyramids.
+  m_MovingImagePyramid->SetInput( movingImage );
+  m_MovingImagePyramid->UpdateLargestPossibleRegion();
+
+  m_FixedImagePyramid->SetInput( fixedImage );
+  m_FixedImagePyramid->UpdateLargestPossibleRegion();
+  // Initializations
+  m_CurrentLevel = 0;
+  m_StopRegistrationFlag = false;
+
+  unsigned int movingLevel = vnl_math_min( (int) m_CurrentLevel, 
+                                          (int) m_MovingImagePyramid->GetNumberOfLevels() );
+
+  unsigned int fixedLevel = vnl_math_min( (int) m_CurrentLevel, 
+                                         (int) m_FixedImagePyramid->GetNumberOfLevels() );
+
+  DeformationFieldPointer tempField = NULL;
+
+  DeformationFieldPointer inputPtr =
+    const_cast< DeformationFieldType * >( this->GetInput(0) );
+  
+  if ( this->m_InitialDeformationField )
+    {
+    tempField = this->m_InitialDeformationField;
+    }
+  else if( inputPtr )
+    {
+    // Arbitrary initial deformation field is set.
+    // smooth it and resample
+
+    // First smooth it
+    tempField = inputPtr;
+      
+    typedef itk::RecursiveGaussianImageFilter< DeformationFieldType,
+      DeformationFieldType> GaussianFilterType;
+    typename GaussianFilterType::Pointer smoother
+      = GaussianFilterType::New();
+      
+    for (unsigned int dim=0; dim<DeformationFieldType::ImageDimension; ++dim)
+      {
+      // sigma accounts for the subsampling of the pyramid
+      double sigma = 0.5 * static_cast<float>(
+        m_FixedImagePyramid->GetSchedule()[fixedLevel][dim] );
+
+      // but also for a possible discrepancy in the spacing
+      sigma *= fixedImage->GetSpacing()[dim]
+        / inputPtr->GetSpacing()[dim];
+      
+      smoother->SetInput( tempField );
+      smoother->SetSigma( sigma );
+      smoother->SetDirection( dim );
+      
+      smoother->Update();
+      
+      tempField = smoother->GetOutput();
+      tempField->DisconnectPipeline();
+      }
+      
+      
+    // Now resample
+    m_FieldExpander->SetInput( tempField );
+    
+    typename FloatImageType::Pointer fi = 
+      m_FixedImagePyramid->GetOutput( fixedLevel );
+    m_FieldExpander->SetSize( 
+      fi->GetLargestPossibleRegion().GetSize() );
+    m_FieldExpander->SetOutputStartIndex(
+      fi->GetLargestPossibleRegion().GetIndex() );
+    m_FieldExpander->SetOutputOrigin( fi->GetOrigin() );
+    m_FieldExpander->SetOutputSpacing( fi->GetSpacing());
+    m_FieldExpander->SetOutputDirection( fi->GetDirection());
+
+    m_FieldExpander->UpdateLargestPossibleRegion();
+    m_FieldExpander->SetInput( NULL );
+    tempField = m_FieldExpander->GetOutput();
+    tempField->DisconnectPipeline();
+    }
+
+
+  bool lastShrinkFactorsAllOnes = false;
+  while ( !this->Halt() )
+    {
+      
+      if( tempField.IsNull() )
+       {
+         m_RegistrationFilter->SetInitialDeformationField( NULL );
+       }
+      else
+       {
+         // Resample the field to be the same size as the fixed image
+         // at the current level
+         m_FieldExpander->SetInput( tempField );
+         
+      typename FloatImageType::Pointer fi = 
+        m_FixedImagePyramid->GetOutput( fixedLevel );
+      m_FieldExpander->SetSize( 
+        fi->GetLargestPossibleRegion().GetSize() );
+      m_FieldExpander->SetOutputStartIndex(
+        fi->GetLargestPossibleRegion().GetIndex() );
+      m_FieldExpander->SetOutputOrigin( fi->GetOrigin() );
+      m_FieldExpander->SetOutputSpacing( fi->GetSpacing());
+
+      m_FieldExpander->UpdateLargestPossibleRegion();
+      m_FieldExpander->SetInput( NULL );
+      tempField = m_FieldExpander->GetOutput();
+      tempField->DisconnectPipeline();
+
+      m_RegistrationFilter->SetInitialDeformationField( tempField );
+
+      }
+
+    // setup registration filter and pyramids 
+    m_RegistrationFilter->SetMovingImage( m_MovingImagePyramid->GetOutput(movingLevel) );
+    m_RegistrationFilter->SetFixedImage( m_FixedImagePyramid->GetOutput(fixedLevel) );
+    m_RegistrationFilter->SetNumberOfIterations(
+      m_NumberOfIterations[m_CurrentLevel] );
+
+    // cache shrink factors for computing the next expand factors.
+    lastShrinkFactorsAllOnes = true;
+    for( unsigned int idim = 0; idim < ImageDimension; idim++ )
+      {
+      if ( m_FixedImagePyramid->GetSchedule()[fixedLevel][idim] > 1 )
+        {
+        lastShrinkFactorsAllOnes = false;
+        break;
+        }
+      }
+
+    // Invoke an iteration event.
+    this->InvokeEvent( itk::IterationEvent() );
+
+    // compute new deformation field
+    m_RegistrationFilter->UpdateLargestPossibleRegion();
+    tempField = m_RegistrationFilter->GetOutput();
+    tempField->DisconnectPipeline();
+
+    // Increment level counter.  
+    m_CurrentLevel++;
+    movingLevel = vnl_math_min( (int) m_CurrentLevel, 
+                               (int) m_MovingImagePyramid->GetNumberOfLevels() );
+    fixedLevel = vnl_math_min( (int) m_CurrentLevel, 
+                              (int) m_FixedImagePyramid->GetNumberOfLevels() );
+
+    // We can release data from pyramid which are no longer required.
+    if ( movingLevel > 0 )
+      {
+      m_MovingImagePyramid->GetOutput( movingLevel - 1 )->ReleaseData();
+      }
+    if( fixedLevel > 0 )
+      {
+      m_FixedImagePyramid->GetOutput( fixedLevel - 1 )->ReleaseData();
+      }
+
+    } // while not Halt()
+
+    if( !lastShrinkFactorsAllOnes )
+      {
+      // Some of the last shrink factors are not one
+      // graft the output of the expander filter to
+      // to output of this filter
+
+      // resample the field to the same size as the fixed image
+      m_FieldExpander->SetInput( tempField );
+      m_FieldExpander->SetSize( 
+        fixedImage->GetLargestPossibleRegion().GetSize() );
+      m_FieldExpander->SetOutputStartIndex(
+        fixedImage->GetLargestPossibleRegion().GetIndex() );
+      m_FieldExpander->SetOutputOrigin( fixedImage->GetOrigin() );
+      m_FieldExpander->SetOutputSpacing( fixedImage->GetSpacing());
+      m_FieldExpander->UpdateLargestPossibleRegion();
+      this->GraftOutput( m_FieldExpander->GetOutput() );
+      }
+    else
+      {
+      // all the last shrink factors are all ones
+      // graft the output of registration filter to
+      // to output of this filter
+      this->GraftOutput( tempField );
+      }
+
+    // Release memory
+    m_FieldExpander->SetInput( NULL );
+    m_FieldExpander->GetOutput()->ReleaseData();
+    m_RegistrationFilter->SetInput( NULL );
+    m_RegistrationFilter->GetOutput()->ReleaseData();
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+void
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::StopRegistration()
+{
+  m_RegistrationFilter->StopRegistration();
+  m_StopRegistrationFlag = true;
+}
+
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+bool
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::Halt()
+{
+  // Halt the registration after the user-specified number of levels
+  if (m_NumberOfLevels != 0)
+  {
+  this->UpdateProgress( static_cast<float>( m_CurrentLevel ) /
+                        static_cast<float>( m_NumberOfLevels ) );
+  }
+
+  if ( m_CurrentLevel >= m_NumberOfLevels )
+    {
+    return true;
+    }
+  if ( m_StopRegistrationFlag )
+    {
+    return true;
+    }
+  else
+    { 
+    return false; 
+    }
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+void
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::GenerateOutputInformation()
+{
+
+  typename itk::DataObject::Pointer output;
+
+ if( this->GetInput(0) )
+  {
+  // Initial deformation field is set.
+  // Copy information from initial field.
+  this->Superclass::GenerateOutputInformation();
+
+  }
+ else if( this->GetFixedImage() )
+  {
+  // Initial deforamtion field is not set. 
+  // Copy information from the fixed image.
+  for (unsigned int idx = 0; idx < 
+    this->GetNumberOfOutputs(); ++idx )
+    {
+    output = this->GetOutput(idx);
+    if (output)
+      {
+      output->CopyInformation(this->GetFixedImage());
+      }  
+    }
+
+  }
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+void
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::GenerateInputRequestedRegion()
+{
+
+  // call the superclass's implementation
+  Superclass::GenerateInputRequestedRegion();
+
+  // request the largest possible region for the moving image
+  MovingImagePointer movingPtr = 
+    const_cast< MovingImageType * >( this->GetMovingImage() );
+  if( movingPtr )
+    {
+    movingPtr->SetRequestedRegionToLargestPossibleRegion();
+    }
+  
+  // just propagate up the output requested region for
+  // the fixed image and initial deformation field.
+  DeformationFieldPointer inputPtr = 
+      const_cast< DeformationFieldType * >( this->GetInput() );
+  DeformationFieldPointer outputPtr = this->GetOutput();
+  FixedImagePointer fixedPtr = 
+        const_cast< FixedImageType *>( this->GetFixedImage() );
+
+  if( inputPtr )
+    {
+    inputPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
+    }
+
+  if( fixedPtr )
+    {
+    fixedPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
+    }
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField, class TRealType>
+void
+MultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField,TRealType>
+::EnlargeOutputRequestedRegion(
+                              itk::DataObject * ptr )
+{
+  // call the superclass's implementation
+  Superclass::EnlargeOutputRequestedRegion( ptr );
+
+  // set the output requested region to largest possible.
+  DeformationFieldType * outputPtr;
+  outputPtr = dynamic_cast<DeformationFieldType*>( ptr );
+
+  if( outputPtr )
+    {
+    outputPtr->SetRequestedRegionToLargestPossibleRegion();
+    }
+
+}
+
+
+} // end namespace itk
+
+#endif
diff --git a/registration/clitkMultiResolutionPyramid.cxx b/registration/clitkMultiResolutionPyramid.cxx
new file mode 100644 (file)
index 0000000..e4480ee
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkMultiResolutionPyramid.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkMultiResolutionPyramid_ggo.h"
+#include "clitkIO.h"
+#include "clitkMultiResolutionPyramidGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkMultiResolutionPyramid, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::MultiResolutionPyramidGenericFilter::Pointer genericFilter=clitk::MultiResolutionPyramidGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkMultiResolutionPyramid.ggo b/registration/clitkMultiResolutionPyramid.ggo
new file mode 100644 (file)
index 0000000..91f13bf
--- /dev/null
@@ -0,0 +1,18 @@
+#File clitkMultiResolutionPyramid.ggo
+Package "clitkMultiResolutionPyramid"
+version "1.0"
+purpose "Compute the multi-resolution (MR) image pyramid. The conventional filter will also modify the image at the original resolution, the recursive not. The spatio-temporal filters leave the last dimension untouched."
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+section "IO"
+option "input"         i       "Input image filename"            string        yes
+option "output"        o       "Output image (level) filenames"  string        yes multiple
+
+section "Pyramid"
+option "type"          t       "0=MR, 1= recursive MR, 2=spatio-temporal MR, 3 recursive spatio-temporal MR"   int     no      default="0"     
+option "levels"                l       "Number of resolution levels"                                                   int     no      default="2"
+
+
+
diff --git a/registration/clitkMultiResolutionPyramidGenericFilter.cxx b/registration/clitkMultiResolutionPyramidGenericFilter.cxx
new file mode 100644 (file)
index 0000000..d7038e0
--- /dev/null
@@ -0,0 +1,72 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkMultiResolutionPyramidGenericFilter_cxx
+#define clitkMultiResolutionPyramidGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkMultiResolutionPyramidGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkMultiResolutionPyramidGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  MultiResolutionPyramidGenericFilter::MultiResolutionPyramidGenericFilter()
+  {
+    m_Verbose=false;
+    m_InputFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void MultiResolutionPyramidGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType);
+
+    
+    // Call UpdateWithDim
+    if(Dimension==2) UpdateWithDim<2>(PixelType);
+    else if(Dimension==3) UpdateWithDim<3>(PixelType);
+    else if (Dimension==4)UpdateWithDim<4>(PixelType); 
+    else 
+      {
+       std::cout<<"Error, Only for 2,3 or 4 Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkMultiResolutionPyramidGenericFilter_cxx
diff --git a/registration/clitkMultiResolutionPyramidGenericFilter.h b/registration/clitkMultiResolutionPyramidGenericFilter.h
new file mode 100644 (file)
index 0000000..cc4005a
--- /dev/null
@@ -0,0 +1,117 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkMultiResolutionPyramidGenericFilter_h
+#define clitkMultiResolutionPyramidGenericFilter_h
+
+/* =================================================
+ * @file   clitkMultiResolutionPyramidGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkImageCommon.h"
+#include "clitkMultiResolutionPyramid_ggo.h"
+#include "clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkRecursiveMultiResolutionPyramidImageFilter.h"
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT MultiResolutionPyramidGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef MultiResolutionPyramidGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( MultiResolutionPyramidGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkMultiResolutionPyramid & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+      m_InputFileName=m_ArgsInfo.input_arg;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    MultiResolutionPyramidGenericFilter();
+    ~MultiResolutionPyramidGenericFilter() {};
+
+    
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <unsigned int Dimension>  void UpdateWithDim(std::string PixelType);
+    template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkMultiResolutionPyramid m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_InputFileName;
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkMultiResolutionPyramidGenericFilter.txx"
+#endif
+
+#endif // #define clitkMultiResolutionPyramidGenericFilter_h
diff --git a/registration/clitkMultiResolutionPyramidGenericFilter.txx b/registration/clitkMultiResolutionPyramidGenericFilter.txx
new file mode 100644 (file)
index 0000000..11b7ad5
--- /dev/null
@@ -0,0 +1,162 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkMultiResolutionPyramidGenericFilter_txx
+#define clitkMultiResolutionPyramidGenericFilter_txx
+
+/* =================================================
+ * @file   clitkMultiResolutionPyramidGenericFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+namespace clitk
+{
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions
+  //-------------------------------------------------------------------
+  template<unsigned int Dimension>
+  void 
+  MultiResolutionPyramidGenericFilter::UpdateWithDim(std::string PixelType)
+  {
+    if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<< PixelType<<"..."<<std::endl;
+
+    if(PixelType == "short"){  
+      if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, signed short>(); 
+    }
+    //    else if(PixelType == "unsigned_short"){  
+    //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, unsigned short>(); 
+    //     }
+    
+    else if (PixelType == "unsigned_char"){ 
+      if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, unsigned char>();
+    }
+    
+    //     else if (PixelType == "char"){ 
+    //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, signed char>();
+    //     }
+    else {
+      if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, float>();
+    }
+  }
+
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions and the pixeltype
+  //-------------------------------------------------------------------
+  template <unsigned int Dimension, class  PixelType> 
+  void 
+  MultiResolutionPyramidGenericFilter::UpdateWithDimAndPixelType()
+  {
+
+    // ImageTypes
+    typedef itk::Image<PixelType, Dimension> InputImageType;
+    typedef itk::Image<PixelType, Dimension> OutputImageType;
+    
+    // Read the input
+    typedef itk::ImageFileReader<InputImageType> InputReaderType;
+    typename InputReaderType::Pointer reader = InputReaderType::New();
+    reader->SetFileName( m_InputFileName);
+    reader->Update();
+    typename InputImageType::Pointer input= reader->GetOutput();
+
+    // Filter
+    typedef itk::ImageToImageFilter<InputImageType, OutputImageType> FilterType;
+    typename FilterType::Pointer filter;
+    switch(m_ArgsInfo.type_arg)
+      {
+      case 0: 
+       {
+         typedef itk::MultiResolutionPyramidImageFilter<InputImageType, OutputImageType> MRFilterType;
+         typename MRFilterType::Pointer rmFilter =MRFilterType::New();
+         if (m_Verbose) std::cout<<"Using the multi-resolution filter..."<<std::endl;
+         rmFilter->SetNumberOfLevels(m_ArgsInfo.levels_arg); 
+         filter=rmFilter;
+         break;
+       }
+      case 1: 
+       {
+         typedef itk::RecursiveMultiResolutionPyramidImageFilter<InputImageType, OutputImageType> RecursiveFilterType;
+         typename RecursiveFilterType::Pointer rFilter=RecursiveFilterType::New();
+         if (m_Verbose) std::cout<<"Using the recursive multi-resolution filter..."<<std::endl;
+         rFilter->SetNumberOfLevels(m_ArgsInfo.levels_arg); 
+         rFilter->SetUseShrinkImageFilter(false);
+         filter=rFilter;
+         break;
+       }
+      case 2: 
+       {
+         typedef clitk::SpatioTemporalMultiResolutionPyramidImageFilter<InputImageType, OutputImageType> SpatioTemporalFilterType;
+         typename SpatioTemporalFilterType::Pointer spFilter=SpatioTemporalFilterType::New();
+         if (m_Verbose) std::cout<<"Using the spatio-temporal multi-resolution filter..."<<std::endl;
+         spFilter->SetNumberOfLevels(m_ArgsInfo.levels_arg); 
+         filter=spFilter;
+         break;
+       }
+    case 3: 
+       {
+         typedef clitk::RecursiveSpatioTemporalMultiResolutionPyramidImageFilter<InputImageType, OutputImageType> RecursiveSpatioTemporalFilterType;
+         typename RecursiveSpatioTemporalFilterType::Pointer rspFilter=RecursiveSpatioTemporalFilterType::New();
+         if (m_Verbose) std::cout<<"Using the recursive spatio-temporal multi-resolution filter..."<<std::endl;
+         rspFilter->SetNumberOfLevels(m_ArgsInfo.levels_arg); 
+         rspFilter->SetUseShrinkImageFilter(false);
+         filter=rspFilter;
+         break;
+       }
+      }
+
+    // Common
+    filter->SetInput(input);  
+    try
+      {
+       filter->Update();
+      }
+    catch (itk::ExceptionObject)
+      {
+       std::cerr<<"Exception thrown during update() of the multi-resolution pyramid filter!"<<std::endl; 
+      }    
+
+    // Output
+    for(unsigned int i=0; i< m_ArgsInfo.output_given;i++)
+      {
+       // Get image at level i
+       typename OutputImageType::Pointer output=filter->GetOutput(i);
+               
+       // Write 
+       writeImage<OutputImageType>(output,m_ArgsInfo.output_arg[i], m_Verbose);
+//     typedef itk::ImageFileWriter<OutputImageType> WriterType;
+//     typename WriterType::Pointer writer = WriterType::New();
+//     writer->SetFileName(m_ArgsInfo.output_arg[i]);
+//     writer->SetInput(output);
+//     writer->Update();
+      }
+  }
+
+
+}//end clitk
+#endif //#define clitkMultiResolutionPyramidGenericFilter_txx
diff --git a/registration/clitkMultiResolutionPyramidRegionFilter.h b/registration/clitkMultiResolutionPyramidRegionFilter.h
new file mode 100644 (file)
index 0000000..1d43cfe
--- /dev/null
@@ -0,0 +1,115 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkMultiResolutionPyramidRegionFilter_h
+#define clitkMultiResolutionPyramidRegionFilter_h
+
+/* =================================================
+ * @file   clitkMultiResolutionPyramidRegionFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+
+//itk include
+#include "itkLightObject.h"
+
+namespace clitk 
+{
+
+  template <class InputImageType>
+  class ITK_EXPORT MultiResolutionPyramidRegionFilter :
+    public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef MultiResolutionPyramidRegionFilter                                                 Self;
+    typedef itk::LightObject                                          Superclass;
+    typedef itk::SmartPointer<Self>                                   Pointer;
+    typedef itk::SmartPointer<const Self>                             ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( MultiResolutionPyramidRegionFilter, LightObject );
+
+    /** Dimension of the domain space. */
+    itkStaticConstMacro(InputImageDimension, unsigned int, InputImageType::ImageDimension);
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+    typedef itk::ImageRegion<InputImageDimension> RegionType;
+    typedef itk::Array2D<unsigned int>  ScheduleType;
+    typedef typename InputImageType::SizeType SizeType;
+    typedef typename InputImageType::IndexType IndexType;
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetRegion(RegionType r){m_Region=r;}
+    void SetSchedule(ScheduleType r){m_Schedule=r;}
+
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update(void);
+    RegionType GetOutput(unsigned int i)
+    {
+      this->Update();
+      return m_RegionPyramid[i];
+    }
+      
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    MultiResolutionPyramidRegionFilter();
+    ~MultiResolutionPyramidRegionFilter() {};
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    RegionType m_Region;
+    std::vector<RegionType>  m_RegionPyramid;
+    ScheduleType m_Schedule;
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkMultiResolutionPyramidRegionFilter.txx"
+#endif
+
+#endif // #define clitkMultiResolutionPyramidRegionFilter_h
+
+
diff --git a/registration/clitkMultiResolutionPyramidRegionFilter.txx b/registration/clitkMultiResolutionPyramidRegionFilter.txx
new file mode 100644 (file)
index 0000000..bed3a50
--- /dev/null
@@ -0,0 +1,88 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkMultiResolutionPyramidRegionFilter_txx
+#define clitkMultiResolutionPyramidRegionFilter_txx
+
+/* =================================================
+ * @file   clitkMultiResolutionPyramidRegionFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+namespace clitk
+{
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions
+  //-------------------------------------------------------------------
+  template<class InputImageType>
+  MultiResolutionPyramidRegionFilter<InputImageType>::MultiResolutionPyramidRegionFilter()
+  {
+    ;
+  }
+
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions and the pixeltype
+  //-------------------------------------------------------------------
+  template <class InputImageType> 
+  void 
+  MultiResolutionPyramidRegionFilter<InputImageType>::Update()
+  {
+
+    // Compute the FixedImageRegion corresponding to each level of the 
+    // pyramid. This uses the same algorithm of the ShrinkImageFilter 
+    // since the regions should be compatible. 
+    unsigned int numberOfLevels=m_Schedule.rows();
+    m_RegionPyramid.reserve( numberOfLevels );
+    m_RegionPyramid.resize( numberOfLevels );
+    SizeType inputSize =m_Region.GetSize();
+    IndexType inputStart =m_Region.GetIndex();
+
+    for ( unsigned int level=0; level < numberOfLevels; level++ )
+      {
+       
+       SizeType  size;
+       IndexType start;
+       for ( unsigned int dim = 0; dim < InputImageDimension; dim++)
+         {
+           const float scaleFactor = static_cast<float>( m_Schedule[ level ][ dim ] );
+           
+           size[ dim ] = static_cast<typename SizeType::SizeValueType>(
+               vcl_floor(static_cast<float>( inputSize[ dim ] ) / scaleFactor ) );
+           if( size[ dim ] < 1 )
+             {
+               size[ dim ] = 1;
+             }
+           
+           start[ dim ] = static_cast<typename IndexType::IndexValueType>(
+                 vcl_ceil(static_cast<float>( inputStart[ dim ] ) / scaleFactor ) ); 
+         }
+       m_RegionPyramid[ level ].SetSize( size );
+       m_RegionPyramid[ level ].SetIndex( start );
+    }
+  }
+
+
+}//end clitk
+#endif //#define clitkMultiResolutionPyramidRegionFilter_txx
diff --git a/registration/clitkPointListReader.h b/registration/clitkPointListReader.h
new file mode 100644 (file)
index 0000000..be3b9ad
--- /dev/null
@@ -0,0 +1,71 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkPointListReader_h
+#define __clitkPointListReader_h
+#include "clitkPointListReader.h"
+
+namespace clitk
+{
+
+
+  template <unsigned int Dimension>
+  class ITK_EXPORT PointListReader : 
+    public itk::LightObject 
+  {
+  public:
+    //------------------------------------
+    // Standard itk typedefs
+    //-----------------------------------
+    typedef PointListReader                     Self;
+    typedef LightObject                         Superclass;
+    typedef itk::SmartPointer<Self>             Pointer;
+    typedef itk::SmartPointer<const Self>       ConstPointer;
+
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self); 
+
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(PointListReader, PointListReader); 
+
+    // Typedefs
+    typedef itk::Point<double, Dimension> PointType;
+    typedef std::vector<PointType> PointListType;
+    typedef std::vector< PointListType> PointListsType;   
+
+    void SetVerbose(bool a){m_Verbose=a;}
+    PointListType Read(const  std::string &);
+    PointListsType Read(char**, const unsigned int &);
+    
+
+  protected:
+    
+    // Constructor & Destructor
+    PointListReader();
+    ~PointListReader(){};
+
+    bool m_Verbose;
+
+  };
+
+} // namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkPointListReader.txx"
+#endif
+
+#endif
diff --git a/registration/clitkPointListReader.txx b/registration/clitkPointListReader.txx
new file mode 100644 (file)
index 0000000..c50927a
--- /dev/null
@@ -0,0 +1,75 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkPointListReader_txx
+#define __clitkPointListReader_txx
+#include "clitkPointListReader.h"
+
+namespace clitk
+{
+
+  template<unsigned int Dimension>
+  PointListReader< Dimension >
+  ::PointListReader()
+  {
+    m_Verbose=false;
+  }
+
+  template<unsigned int Dimension>
+  typename PointListReader< Dimension >::PointListType
+  PointListReader< Dimension >
+  ::Read(const std::string& filename)
+  {
+    std::ifstream is;
+    openFileForReading(is, filename);
+    PointListType list;
+    PointType point;
+    double x;
+
+    if(m_Verbose)std::cout<<"Reading "<<filename<<"..."<<std::endl;
+    for (unsigned int dim=0; dim<Dimension; dim++)
+      {
+       skipComment(is);
+       is >> x;
+       point[dim]=x;
+      }
+    while (!is.eof()) 
+      {
+       list.push_back(point);
+       for (unsigned int dim=0; dim<Dimension; dim++)
+         {
+           skipComment(is);
+           is >> x;
+           point[dim]=x;
+         }
+      }
+    return list;
+  }
+    
+  template<unsigned int Dimension>
+  typename PointListReader< Dimension >::PointListsType
+  PointListReader< Dimension >
+  ::Read(char** filename, const unsigned int& n)
+  {
+    PointListsType lists;
+    for (unsigned int number=0; number<n; number++)
+      lists.push_back(Read(filename[number]) );
+    return lists;
+  }
+
+}// clitk
+#endif // PointListReader
diff --git a/registration/clitkPointListTransform.h b/registration/clitkPointListTransform.h
new file mode 100644 (file)
index 0000000..3146f80
--- /dev/null
@@ -0,0 +1,95 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkPointListTransform_h
+#define __clitkPointListTransform_h
+#include "clitkList.h"
+#include "clitkLists.h"
+
+// itk
+#include "itkTransform.h"
+#include "itkVectorInterpolateImageFunction.h"
+
+namespace clitk
+{
+
+  template < class TScalarType=double, unsigned int NDimensions=4,unsigned int NOutputDimensions=4 >        
+  class ITK_EXPORT PointListTransform : public itk::Transform< TScalarType, NDimensions, NOutputDimensions >
+  {
+  public:
+    /** Standard class typedefs. */
+    typedef PointListTransform                                      Self;
+    typedef itk::Transform< TScalarType, NDimensions, NOutputDimensions > Superclass;
+    typedef itk::SmartPointer<Self>                                 Pointer;
+    typedef itk::SmartPointer<const Self>                           ConstPointer;
+      
+    /** New macro for creation of through the object factory. */
+    itkNewMacro( Self );
+
+    /** Run-time type information (and related methods). */
+    itkTypeMacro( PointListTransform, Transform );
+
+    /** Dimension of the domain space. */
+    itkStaticConstMacro(SpaceDimension, unsigned int, NDimensions-1);
+    itkStaticConstMacro(ImageDimension, unsigned int, NDimensions);
+
+    // typedef 
+    typedef  itk::Point<double, SpaceDimension> SpacePointType;
+    typedef  itk::Point<double, ImageDimension> SpaceTimePointType;
+    typedef clitk::List<SpacePointType> PointListType;
+    typedef clitk::Lists<SpacePointType> PointListsType;
+    typedef itk::Vector<double, SpaceDimension> PointListImagePixelType;
+    typedef itk::Image<PointListImagePixelType, 1> PointListImageType; 
+    typedef itk::VectorInterpolateImageFunction<PointListImageType, double> InterpolatorType;
+
+    void SetPointList (PointListType p){m_PointList=p;}
+    void SetPointLists (PointListsType p){m_PointLists=p;}
+    void SetInterpolator (typename InterpolatorType::Pointer i){ m_Interpolator=i;}
+
+    /** Standard coordinate point type for this class. */
+    typedef itk::Point<TScalarType, itkGetStaticConstMacro(ImageDimension)> InputPointType;
+    typedef itk::Point<TScalarType, itkGetStaticConstMacro(ImageDimension)> OutputPointType;
+
+
+    PointListType GetCorrespondingPointList(const InputPointType &inputPoint) const; 
+    OutputPointType TransformPoint(const InputPointType  &point ) const;
+   
+  protected:
+    PointListTransform();
+    ~PointListTransform(){;}
+
+  private:
+    PointListTransform(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+
+    PointListsType m_PointLists;
+    mutable PointListType m_PointList;
+    typename InterpolatorType::Pointer m_Interpolator;
+
+
+  }; //class PointListTransform
+
+
+
+}  // namespace itk
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkPointListTransform.txx"
+#endif
+
+#endif /* __clitkPointListTransform_h */
diff --git a/registration/clitkPointListTransform.txx b/registration/clitkPointListTransform.txx
new file mode 100644 (file)
index 0000000..ef4a08e
--- /dev/null
@@ -0,0 +1,146 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkPointListTransform_txx
+#define __clitkPointListTransform_txx
+#include "clitkPointListTransform.h"
+
+
+namespace clitk
+{
+
+  // Constructor
+  template<class TScalarType, unsigned int NDimensions, unsigned int NOutputDimensions>
+  PointListTransform<TScalarType, NDimensions, NOutputDimensions>
+  ::PointListTransform():Superclass(NOutputDimensions,1)
+  {
+    m_PointLists.resize(0);
+    m_PointList.resize(1);
+  }
+    
+  // Find the point list in the lists
+  template<class TScalarType, unsigned int NDimensions,unsigned int NOutputDimensions>
+  typename PointListTransform<TScalarType,  NDimensions, NOutputDimensions>::PointListType
+  PointListTransform<TScalarType, NDimensions,NOutputDimensions>::
+  GetCorrespondingPointList(const InputPointType &inputPoint) const 
+  { 
+    SpacePointType point;
+    for(unsigned int j=0; j< SpaceDimension;j++)
+      point[j]=inputPoint[j];
+    
+    if(m_PointList[0]==point) return m_PointList;
+    else
+      {
+       for (unsigned int i=0; i< m_PointLists.size();i++)
+         if(m_PointLists[i][0]==point) return m_PointLists[i];
+      }
+    
+    itkExceptionMacro(<<"Point List not found");
+  }
+
+
+  // Transform a point
+  template<class TScalarType, unsigned int NDimensions,unsigned int NOutputDimensions>
+  typename PointListTransform<TScalarType,  NDimensions,NOutputDimensions>::OutputPointType
+  PointListTransform<TScalarType, NDimensions,NOutputDimensions>::
+  TransformPoint(const InputPointType &inputPoint) const 
+  {
+
+    // -------------------------------
+    // Get the corresponding point list
+    m_PointList = this->GetCorrespondingPointList(inputPoint);
+
+    // -------------------------------
+    // Create 1D vector image
+    typename PointListImageType::Pointer pointListImage=PointListImageType::New();
+    typename PointListImageType::RegionType region;
+    region.SetSize(0,m_PointList.size()+6);
+    pointListImage->SetRegions(region);
+    pointListImage->Allocate();
+    typename PointListImageType::SpacingType spacing;
+    spacing[0]=1;
+    pointListImage->SetSpacing(spacing);
+    typename PointListImageType::PointType origin;
+    origin[0]=-2.;
+    pointListImage->SetOrigin(origin);
+
+
+    // -------------------------------
+    // Copy Point list to image
+    typedef itk::ImageRegionIterator<PointListImageType> IteratorType;
+    IteratorType it(pointListImage, pointListImage->GetLargestPossibleRegion());
+
+    // First points are the last
+    PointListImagePixelType pixel;
+    for (unsigned int j=0; j<2;j++)
+      {
+       for (unsigned int i=0; i <SpaceDimension; i++)
+         pixel[i]=m_PointList[m_PointList.size()-2+j][i];
+       it.Set(pixel); 
+       ++it;
+      }
+
+    // Copy the rest
+    unsigned int position=0;
+    while(position< m_PointList.size())
+      {
+       for (unsigned int i=0; i <SpaceDimension; i++)
+         pixel[i]=m_PointList[position][i];
+       it.Set(pixel); 
+       ++it;
+       ++position;
+      }
+    
+    // last points are the first
+    for (unsigned int j=0; j<4;j++)
+      {
+       for (unsigned int i=0; i <SpaceDimension; i++)
+         pixel[i]=m_PointList[j][i];
+       it.Set(pixel); 
+       ++it;
+      }        
+
+    // -------------------------------
+    // Set 1D image to vectorInterpolator
+    m_Interpolator->SetInputImage(pointListImage);
+   
+
+    // -------------------------------
+    // Evaluate at phase value
+    typename PointListImageType::PointType t;
+    t[0]=inputPoint[ImageDimension-1];
+
+    // Inside valid region?
+    if ( (t[0] >= 0) &&
+        (t[0] < m_PointList.size()) )
+      {
+       pixel= m_Interpolator->Evaluate(t);
+       OutputPointType outputPoint;
+       for (unsigned int i=0; i < SpaceDimension; i++)
+         outputPoint[i]=pixel[i];
+       outputPoint[ImageDimension-1]=t[0];
+       return outputPoint;
+      }
+    // No displacement
+    else return inputPoint;
+        
+  }
+
+  
+} // namespace clitk
+
+#endif
diff --git a/registration/clitkPointListWriter.h b/registration/clitkPointListWriter.h
new file mode 100644 (file)
index 0000000..efe866c
--- /dev/null
@@ -0,0 +1,78 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkPointListWriter_h
+#define __clitkPointListWriter_h
+#include "clitkPointListWriter.h"
+
+namespace clitk
+{
+
+
+  template <unsigned int Dimension>
+  class ITK_EXPORT PointListWriter : 
+    public itk::LightObject 
+  {
+  public:
+    //------------------------------------
+    // Standard itk typedefs
+    //-----------------------------------
+    typedef PointListWriter                     Self;
+    typedef LightObject                         Superclass;
+    typedef itk::SmartPointer<Self>             Pointer;
+    typedef itk::SmartPointer<const Self>       ConstPointer;
+
+    /** Method for creation through the object factory. */
+    itkNewMacro(Self); 
+
+    /** Run-time type information (and related methods). */
+    itkTypeMacro(PointListWriter, LightObject); 
+
+    // Typedefs
+    typedef itk::Point<double, Dimension> PointType;
+    typedef std::vector<PointType> PointListType;
+    typedef std::vector< PointListType> PointListsType; 
+    typedef itk::Vector<float, Dimension> DisplacementType;
+    typedef std::vector<DisplacementType> DisplacementListType;
+    typedef std::vector< DisplacementListType> DisplacementListsType;   
+
+    // Members
+    void Write(const  PointListType & , const  std::string &);
+    void Write(const  PointListsType & , char** );
+    void Write(const  PointListsType & , const  std::string &){;};
+
+    void Write(const  DisplacementListType & , const  std::string &);
+    void Write(const  DisplacementListsType & , char**);
+    void Write(const  DisplacementListsType & , const  std::string &){;};
+
+    
+  protected:
+    
+    // Constructor & Destructor+
+    PointListWriter();
+    ~PointListWriter(){};
+
+
+  };
+
+} // namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkPointListWriter.txx"
+#endif
+
+#endif
diff --git a/registration/clitkPointListWriter.txx b/registration/clitkPointListWriter.txx
new file mode 100644 (file)
index 0000000..faefeed
--- /dev/null
@@ -0,0 +1,90 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkPointListWriter_txx
+#define __clitkPointListWriter_txx
+#include "clitkPointListWriter.h"
+
+namespace clitk
+{
+
+  template<unsigned int Dimension>
+  PointListWriter< Dimension >
+  ::PointListWriter()
+  {
+    
+  }
+
+  template<unsigned int Dimension>
+  void
+  PointListWriter< Dimension >
+  ::Write(const PointListType& list, const std::string& filename )
+  {
+    std::ofstream os;
+    openFileForWriting(os, filename);
+    
+    for (unsigned int pointIndex=0; pointIndex<list.size(); pointIndex++)
+      {        
+       os << list[pointIndex][0];
+       for (unsigned int dim=1; dim<Dimension; dim++)
+         os <<"\t"<< list[pointIndex][dim];
+       os<<std::endl;
+      }
+  }
+  
+  
+  template<unsigned int Dimension>
+  void
+  PointListWriter< Dimension >
+  ::Write(const DisplacementListType& list, const std::string& filename )
+  {
+    std::ofstream os;
+    openFileForWriting(os, filename);
+    
+    for (unsigned int pointIndex=0; pointIndex<list.size(); pointIndex++)
+      {        
+       os << list[pointIndex][0];
+       for (unsigned int dim=1; dim<Dimension; dim++)
+         os <<"\t"<< list[pointIndex][dim];
+       os<<std::endl;
+      }
+  }
+  
+  
+  template<unsigned int Dimension>
+  void 
+  PointListWriter< Dimension >
+  ::Write(const PointListsType& lists, char** filename)
+  {
+    for (unsigned int number =0; number<lists.size(); number++)
+      Write(lists[number],filename[number]);
+  }
+
+
+  template<unsigned int Dimension>
+  void 
+  PointListWriter< Dimension >
+  ::Write(const DisplacementListsType& lists, char** filename)
+  {
+    for (unsigned int number =0; number<lists.size(); number++)
+      Write(lists[number],filename[number]);
+  }
+
+
+}// clitk
+
+#endif // PointListWriter
diff --git a/registration/clitkPointTrajectory.cxx b/registration/clitkPointTrajectory.cxx
new file mode 100755 (executable)
index 0000000..cb0f203
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkPointTrajectory.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkPointTrajectory_ggo.h"
+#include "clitkIO.h"
+#include "clitkPointTrajectoryGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkPointTrajectory, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::PointTrajectoryGenericFilter::Pointer genericFilter=clitk::PointTrajectoryGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkPointTrajectory.ggo b/registration/clitkPointTrajectory.ggo
new file mode 100755 (executable)
index 0000000..b95e0c3
--- /dev/null
@@ -0,0 +1,26 @@
+#File clitkPointTrajectory.ggo
+Package "clitkPointTrajectory"
+version "1.0"
+purpose "Compute the cyclic trajectory of a point based input transform. The transform can be given by N lists of (manually identified) landmarks, a 4DDVF or a ST transform. Interpolation is performed between "
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+section "IO"
+
+option "ref"           r       "Reference point list"                          string          no      
+option "phaseIncrement"        p       "Phase step size for the trajectory [0,10)"     double          no      default="0.1"
+option "trajectory"            o       "Base filename for the trajectory files(+pointNumber) "          string         yes
+
+
+section "Transform: either given n lists of points; a 4DVF or the coefficient image of a spatiotemporal transform"
+option         "transform"     t       "Transform type: 0=points, 1=4DVF, 2=coeff"     int     no      default="0"
+option  "points"       -       "0:Lists of points"                                     string          no multiple
+option  "input"                i       "1,2: 4DVF or coeff image"              string          no
+option         "interpVF"      -       "0,1: Interpolation: 0=NN, 1=Linear, 2=BSpline, 3=BLUT" int     no  default="1"
+option         "interpVFOrder" -       "0,1: Order if BLUT or BSpline (0-5)"                   int     no  default="3"
+option "interpVFSF"    -       "0,1: Sampling factor if BLUT"                          int     no  default="20"
+option  "order"        -       "2: Spline order"                                       int             multiple        no 
+option  "mask"         m       "2: Mask image filename"                                string          no 
+option  "spacing"      -       "2: Spacing of the ref image for the sampling factor"   double          no      default="2" 
+option  "shape"                -       "2: Shape of the transform: 0=egg, 1=diamond"           int             no      default="0" 
diff --git a/registration/clitkPointTrajectoryGenericFilter.cxx b/registration/clitkPointTrajectoryGenericFilter.cxx
new file mode 100755 (executable)
index 0000000..dba4c00
--- /dev/null
@@ -0,0 +1,380 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkPointTrajectoryGenericFilter_cxx
+#define clitkPointTrajectoryGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkPointTrajectoryGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkPointTrajectoryGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  PointTrajectoryGenericFilter::PointTrajectoryGenericFilter()
+  {
+    m_Verbose=false;
+    //    m_InputFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void PointTrajectoryGenericFilter::Update()
+  {
+    // ImageTypes
+    const unsigned int ImageDimension=4;
+    const unsigned int SpaceDimension=3;
+    typedef itk::Vector<double, SpaceDimension> CoefficientPixelType;
+    typedef itk::Vector<float, SpaceDimension> VectorPixelType;
+    typedef itk::Image<CoefficientPixelType, ImageDimension> CoefficientImageType;
+    typedef itk::Image<VectorPixelType, ImageDimension> VectorFieldType;
+  
+
+    // -----------------------------------------------
+    // Reference Point List 3D
+    // -----------------------------------------------
+    typedef itk::Point<double, SpaceDimension> SpacePointType;
+    typedef clitk::List<SpacePointType> PointListType;
+    PointListType referencePointList;
+    if (m_Verbose) std::cout<<"Reference point list:"<<std::endl;
+    referencePointList=PointListType(m_ArgsInfo.ref_arg, m_Verbose);
+
+
+    // -----------------------------------------------
+    // Transform: based on points, 4DVF, spatio-Temporal transform 
+    // -----------------------------------------------
+    typedef itk::Transform<double, 4, 4> TransformType;
+    TransformType::Pointer transform;
+    switch (m_ArgsInfo.transform_arg)
+      {
+       // ==========================
+       // List of points
+       // ==========================
+      case 0: 
+       {
+         //-----------------------------
+         // Input point lists
+         //-----------------------------   
+         typedef itk::Point<double, SpaceDimension> PointType;
+         typedef clitk::List<PointType> PointListType;
+         typedef clitk::Lists<PointType> PointListsType;
+         PointListsType inputPointLists, sortedPointLists;
+         
+         // Read the lists
+         for (unsigned int i=0; i<m_ArgsInfo.points_given; i++)
+           inputPointLists.push_back(PointListType(m_ArgsInfo.points_arg[i], m_Verbose) );
+       
+         // Convert/sort the lists
+         sortedPointLists.resize(inputPointLists[0].size());
+         for (unsigned int i=0; i<inputPointLists[0].size(); i++)
+           {
+             sortedPointLists[i].push_back(referencePointList[i]);
+             for (unsigned int j=0; j<inputPointLists.size(); j++)
+               {
+                 sortedPointLists[i].push_back(inputPointLists[j][i]);
+               }
+           }
+                                           
+         // Point list Transform
+         typedef clitk::PointListTransform<double, ImageDimension,ImageDimension> PointListTransformType;
+         PointListTransformType::Pointer pointListTransform=PointListTransformType::New();
+         pointListTransform->SetPointLists(sortedPointLists);
+         
+         // Vector Interpolator
+         typedef PointListTransformType::PointListImageType PointListImageType;
+         typedef clitk::GenericVectorInterpolator<args_info_clitkPointTrajectory,PointListImageType, double> GenericVectorInterpolatorType;
+         GenericVectorInterpolatorType::Pointer genericInterpolator=GenericVectorInterpolatorType::New();
+         genericInterpolator->SetArgsInfo(m_ArgsInfo);
+         typedef itk::VectorInterpolateImageFunction<PointListImageType, double> InterpolatorType; 
+         InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
+         pointListTransform->SetInterpolator(interpolator);
+         transform=pointListTransform;
+
+         break;
+       }
+
+       // ==========================
+       // 4D vector field
+       // ==========================
+      case 1: 
+       {
+         // Deformation field transform
+         typedef clitk::DeformationFieldTransform<double, ImageDimension,ImageDimension, SpaceDimension> DeformationFieldTransformType;
+         DeformationFieldTransformType::Pointer deformationFieldTransform=DeformationFieldTransformType::New();
+         
+         // The deformation field
+         typedef DeformationFieldTransformType::DeformationFieldType DeformationFieldType;
+         typedef itk::ImageFileReader<DeformationFieldType> InputReaderType;
+         InputReaderType::Pointer reader = InputReaderType::New();
+         reader->SetFileName( m_ArgsInfo.input_arg);
+         reader->Update();
+         DeformationFieldType::Pointer input= reader->GetOutput();
+         deformationFieldTransform->SetDeformationField(input);
+         
+         // Vector Interpolator
+         typedef clitk::GenericVectorInterpolator<args_info_clitkPointTrajectory,DeformationFieldType, double> GenericVectorInterpolatorType;
+         GenericVectorInterpolatorType::Pointer genericInterpolator=GenericVectorInterpolatorType::New();
+         genericInterpolator->SetArgsInfo(m_ArgsInfo);
+         typedef itk::VectorInterpolateImageFunction<DeformationFieldType, double> InterpolatorType; 
+         InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
+         deformationFieldTransform->SetInterpolator(interpolator);
+         transform=deformationFieldTransform;
+
+         break;
+       }
+
+       // ==========================   
+       // Spatio-Temporal transform
+       // ==========================
+      case 2:
+       {       
+         // S-T transform      
+         typedef clitk::ShapedBLUTSpatioTemporalDeformableTransform< double, ImageDimension, ImageDimension > TransformType; 
+         TransformType::Pointer spatioTemporalTransform = TransformType::New();
+
+
+         // Spline orders:  Default is cubic splines
+         CoefficientImageType::RegionType::SizeType splineOrders ;
+         splineOrders.Fill(3);
+         if (m_ArgsInfo.order_given)
+           for(unsigned int i=0; i<ImageDimension;i++) 
+             splineOrders[i]=m_ArgsInfo.order_arg[i];
+         if (m_Verbose) std::cout<<"Setting the spline orders  to "<<splineOrders<<"..."<<std::endl;
+         
+         // Coefficient image
+         typedef itk::ImageFileReader<CoefficientImageType> InputReaderType;
+         InputReaderType::Pointer reader = InputReaderType::New();
+         reader->SetFileName( m_ArgsInfo.input_arg);
+         reader->Update();
+         CoefficientImageType::Pointer input= reader->GetOutput();
+         //      itk::Vector<double,3> vector;
+         //      vector.Fill(0.);
+         //      vector[2]=100;
+         //      input->FillBuffer(vector);
+
+         // Mask
+         typedef itk::ImageMaskSpatialObject<  ImageDimension >   MaskType;
+         MaskType::Pointer  spatialObjectMask=NULL;
+         if (m_ArgsInfo.mask_given)
+           {
+             typedef itk::Image< unsigned char, ImageDimension >   ImageMaskType;
+             typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
+             MaskReaderType::Pointer  maskReader = MaskReaderType::New();
+             maskReader->SetFileName(m_ArgsInfo.mask_arg);
+             
+             try 
+               { 
+                 maskReader->Update(); 
+               } 
+             catch( itk::ExceptionObject & err ) 
+               { 
+                 std::cerr << "ExceptionObject caught while reading mask !" << std::endl; 
+                 std::cerr << err << std::endl; 
+                 return;
+               } 
+             if (m_Verbose)std::cout <<"Mask was read..." <<std::endl;
+             
+             // Set the image to the spatialObject
+             spatialObjectMask = MaskType::New();
+             spatialObjectMask->SetImage( maskReader->GetOutput() );
+           }
+         
+         // Samplingfactors
+         CoefficientImageType::SizeType samplingFactors; 
+         for (unsigned int i=0; i< ImageDimension-1; i++)
+           {   
+             samplingFactors[i]= (int) ( input->GetSpacing()[i]/ m_ArgsInfo.spacing_arg);
+             if (m_Verbose) std::cout<<"Setting sampling factor "<<i<<" to "<<samplingFactors[i]<<"..."<<std::endl;
+           }
+         samplingFactors[ImageDimension-1]= (int) ( input->GetSpacing()[ImageDimension-1]/ m_ArgsInfo.phaseIncrement_arg);
+         if (m_Verbose) std::cout<<"Setting sampling factor "<<ImageDimension-1<<" to "<<samplingFactors[ImageDimension-1]<<"..."<<std::endl;
+         if( (m_ArgsInfo.shape_arg==3) |
+             (m_ArgsInfo.shape_arg==4) |
+             (m_ArgsInfo.shape_arg==6) |
+             (m_ArgsInfo.shape_arg==8)
+             ) samplingFactors[ImageDimension-1]*=2.5;
+         
+         // Set
+         spatioTemporalTransform->SetTransformShape(m_ArgsInfo.shape_arg);
+         spatioTemporalTransform->SetSplineOrders(splineOrders);
+         spatioTemporalTransform->SetMask(spatialObjectMask);
+         spatioTemporalTransform->SetLUTSamplingFactors(samplingFactors);
+         spatioTemporalTransform->SetCoefficientImage(input);
+         transform=spatioTemporalTransform;
+         
+         break;
+       }
+
+//     // ==========================   
+//     // Spatio-Temporal transform
+//     // ==========================
+//       case 3:
+//     {       
+//       // S-T transform      
+//       typedef clitk::BSplineSpatioTemporalDeformableTransform< double, ImageDimension, ImageDimension > TransformType; 
+//       TransformType::Pointer spatioTemporalTransform = TransformType::New();
+
+
+//       // Spline orders:  Default is cubic splines
+//       CoefficientImageType::RegionType::SizeType splineOrders ;
+//       splineOrders.Fill(3);
+//       if (m_ArgsInfo.order_given)
+//         for(unsigned int i=0; i<ImageDimension;i++) 
+//           splineOrders[i]=m_ArgsInfo.order_arg[i];
+//       if (m_Verbose) std::cout<<"Setting the spline orders  to "<<splineOrders<<"..."<<std::endl;
+         
+//       // Coefficient image
+//       typedef itk::ImageFileReader<CoefficientImageType> InputReaderType;
+//       InputReaderType::Pointer reader = InputReaderType::New();
+//       reader->SetFileName( m_ArgsInfo.input_arg);
+//       reader->Update();
+//       CoefficientImageType::Pointer input= reader->GetOutput();
+//       //      itk::Vector<double,3> vector;
+//       //      vector.Fill(0.);
+//       //      vector[2]=100;
+//       //      input->FillBuffer(vector);
+         
+//       // Mask
+//       typedef itk::ImageMaskSpatialObject<  ImageDimension >   MaskType;
+//       MaskType::Pointer  spatialObjectMask=NULL;
+//       if (m_ArgsInfo.mask_given)
+//         {
+//           typedef itk::Image< unsigned char, ImageDimension >   ImageMaskType;
+//           typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
+//           MaskReaderType::Pointer  maskReader = MaskReaderType::New();
+//           maskReader->SetFileName(m_ArgsInfo.mask_arg);
+             
+//           try 
+//             { 
+//               maskReader->Update(); 
+//             } 
+//           catch( itk::ExceptionObject & err ) 
+//             { 
+//               std::cerr << "ExceptionObject caught while reading mask !" << std::endl; 
+//               std::cerr << err << std::endl; 
+//               return;
+//             } 
+//           if (m_Verbose)std::cout <<"Mask was read..." <<std::endl;
+             
+//           // Set the image to the spatialObject
+//           spatialObjectMask = MaskType::New();
+//           spatialObjectMask->SetImage( maskReader->GetOutput() );
+//         }
+         
+//       // Samplingfactors
+//       CoefficientImageType::SizeType samplingFactors; 
+//       for (unsigned int i=0; i< ImageDimension-1; i++)
+//         {   
+//           samplingFactors[i]= (int) ( input->GetSpacing()[i]/ m_ArgsInfo.spacing_arg);
+//           if (m_Verbose) std::cout<<"Setting sampling factor "<<i<<" to "<<samplingFactors[i]<<"..."<<std::endl;
+//         }
+//       samplingFactors[ImageDimension-1]= (int) ( input->GetSpacing()[ImageDimension-1]/ m_ArgsInfo.phaseIncrement_arg);
+//       if (m_Verbose) std::cout<<"Setting sampling factor "<<ImageDimension-1<<" to "<<samplingFactors[ImageDimension-1]<<"..."<<std::endl;
+         
+//       // Set
+//       //spatioTemporalTransform->SetTransformShape(m_ArgsInfo.shape_arg);
+//       spatioTemporalTransform->SetSplineOrders(splineOrders);
+//       spatioTemporalTransform->SetMask(spatialObjectMask);
+//       spatioTemporalTransform->SetLUTSamplingFactors(samplingFactors);
+//       spatioTemporalTransform->SetCoefficientImage(input);
+//       transform=spatioTemporalTransform;
+
+//       break;
+//     }
+      }
+         
+    
+    // -----------------------------------------------
+    // Construct Spatio-Temporal Point lists 4D
+    // -----------------------------------------------
+    typedef itk::Point<double, ImageDimension> SpaceTimePointType;
+    typedef clitk::Lists<SpaceTimePointType> PointListsType;
+    PointListsType pointLists(referencePointList.size());
+    SpaceTimePointType spaceTimePoint;
+    double phase;
+    for (unsigned int i=0; i<referencePointList.size(); i++)
+      {
+       for (unsigned int d=0; d<SpaceDimension; d++)
+         {
+           spaceTimePoint[d]=referencePointList[i][d];
+         }
+       phase=0;
+       while (phase<10.)
+         {
+           spaceTimePoint[ImageDimension-1]=phase;
+           pointLists[i].push_back(spaceTimePoint);
+           phase+=m_ArgsInfo.phaseIncrement_arg;
+         }
+      }
+
+
+    // -----------------------------------------------
+    // Transform Points
+    // -----------------------------------------------
+    typedef itk::Vector<double, ImageDimension> VectorType;
+    typedef clitk::List<VectorType> VectorListType;
+    typedef clitk::Lists<VectorType> VectorListsType;
+    VectorListsType displacementLists(pointLists.size());
+    VectorType displacement;
+    for (unsigned int i=0; i<pointLists.size(); i++)
+      {
+       if (m_Verbose) std::cout<<"Transforming point "<<pointLists[i][0]<<"..."<<std::endl;
+       for (unsigned int j=0; j<pointLists[i].size(); j++)
+         {
+           spaceTimePoint= transform->TransformPoint(pointLists[i][j]);
+           if (m_Verbose) std::cout<<"Transformed point "<<spaceTimePoint<<"..."<<std::endl;
+           displacement=spaceTimePoint-pointLists[i][j];
+           displacementLists[i].push_back(displacement);
+         }
+      }
+
+
+    // -----------------------------------------------
+    // Write displacements
+    // -----------------------------------------------
+    std::vector<std::string> filenames;
+    for (unsigned int i=0;i<displacementLists.size();i++)
+      {
+       std::ostringstream number_ostr;
+       number_ostr << i;
+       std::string number_str;
+       if (i<10)  number_str=  "0"+number_ostr.str();
+       else number_str =  number_ostr.str();
+       filenames.push_back(m_ArgsInfo.trajectory_arg+number_str);
+      }
+    displacementLists.Write(filenames, m_Verbose );
+  
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkPointTrajectoryGenericFilter_cxx
diff --git a/registration/clitkPointTrajectoryGenericFilter.h b/registration/clitkPointTrajectoryGenericFilter.h
new file mode 100755 (executable)
index 0000000..2172ea5
--- /dev/null
@@ -0,0 +1,110 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkPointTrajectoryGenericFilter_h
+#define clitkPointTrajectoryGenericFilter_h
+
+/* =================================================
+ * @file   clitkPointTrajectoryGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkPointTrajectory_ggo.h"
+#include "clitkPointListTransform.h"
+#include "clitkDeformationFieldTransform.h"
+#include "clitkShapedBLUTSpatioTemporalDeformableTransform.h"
+#include "clitkLists.h"
+#include "clitkGenericVectorInterpolator.h"
+
+
+//itk include
+#include "itkLightObject.h"
+#include "itkTransform.h"
+#include "itkImageMaskSpatialObject.h"
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT PointTrajectoryGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef PointTrajectoryGenericFilter       Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( PointTrajectoryGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkPointTrajectory & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    PointTrajectoryGenericFilter();
+    ~PointTrajectoryGenericFilter() {};
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkPointTrajectory m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_InputFileName;
+
+  };
+
+
+} // end namespace clitk
+
+
+#endif // #define clitkPointTrajectoryGenericFilter_h
diff --git a/registration/clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.h b/registration/clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.h
new file mode 100644 (file)
index 0000000..a43b2ed
--- /dev/null
@@ -0,0 +1,94 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter_h
+#define __clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter_h
+#include "clitkSpatioTemporalMultiResolutionPyramidImageFilter.h"
+#include "vnl/vnl_matrix.h"
+
+namespace clitk
+{
+
+template <
+  class TInputImage, 
+  class TOutputImage
+  >
+class ITK_EXPORT RecursiveSpatioTemporalMultiResolutionPyramidImageFilter : 
+    public SpatioTemporalMultiResolutionPyramidImageFilter< TInputImage, TOutputImage >
+{
+public:
+  /** Standard class typedefs. */
+  typedef RecursiveSpatioTemporalMultiResolutionPyramidImageFilter  Self;
+  typedef SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage,TOutputImage>  Superclass;
+  typedef itk::SmartPointer<Self>                          Pointer;
+  typedef itk::SmartPointer<const Self>                    ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(RecursiveSpatioTemporalMultiResolutionPyramidImageFilter, 
+               SpatioTemporalMultiResolutionPyramidImageFilter);
+
+  /** ImageDimension enumeration. */
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      Superclass::ImageDimension);
+
+  /** Inherit types from the superclass.. */
+  typedef typename Superclass::InputImageType         InputImageType;
+  typedef typename Superclass::OutputImageType        OutputImageType;
+  typedef typename Superclass::InputImagePointer      InputImagePointer;
+  typedef typename Superclass::OutputImagePointer     OutputImagePointer;
+  typedef typename Superclass::InputImageConstPointer InputImageConstPointer;
+
+  /** Given one output whose requested region has been set, 
+   * this method sets the requtested region for the remaining
+   * output images.
+   * The original documentation of this method is below.
+   * \sa ProcessObject::GenerateOutputRequestedRegion(); */
+  virtual void GenerateOutputRequestedRegion(itk::DataObject *output);
+
+  /** RecursiveSpatioTemporalMultiResolutionPyramidImageFilter requires a larger input
+   * requested region than the output requested regions to accomdate the
+   * shrinkage and smoothing operations.  As such,
+   * SpatioTemporalMultiResolutionPyramidImageFilter needs to provide an implementation for
+   * GenerateInputRequestedRegion().  The original documentation of this
+   * method is below.  \sa ProcessObject::GenerateInputRequestedRegion() */
+  virtual void GenerateInputRequestedRegion();
+
+protected:
+  RecursiveSpatioTemporalMultiResolutionPyramidImageFilter();
+  ~RecursiveSpatioTemporalMultiResolutionPyramidImageFilter() {};
+  void PrintSelf(std::ostream&os, itk::Indent indent) const;
+
+  /** Generate the output data. */
+  void GenerateData();
+
+private:
+  RecursiveSpatioTemporalMultiResolutionPyramidImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+};
+
+
+} // namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.txx"
+#endif
+
+#endif
diff --git a/registration/clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.txx b/registration/clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.txx
new file mode 100644 (file)
index 0000000..b6c2abb
--- /dev/null
@@ -0,0 +1,479 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter_txx
+#define __clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter_txx
+#include "clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.h"
+#include "itkShrinkImageFilter.h"
+#include "itkGaussianOperator.h"
+#include "itkCastImageFilter.h"
+#include "itkDiscreteGaussianImageFilter.h"
+#include "itkExceptionObject.h"
+#include "itkResampleImageFilter.h"
+#include "itkShrinkImageFilter.h"
+#include "itkIdentityTransform.h"
+
+#include "vnl/vnl_math.h"
+
+namespace clitk
+{
+
+/**
+ * Constructor
+ */
+template <class TInputImage, class TOutputImage>
+RecursiveSpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::RecursiveSpatioTemporalMultiResolutionPyramidImageFilter()
+{
+  this->Superclass::m_UseShrinkImageFilter = true;
+}
+
+/**
+ * GenerateData
+ */
+template <class TInputImage, class TOutputImage>
+void
+RecursiveSpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::GenerateData()
+{
+
+  if( !this->IsScheduleDownwardDivisible( this->GetSchedule() ) )
+    {
+    // use the Superclass implemenation
+    this->Superclass::GenerateData();
+    return;
+    }
+
+  // Get the input and output pointers
+  InputImageConstPointer  inputPtr = this->GetInput();
+
+  // Create caster, smoother and resampleShrink filters
+  typedef itk::CastImageFilter<TInputImage, TOutputImage>              CasterType;
+  typedef itk::CastImageFilter<TOutputImage, TOutputImage>             CopierType;
+  typedef itk::DiscreteGaussianImageFilter<TOutputImage, TOutputImage> SmootherType;
+
+  typedef itk::ImageToImageFilter<TOutputImage,TOutputImage>           ImageToImageType;
+  typedef itk::ResampleImageFilter<TOutputImage,TOutputImage>          ResampleShrinkerType;
+  typedef itk::ShrinkImageFilter<TOutputImage,TOutputImage>            ShrinkerType;
+
+  typename CasterType::Pointer   caster   = CasterType::New();
+  typename CopierType::Pointer   copier   = CopierType::New();
+  typename SmootherType::Pointer smoother = SmootherType::New();
+
+
+  typename ImageToImageType::Pointer shrinkerFilter;
+  //
+  // only one of these pointers is going to be valid, depending on the
+  // value of UseShrinkImageFilter flag
+  typename ResampleShrinkerType::Pointer resampleShrinker;
+  typename ShrinkerType::Pointer shrinker;
+
+  if(this->GetUseShrinkImageFilter())
+    {
+    shrinker = ShrinkerType::New();
+    shrinkerFilter = shrinker.GetPointer();
+    }
+  else
+    {
+    resampleShrinker = ResampleShrinkerType::New();
+    typedef itk::LinearInterpolateImageFunction< OutputImageType, double >
+      LinearInterpolatorType;
+    typename LinearInterpolatorType::Pointer interpolator = 
+      LinearInterpolatorType::New();
+    typedef itk::IdentityTransform<double,OutputImageType::ImageDimension>
+      IdentityTransformType;
+    typename IdentityTransformType::Pointer identityTransform =
+      IdentityTransformType::New();
+    resampleShrinker->SetInterpolator( interpolator );
+    resampleShrinker->SetDefaultPixelValue( 0 );
+    resampleShrinker->SetTransform(identityTransform);
+    shrinkerFilter = resampleShrinker.GetPointer();
+    }
+
+  int ilevel;
+  unsigned int idim;
+  unsigned int factors[ImageDimension];
+  double       variance[ImageDimension];
+
+  bool         allOnes;
+  OutputImagePointer   outputPtr;
+  OutputImagePointer swapPtr;
+  typename TOutputImage::RegionType  LPRegion;
+
+  smoother->SetUseImageSpacing( false );
+  smoother->SetMaximumError( this->GetMaximumError() );
+  shrinkerFilter->SetInput( smoother->GetOutput() );
+
+  
+  // recursively compute outputs starting from the last one
+  for( ilevel = this->GetNumberOfLevels() - 1; ilevel > -1; ilevel--)
+    {
+
+    this->UpdateProgress( 1.0 - static_cast<float>( 1 + ilevel ) /
+                          static_cast<float>( this->GetNumberOfLevels() ) );
+
+    // Allocate memory for each output
+    outputPtr = this->GetOutput( ilevel );
+    outputPtr->SetBufferedRegion( outputPtr->GetRequestedRegion() );
+    outputPtr->Allocate();
+    
+    // cached a copy of the largest possible region
+    LPRegion = outputPtr->GetLargestPossibleRegion();
+
+    // Check shrink factors and compute variances
+    allOnes = true;
+    for( idim = 0; idim < ImageDimension; idim++ )
+      {
+      if( ilevel == static_cast<int>(this->GetNumberOfLevels()) - 1)
+        {
+        factors[idim] = this->GetSchedule()[ilevel][idim];
+        }
+      else
+        {
+        factors[idim] = this->GetSchedule()[ilevel][idim] /
+          this->GetSchedule()[ilevel+1][idim];
+        }
+      variance[idim] = vnl_math_sqr( 0.5 * 
+                                     static_cast<float>( factors[idim] ) );
+      if( factors[idim] != 1 ) 
+        { 
+        allOnes = false; 
+        }
+      else
+        {
+        variance[idim] = 0.0;
+        }
+      }
+
+
+    if( allOnes && ilevel == static_cast<int>(this->GetNumberOfLevels()) - 1 )
+      {
+      // just copy the input over
+      caster->SetInput( inputPtr );
+      caster->GraftOutput( outputPtr );
+      // ensure only the requested region is updated
+      caster->UpdateOutputInformation();
+      caster->GetOutput()->SetRequestedRegion(outputPtr->GetRequestedRegion());
+      caster->GetOutput()->PropagateRequestedRegion();
+      caster->GetOutput()->UpdateOutputData();
+
+      swapPtr = caster->GetOutput();
+
+
+      }
+    else if( allOnes )
+      {
+      // just copy the data over
+      copier->SetInput( swapPtr );
+      copier->GraftOutput( outputPtr );
+      // ensure only the requested region is updated
+      copier->GetOutput()->UpdateOutputInformation();
+      copier->GetOutput()->SetRequestedRegion(outputPtr->GetRequestedRegion());
+      copier->GetOutput()->PropagateRequestedRegion();
+      copier->GetOutput()->UpdateOutputData();
+
+      swapPtr = copier->GetOutput();
+        
+      }
+    else
+      {
+      if( ilevel == static_cast<int>(this->GetNumberOfLevels()) - 1 )
+        {
+        // use caster -> smoother -> shrinker piepline
+        caster->SetInput( inputPtr );
+        smoother->SetInput( caster->GetOutput() );
+        }
+      else
+        {
+        // use smoother -> shrinker pipeline
+        smoother->SetInput( swapPtr );
+        }
+
+      smoother->SetVariance( variance );
+
+      //      shrinker->SetShrinkFactors( factors );
+      //      shrinker->GraftOutput( outputPtr );
+      if(!this->GetUseShrinkImageFilter())
+        {
+        resampleShrinker->SetOutputParametersFromImage(outputPtr);
+        }
+      else
+        {
+        shrinker->SetShrinkFactors(factors);
+        }
+      shrinkerFilter->GraftOutput(outputPtr);
+      shrinkerFilter->Modified();
+      // ensure only the requested region is updated
+      shrinkerFilter->GetOutput()->UpdateOutputInformation();
+      shrinkerFilter->GetOutput()->SetRequestedRegion(outputPtr->GetRequestedRegion());
+      shrinkerFilter->GetOutput()->PropagateRequestedRegion();
+      shrinkerFilter->GetOutput()->UpdateOutputData();
+
+      swapPtr = shrinkerFilter->GetOutput();
+
+      }
+
+    // graft pipeline output back onto this filter's output
+    swapPtr->SetLargestPossibleRegion( LPRegion );
+    this->GraftNthOutput( ilevel, swapPtr );
+
+    // disconnect from pipeline to stop cycle
+    swapPtr->DisconnectPipeline();
+
+    }
+
+}
+
+/**
+ * PrintSelf method
+ */
+template <class TInputImage, class TOutputImage>
+void
+RecursiveSpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os,indent);
+}
+
+
+/* 
+ * GenerateOutputRequestedRegion
+ */
+template <class TInputImage, class TOutputImage>
+void
+RecursiveSpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::GenerateOutputRequestedRegion(itk::DataObject * ptr )
+{
+
+  // call the superclass's implementation of this method
+  Superclass::GenerateOutputRequestedRegion( ptr );
+
+  TOutputImage * refOutputPtr = static_cast<TOutputImage*>( ptr );
+  if( !refOutputPtr )
+    {
+    itkExceptionMacro( << "Could not cast ptr to TOutputImage*." );
+    }
+
+  // find the index for this output
+  unsigned int refLevel;
+  refLevel = refOutputPtr->GetSourceOutputIndex();
+
+  typedef typename TOutputImage::PixelType                 OutputPixelType;
+  typedef itk::GaussianOperator<OutputPixelType,ImageDimension> OperatorType;
+
+  OperatorType * oper = new OperatorType;
+  oper->SetMaximumError( this->GetMaximumError() );
+
+  typedef typename OutputImageType::SizeType    SizeType;
+  typedef typename SizeType::SizeValueType      SizeValueType;
+  typedef typename OutputImageType::IndexType   IndexType;
+  typedef typename IndexType::IndexValueType    IndexValueType;
+  typedef typename OutputImageType::RegionType  RegionType;
+
+  int ilevel, idim;
+  unsigned int factors[ImageDimension];
+  
+  typename TInputImage::SizeType radius;
+
+  RegionType requestedRegion;
+  SizeType   requestedSize;
+  IndexType  requestedIndex;
+
+  // compute requested regions for lower levels
+  for( ilevel = refLevel + 1; ilevel < static_cast<int>(this->GetNumberOfLevels()); 
+       ilevel++ )
+    {
+
+    requestedRegion = this->GetOutput( ilevel - 1 )->GetRequestedRegion();
+    requestedSize = requestedRegion.GetSize();
+    requestedIndex = requestedRegion.GetIndex();
+
+    for( idim = 0; idim < static_cast<int>(ImageDimension); idim++ )
+      {
+      factors[idim] = this->GetSchedule()[ilevel-1][idim] / this->GetSchedule()[ilevel][idim];
+
+      // take into account shrink component
+      requestedSize[idim] *= static_cast<SizeValueType>(factors[idim]);
+      requestedIndex[idim] *= static_cast<IndexValueType>(factors[idim]);
+      
+      // take into account smoothing component
+      if( factors[idim] > 1 )
+        {
+        oper->SetDirection( idim );
+        oper->SetVariance( vnl_math_sqr( 0.5 * 
+                                         static_cast<float>( factors[idim] ) ) );
+        oper->CreateDirectional();
+        radius[idim] = oper->GetRadius()[idim];
+        }
+      else
+        {
+        radius[idim] = 0;
+        }
+      }
+
+    requestedRegion.SetSize( requestedSize );
+    requestedRegion.SetIndex( requestedIndex );
+    requestedRegion.PadByRadius( radius );
+    requestedRegion.Crop( this->GetOutput(ilevel)->
+                          GetLargestPossibleRegion() );
+
+    this->GetOutput(ilevel)->SetRequestedRegion( requestedRegion );
+
+    }
+
+
+  // compute requested regions for higher levels
+  for( ilevel = refLevel - 1; ilevel > -1; ilevel-- )
+    {
+    requestedRegion = this->GetOutput( ilevel + 1 )->GetRequestedRegion();
+    requestedSize = requestedRegion.GetSize();
+    requestedIndex = requestedRegion.GetIndex();
+
+    for( idim = 0; idim < static_cast<int>(ImageDimension); idim++ )
+      {
+
+      factors[idim] = this->GetSchedule()[ilevel][idim] / this->GetSchedule()[ilevel+1][idim];
+      
+      // take into account smoothing component
+      if( factors[idim] > 1 )
+        {
+        oper->SetDirection( idim );
+        oper->SetVariance( vnl_math_sqr( 0.5 * 
+                                         static_cast<float>( factors[idim] ) ) );
+        oper->CreateDirectional();
+        radius[idim] = oper->GetRadius()[idim];
+        }
+      else
+        {
+        radius[idim] = 0;
+        }
+
+      requestedSize[idim] -= static_cast<SizeValueType>( 
+        2 * radius[idim] );
+      requestedIndex[idim] += radius[idim];
+      
+      // take into account shrink component
+      requestedSize[idim] = static_cast<SizeValueType>( vcl_floor(
+                                                          static_cast<double>(requestedSize[idim]) / 
+                                                          static_cast<double>(factors[idim]) ) );
+      if( requestedSize[idim] < 1 )
+        {
+        requestedSize[idim] = 1;
+        }
+      requestedIndex[idim] = static_cast<IndexValueType>( vcl_ceil(
+                                                            static_cast<double>(requestedIndex[idim]) /
+                                                            static_cast<double>(factors[idim]) ) );
+
+      }
+
+    requestedRegion.SetSize( requestedSize );
+    requestedRegion.SetIndex( requestedIndex );
+    requestedRegion.Crop( this->GetOutput(ilevel)->
+                          GetLargestPossibleRegion() );
+
+    this->GetOutput(ilevel)->SetRequestedRegion( requestedRegion );
+
+    }
+
+  // clean up
+  delete oper;
+
+}
+
+/** 
+ * GenerateInputRequestedRegion
+ */
+template <class TInputImage, class TOutputImage>
+void
+RecursiveSpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::GenerateInputRequestedRegion()
+{
+
+  // call the superclass' implementation of this method
+  Superclass::GenerateInputRequestedRegion();
+  
+  // get pointers to the input and output
+  InputImagePointer  inputPtr = 
+    const_cast< InputImageType *>( this->GetInput() );
+  if ( !inputPtr )
+    {
+    itkExceptionMacro( << "Input has not been set." );
+    }
+
+  // compute baseIndex and baseSize
+  typedef typename OutputImageType::SizeType    SizeType;
+  typedef typename SizeType::SizeValueType      SizeValueType;
+  typedef typename OutputImageType::IndexType   IndexType;
+  typedef typename IndexType::IndexValueType    IndexValueType;
+  typedef typename OutputImageType::RegionType  RegionType;
+
+  unsigned int refLevel = this->GetNumberOfLevels() - 1;
+  SizeType baseSize = this->GetOutput(refLevel)->GetRequestedRegion().GetSize();
+  IndexType baseIndex = this->GetOutput(refLevel)->GetRequestedRegion().GetIndex();
+  RegionType baseRegion;
+
+  unsigned int idim;
+  for( idim = 0; idim < ImageDimension; idim++ )
+    {
+    unsigned int factor = this->GetSchedule()[refLevel][idim];
+    baseIndex[idim] *= static_cast<IndexValueType>( factor );
+    baseSize[idim] *= static_cast<SizeValueType>( factor );
+    }
+  baseRegion.SetIndex( baseIndex );
+  baseRegion.SetSize( baseSize );
+
+  // compute requirements for the smoothing part
+  typedef typename TOutputImage::PixelType                 OutputPixelType;
+  typedef itk::GaussianOperator<OutputPixelType,ImageDimension> OperatorType;
+
+  OperatorType *oper = new OperatorType;
+
+  typename TInputImage::SizeType radius;
+
+  RegionType inputRequestedRegion = baseRegion;
+  refLevel = 0;
+
+  for( idim = 0; idim < TInputImage::ImageDimension; idim++ )
+    {
+    oper->SetDirection(idim);
+    oper->SetVariance( vnl_math_sqr( 0.5 * static_cast<float>(
+                                       this->GetSchedule()[refLevel][idim] ) ) );
+    oper->SetMaximumError( this->GetMaximumError() );
+    oper->CreateDirectional();
+    radius[idim] = oper->GetRadius()[idim];
+    if( this->GetSchedule()[refLevel][idim] <= 1 )
+      {
+      radius[idim] = 0;
+      }
+      
+    }
+  delete oper;
+
+  inputRequestedRegion.PadByRadius( radius );
+
+  // make sure the requested region is within the largest possible
+  inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() );
+  
+  // set the input requested region
+  inputPtr->SetRequestedRegion( inputRequestedRegion );
+
+}
+
+
+} // namespace clitk
+
+#endif
diff --git a/registration/clitkResampleBSplineDeformableTransform.cxx b/registration/clitkResampleBSplineDeformableTransform.cxx
new file mode 100644 (file)
index 0000000..68633af
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkResampleBSplineDeformableTransform.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkResampleBSplineDeformableTransform_ggo.h"
+#include "clitkIO.h"
+#include "clitkResampleBSplineDeformableTransformGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkResampleBSplineDeformableTransform, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::ResampleBSplineDeformableTransformGenericFilter::Pointer genericFilter=clitk::ResampleBSplineDeformableTransformGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkResampleBSplineDeformableTransform.ggo b/registration/clitkResampleBSplineDeformableTransform.ggo
new file mode 100644 (file)
index 0000000..0dc6054
--- /dev/null
@@ -0,0 +1,22 @@
+#File clitkResampleBSplineDeformableTransform.ggo
+Package "clitkResampleBSplineDeformableTransform"
+version "1.0"
+purpose "Resample the B-spline control point grid to given properties. Coefficients are resampled to values with the desired properties and reconverted to coefficients "
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+option "input"         i       "Input image filename"            string        yes
+option "output"        o       "Output image filename"           string        yes
+option "like"          -       "Resample output like this image" string        no              
+
+
+section "Output Image Properties"
+
+option "origin"                        -       "Origin for the output image"                   double          multiple no     
+option "size"                  -       "Size for the output image"                     int             multiple no           
+option "spacing"               -       "Spacing for the output image"                  double          multiple no            
+
+
+
+
diff --git a/registration/clitkResampleBSplineDeformableTransformGenericFilter.cxx b/registration/clitkResampleBSplineDeformableTransformGenericFilter.cxx
new file mode 100644 (file)
index 0000000..94c2411
--- /dev/null
@@ -0,0 +1,71 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkResampleBSplineDeformableTransformGenericFilter_cxx
+#define clitkResampleBSplineDeformableTransformGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkResampleBSplineDeformableTransformGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkResampleBSplineDeformableTransformGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  ResampleBSplineDeformableTransformGenericFilter::ResampleBSplineDeformableTransformGenericFilter()
+  {
+    m_Verbose=false;
+    m_InputFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void ResampleBSplineDeformableTransformGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension, Components;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_InputFileName, Dimension, PixelType, Components);
+
+    
+    // Call UpdateWithDim
+    if(Dimension==2) UpdateWithDim<2>(PixelType, Components);
+    else if(Dimension==3) UpdateWithDim<3>(PixelType, Components);
+    else if (Dimension==4)UpdateWithDim<4>(PixelType, Components); 
+    else 
+      {
+       std::cout<<"Error, Only for 2,3 or 4 Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+} //end clitk
+
+#endif  //#define clitkResampleBSplineDeformableTransformGenericFilter_cxx
diff --git a/registration/clitkResampleBSplineDeformableTransformGenericFilter.h b/registration/clitkResampleBSplineDeformableTransformGenericFilter.h
new file mode 100644 (file)
index 0000000..9415f93
--- /dev/null
@@ -0,0 +1,116 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkResampleBSplineDeformableTransformGenericFilter_h
+#define clitkResampleBSplineDeformableTransformGenericFilter_h
+
+/* =================================================
+ * @file   clitkResampleBSplineDeformableTransformGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkImageCommon.h"
+#include "clitkResampleBSplineDeformableTransform_ggo.h"
+#include "clitkResampleBSplineDeformableTransformImageFilter.h"
+
+//itk include
+#include "itkLightObject.h"
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT ResampleBSplineDeformableTransformGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef ResampleBSplineDeformableTransformGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( ResampleBSplineDeformableTransformGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkResampleBSplineDeformableTransform & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+      m_InputFileName=m_ArgsInfo.input_arg;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    ResampleBSplineDeformableTransformGenericFilter();
+    ~ResampleBSplineDeformableTransformGenericFilter() {};
+
+    
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <unsigned int Dimension>  void UpdateWithDim(std::string PixelType, int Components);
+    template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkResampleBSplineDeformableTransform m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_InputFileName;
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkResampleBSplineDeformableTransformGenericFilter.txx"
+#endif
+
+#endif // #define clitkResampleBSplineDeformableTransformGenericFilter_h
diff --git a/registration/clitkResampleBSplineDeformableTransformGenericFilter.txx b/registration/clitkResampleBSplineDeformableTransformGenericFilter.txx
new file mode 100644 (file)
index 0000000..7cf8e84
--- /dev/null
@@ -0,0 +1,158 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkResampleBSplineDeformableTransformGenericFilter_txx
+#define clitkResampleBSplineDeformableTransformGenericFilter_txx
+
+/* =================================================
+ * @file   clitkResampleBSplineDeformableTransformGenericFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+namespace clitk
+{
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions
+  //-------------------------------------------------------------------
+  template<unsigned int Dimension>
+  void 
+  ResampleBSplineDeformableTransformGenericFilter::UpdateWithDim(std::string PixelType, int Components)
+  {
+    if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<<Components<<" component(s) of "<<  PixelType<<"..."<<std::endl;
+
+    if (Components==2)
+      {
+       if(PixelType == "double"){  
+         if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and 2D double..." << std::endl;
+         UpdateWithDimAndPixelType<Dimension, itk::Vector<double,2 > >(); 
+       }
+       else {
+         if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and 2D float..." << std::endl;
+         UpdateWithDimAndPixelType<Dimension, itk::Vector<float,2 > >();
+       }
+      }
+    else if (Components==3)
+      {
+       if(PixelType == "double"){  
+         if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and 3D double..." << std::endl;
+         UpdateWithDimAndPixelType<Dimension, itk::Vector<double,3 > >(); 
+       }
+       else {
+         if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and 3D float..." << std::endl;
+         UpdateWithDimAndPixelType<Dimension, itk::Vector<float,3 > >();
+       }
+      }
+    else std::cerr<<"Number of components is "<<Components<<", not supported!"<<std::endl;
+  }
+
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions and the pixeltype
+  //-------------------------------------------------------------------
+  template <unsigned int Dimension, class  PixelType> 
+  void 
+  ResampleBSplineDeformableTransformGenericFilter::UpdateWithDimAndPixelType()
+  {
+
+    // ImageTypes
+    typedef itk::Image<PixelType, Dimension> InputImageType;
+    typedef itk::Image<PixelType, Dimension> OutputImageType;
+    
+    // Read the input
+    typedef itk::ImageFileReader<InputImageType> InputReaderType;
+    typename InputReaderType::Pointer reader = InputReaderType::New();
+    reader->SetFileName( m_InputFileName);
+    reader->Update();
+    typename InputImageType::Pointer input= reader->GetOutput();
+
+    // Filter
+    typedef clitk::ResampleBSplineDeformableTransformImageFilter<InputImageType,OutputImageType> ResampleFilterType;
+    typename   ResampleFilterType::Pointer filter=ResampleFilterType::New();
+    filter->SetInput(input);
+    
+    // Output image info
+    if (m_ArgsInfo.like_given)
+      {
+       typename InputReaderType::Pointer likeReader=InputReaderType::New();
+       likeReader->SetFileName(m_ArgsInfo.like_arg);
+       likeReader->Update();
+       filter->SetOutputParametersFromImage(likeReader->GetOutput());
+      }
+    else
+      {
+       // Size
+       typename OutputImageType::SizeType outputSize;
+       if (m_ArgsInfo.size_given) 
+         {
+           for(unsigned int i=0; i< Dimension; i++)
+             outputSize[i]=m_ArgsInfo.size_arg[i];
+         }
+       else outputSize=input->GetLargestPossibleRegion().GetSize();
+       if (m_Verbose) std::cout<<"Setting the size to "<<outputSize<<"..."<<std::endl;
+       
+       // Spacing
+       typename OutputImageType::SpacingType outputSpacing;
+       if (m_ArgsInfo.spacing_given) 
+         {
+           for(unsigned int i=0; i< Dimension; i++)
+             outputSpacing[i]=m_ArgsInfo.spacing_arg[i];
+         }
+       else outputSpacing=input->GetSpacing();
+       if (m_Verbose) std::cout<<"Setting the spacing to "<<outputSpacing<<"..."<<std::endl;
+    
+       // Origin
+       typename OutputImageType::PointType outputOrigin;
+       if (m_ArgsInfo.origin_given) 
+         {
+           for(unsigned int i=0; i< Dimension; i++)
+             outputOrigin[i]=m_ArgsInfo.origin_arg[i];
+         }
+       else outputOrigin=input->GetOrigin();
+       if (m_Verbose) std::cout<<"Setting the origin to "<<outputOrigin<<"..."<<std::endl;
+
+       // Set
+       filter->SetSize( outputSize );
+       filter->SetOutputSpacing( outputSpacing );
+       filter->SetOutputOrigin(  outputOrigin );
+       
+      }
+
+    // Go
+    filter->Update();
+    
+    // Get the output
+    typename OutputImageType::Pointer output=filter->GetOutput();
+    
+    // Output
+    typedef itk::ImageFileWriter<OutputImageType> WriterType;
+    typename WriterType::Pointer writer = WriterType::New();
+    writer->SetFileName(m_ArgsInfo.output_arg);
+    writer->SetInput(output);
+    writer->Update();
+
+  }
+
+
+}//end clitk
+#endif //#define clitkResampleBSplineDeformableTransformGenericFilter_txx
diff --git a/registration/clitkResampleBSplineDeformableTransformImageFilter.h b/registration/clitkResampleBSplineDeformableTransformImageFilter.h
new file mode 100644 (file)
index 0000000..96121be
--- /dev/null
@@ -0,0 +1,179 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkResampleBSplineDeformableTransformImageFilter_h
+#define clitkResampleBSplineDeformableTransformImageFilter_h
+
+/* =================================================
+ * @file   clitkResampleBSplineDeformableTransformImageFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkVectorBSplineDecompositionImageFilterWithOBD.h"
+#include "clitkVectorBSplineResampleImageFunction.h"
+
+//itk include
+#include "itkImageToImageFilter.h"
+#include "itkVectorResampleImageFilter.h"
+#include "itkCastImageFilter.h"
+
+
+namespace clitk 
+{
+
+  template <class InputImageType, class OutputImageType>
+  class ITK_EXPORT ResampleBSplineDeformableTransformImageFilter :
+    public itk::ImageToImageFilter<InputImageType, OutputImageType>
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef ResampleBSplineDeformableTransformImageFilter                                                 Self;
+    typedef itk::ImageToImageFilter<InputImageType, OutputImageType>  Superclass;
+    typedef itk::SmartPointer<Self>                                   Pointer;
+    typedef itk::SmartPointer<const Self>                             ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( ResampleBSplineDeformableTransformImageFilter, ImageToImageFilter );
+
+    /** Dimension of the domain space. */
+    itkStaticConstMacro(InputImageDimension, unsigned int, Superclass::InputImageDimension);
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+    typedef typename InputImageType::PointType              InputPointType;
+    typedef typename InputImageType::IndexType              IndexType;
+    
+    typedef typename OutputImageType::RegionType            OutputImageRegionType;
+    typedef typename OutputImageType::PointType             OutputPointType;
+    typedef typename OutputImageType::SpacingType           OutputSpacingType;
+    typedef typename OutputImageType::DirectionType         OutputDirectionType;
+    typedef typename OutputImageType::IndexType             OutputIndexType;
+    typedef typename OutputImageType::SizeType             OutputSizeType;
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    itkBooleanMacro(Verbose);
+    itkSetMacro( Verbose, bool);
+    itkGetConstReferenceMacro( Verbose, bool);
+
+    // Properties of the output 
+    itkSetMacro( Size, OutputSizeType );
+    itkGetConstReferenceMacro( Size, OutputSizeType );
+    itkSetMacro(OutputSpacing, OutputSpacingType);
+    virtual void SetOutputSpacing( const double* values);
+    itkGetConstReferenceMacro( OutputSpacing, OutputSpacingType );
+    itkSetMacro(OutputOrigin, OutputPointType);
+    virtual void SetOutputOrigin( const double* values);
+    itkGetConstReferenceMacro( OutputOrigin, OutputPointType );
+    itkSetMacro(OutputDirection, OutputDirectionType);
+    itkGetConstReferenceMacro(OutputDirection, OutputDirectionType);
+    itkSetMacro( OutputStartIndex, OutputIndexType );
+    itkGetConstReferenceMacro( OutputStartIndex, OutputIndexType );
+    void SetOutputParametersFromImage ( typename OutputImageType::Pointer Image )
+    {
+      this->SetOutputOrigin ( Image->GetOrigin() );
+      this->SetOutputSpacing ( Image->GetSpacing() );
+      this->SetOutputDirection ( Image->GetDirection() );
+      this->SetSize ( Image->GetLargestPossibleRegion().GetSize() );
+      this->SetOutputStartIndex(Image->GetLargestPossibleRegion().GetIndex());
+    }
+
+    void SetOutputParametersFromConstImage ( typename OutputImageType::ConstPointer Image )
+    {
+      this->SetOutputOrigin ( Image->GetOrigin() );
+      this->SetOutputSpacing ( Image->GetSpacing() );
+      this->SetOutputDirection ( Image->GetDirection() );
+      this->SetSize ( Image->GetLargestPossibleRegion().GetSize() );
+      this->SetOutputStartIndex(Image->GetLargestPossibleRegion().GetIndex());
+    }
+   
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    ResampleBSplineDeformableTransformImageFilter();
+    ~ResampleBSplineDeformableTransformImageFilter() {};
+
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    // Generate Data
+    void GenerateData(void);
+    //     // Threaded Generate Data
+    //     void BeforeThreadedGenerateData(void );
+    //     void ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread, int threadId );
+    //     void AfterThreadedGenerateData(void );
+    //     // Override defaults
+    //     virtual void GenerateInputRequestedRegion();
+    //     virtual void GenerateOutputInformation (void);
+    //     virtual void EnlargeOutputRequestedRegion(DataObject *data);
+    void AllocateOutputs(){};
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    bool m_Verbose;
+    OutputSizeType                m_Size;              // Size of the output image
+    OutputSpacingType             m_OutputSpacing;     // output image spacing
+    OutputPointType               m_OutputOrigin;      // output image origin
+    OutputDirectionType           m_OutputDirection;   // output image direction cosines
+    OutputIndexType               m_OutputStartIndex;  // output image start index
+    OutputSizeType                m_SplineOrders;
+
+    //----------------------------------------  
+    // Components
+    //----------------------------------------
+    typedef itk::VectorResampleImageFilter<InputImageType, OutputImageType> ResamplerType;
+    typedef VectorBSplineResampleImageFunction<InputImageType, double> FunctionType;
+    typedef itk::IdentityTransform<double,InputImageDimension> IdentityTransformType; 
+    typedef VectorBSplineDecompositionImageFilterWithOBD<OutputImageType, OutputImageType> DecompositionType;
+    typename ResamplerType::Pointer m_Resampler;
+    typename FunctionType::Pointer m_Function;
+    typename IdentityTransformType::Pointer m_Identity;
+    typename DecompositionType::Pointer m_Decomposition;
+
+
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkResampleBSplineDeformableTransformImageFilter.txx"
+#endif
+
+#endif // #define clitkResampleBSplineDeformableTransformImageFilter_h
+
+
diff --git a/registration/clitkResampleBSplineDeformableTransformImageFilter.txx b/registration/clitkResampleBSplineDeformableTransformImageFilter.txx
new file mode 100644 (file)
index 0000000..60f7fc1
--- /dev/null
@@ -0,0 +1,138 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkResampleBSplineDeformableTransformImageFilter_txx
+#define clitkResampleBSplineDeformableTransformImageFilter_txx
+
+/* =================================================
+ * @file   clitkResampleBSplineDeformableTransformImageFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+namespace clitk
+{
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions
+  //-------------------------------------------------------------------
+  template<class InputImageType, class OutputImageType>
+  ResampleBSplineDeformableTransformImageFilter<InputImageType, OutputImageType>::ResampleBSplineDeformableTransformImageFilter()
+  {
+   m_Verbose=false;
+   m_SplineOrders.Fill(3);
+   m_Size.Fill(0);
+   m_OutputSpacing.Fill(1.0);
+   m_OutputOrigin.Fill(-1);
+   m_OutputStartIndex.Fill(0);
+   m_OutputDirection.SetIdentity();
+   
+   // Components
+   m_Resampler = ResamplerType::New();
+   m_Function = FunctionType::New();
+   m_Identity = IdentityTransformType::New();
+   m_Decomposition = DecompositionType::New();
+   
+   // Connect
+   m_Resampler->SetInterpolator( m_Function );
+   m_Resampler->SetTransform( m_Identity );
+   m_Decomposition->SetInput( m_Resampler->GetOutput() );
+
+  }
+
+  //-------------------------------------------------------------------
+  // Output Info
+  //-------------------------------------------------------------------
+  template <class InputImageType, class  OutputImageType> 
+  void 
+  ResampleBSplineDeformableTransformImageFilter<InputImageType, OutputImageType>::SetOutputSpacing( const double* spacing )
+  {
+    OutputSpacingType s(spacing);
+    this->SetOutputSpacing( s );
+  }
+  
+  //-------------------------------------------------------------------
+  // Output Info
+  //-------------------------------------------------------------------
+  template <class InputImageType, class  OutputImageType> 
+  void 
+  ResampleBSplineDeformableTransformImageFilter<InputImageType, OutputImageType>::SetOutputOrigin( const double* origin )
+  {
+    OutputPointType p(origin);
+    this->SetOutputOrigin( p );
+  }
+
+
+
+  //-------------------------------------------------------------------
+  // Update with the number of dimensions and the pixeltype
+  //-------------------------------------------------------------------
+  template <class InputImageType, class  OutputImageType> 
+  void 
+  ResampleBSplineDeformableTransformImageFilter<InputImageType, OutputImageType>::GenerateData()
+  {
+
+    // Resample?
+    bool sizeIsCorrect=true;
+    
+    if (this->GetInput()->GetSpacing()  !=m_OutputSpacing)
+      sizeIsCorrect=false;
+    else if (this->GetInput()->GetLargestPossibleRegion().GetSize()!=m_Size)
+      sizeIsCorrect=false;
+    else if (this->GetInput()->GetOrigin()!=m_OutputOrigin)
+      sizeIsCorrect=false;
+    
+    // No resampling resquired
+    if (sizeIsCorrect)
+      {
+       if(m_Verbose)std::cout<<"Output properties are up to date, no resampling required!"<<std::endl;
+       typedef itk::CastImageFilter<InputImageType, OutputImageType>  CastImageFilterType;
+       typename CastImageFilterType::Pointer caster = CastImageFilterType::New();
+       caster->SetInput(this->GetInput());
+       caster->Update();
+       this->GraftOutput(caster->GetOutput());
+      }
+
+    // Resample
+    else
+      {
+       if(m_Verbose)std::cout<<"Resampling transform..."<<std::endl;
+
+       // Resample the coeeficients to values of correct size, spacing,...
+       m_Resampler->SetInput( this->GetInput() );
+       m_Resampler->SetSize( m_Size);
+       m_Resampler->SetOutputSpacing( m_OutputSpacing );
+       m_Resampler->SetOutputOrigin( m_OutputOrigin );
+       m_Resampler->SetOutputDirection( m_OutputDirection );
+       m_Resampler->SetOutputStartIndex( m_OutputStartIndex );
+       
+       // Transform the values back to Bspline coefficients
+       m_Decomposition->SetSplineOrders( m_SplineOrders );     
+       m_Decomposition->Update();
+       this->GraftOutput( m_Decomposition->GetOutput() );
+      }
+
+  }
+
+
+}//end clitk
+#endif //#define clitkResampleBSplineDeformableTransformImageFilter_txx
diff --git a/registration/clitkSelectPoints.cxx b/registration/clitkSelectPoints.cxx
new file mode 100755 (executable)
index 0000000..6c8e40b
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkSelectPoints.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkSelectPoints_ggo.h"
+#include "clitkIO.h"
+#include "clitkSelectPointsGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkSelectPoints, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::SelectPointsGenericFilter::Pointer genericFilter=clitk::SelectPointsGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkSelectPoints.ggo b/registration/clitkSelectPoints.ggo
new file mode 100755 (executable)
index 0000000..6c15fae
--- /dev/null
@@ -0,0 +1,24 @@
+#File clitkSelectPoints.ggo
+Package "clitkSelectPoints"
+version "1.0"
+purpose "Perform a selection of points on the reference and target lists of points, based on criteria applied to the reference list."
+
+option "config"                -       "Config file"                     string        no
+option "verbose"       v       "Verbose"                         flag          off
+
+section "Input"
+
+option "ref"                   r       "List of points in reference"           string          yes                     
+option "input"         i       "Lists of points in targets"            string          multiple        yes
+
+
+section "Output"
+
+option "sRef"                  -       "List of points selected in reference"          string          yes                     
+option "sInput"                o       "Lists of points selected in targets"           string          multiple        yes
+
+section "Selection: Provide lower and upper coordinate bounds for as much as components as provided"
+
+option "component"     c       "Component index [0,2]" int             multiple        yes     
+option "lower"         l       "Lower bound"           double          multiple        yes     
+option "upper"         u       "Upper bound"           double          multiple        yes     
diff --git a/registration/clitkSelectPointsGenericFilter.cxx b/registration/clitkSelectPointsGenericFilter.cxx
new file mode 100755 (executable)
index 0000000..3754160
--- /dev/null
@@ -0,0 +1,141 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkSelectPointsGenericFilter_cxx
+#define clitkSelectPointsGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkSelectPointsGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkSelectPointsGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  SelectPointsGenericFilter::SelectPointsGenericFilter()
+  {
+    m_Verbose=false;
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void SelectPointsGenericFilter::Update()
+  {
+    //-----------------------------
+    // Typedefs
+    //-----------------------------
+    typedef double ValueType;
+    typedef std::vector<ValueType> MeasureListType;
+
+    typedef itk::Point<double, 3> PointType;
+    typedef clitk::List<PointType> PointListType;
+    typedef clitk::Lists<PointType> PointListsType;
+
+   
+    //-----------------------------
+    // Input point lists
+    //-----------------------------   
+    PointListsType pointLists;
+    unsigned int numberOfPoints=0;
+    unsigned int numberOfLists=m_ArgsInfo.input_given;
+    for (unsigned int i=0; i<numberOfLists; i++)
+      {
+       // Read the lists
+       pointLists.push_back(PointListType(m_ArgsInfo.input_arg[i], m_Verbose) );
+
+       // Verify the number of points
+       if (i==0) numberOfPoints=pointLists[i].size();
+       else 
+         {
+           if  (numberOfPoints!=pointLists[i].size())
+             {
+               std::cerr<<"Size of first list ("<<numberOfPoints
+                        <<") is different from size of list "<<i
+                        <<" ("<<pointLists[i].size()<<")..."<<std::endl;
+               return;
+             }
+         }
+      }    
+    
+    //-----------------------------
+    // Reference point list
+    //-----------------------------
+    PointListType referencePointList;
+    if (m_Verbose) std::cout<<"Reference point list:"<<std::endl;
+    referencePointList=PointListType(m_ArgsInfo.ref_arg, m_Verbose);
+    if  (numberOfPoints!=referencePointList.size())
+      {
+       std::cerr<<"Size of the first list ("<<numberOfPoints
+                <<") is different from size of the reference list ("
+                << referencePointList.size() <<")..."<<std::endl;
+       return;
+      }
+
+    
+    //-----------------------------
+    // Select
+    //-----------------------------
+    PointListType sReferencePointList;
+    PointListsType sPointLists(numberOfLists);
+    unsigned int counter=0;
+    for (unsigned int number=0; number< referencePointList.size(); number++)
+      {
+       for (unsigned int component=0; component< m_ArgsInfo.component_given; component++)
+         {
+           if (  (referencePointList[number][m_ArgsInfo.component_arg[component]] >= m_ArgsInfo.lower_arg[component])
+                 &&  (referencePointList[number][m_ArgsInfo.component_arg[component]] <= m_ArgsInfo.upper_arg[component]) )
+             {
+               if(m_Verbose) std::cout<<"Selecting point "<<number<<": "<<referencePointList[number]<<std::endl;
+               sReferencePointList.push_back(referencePointList[number]);
+               for (unsigned int i=0;i<pointLists.size();i++)
+                 sPointLists[i].push_back(pointLists[i][number]);
+               counter++;
+             }
+         }
+      }
+    if (m_Verbose) std::cout<<"Selected "<<counter<<" points..."<<std::endl;
+    
+
+    
+    //-----------------------------
+    // Output
+    //-----------------------------
+    sReferencePointList.Write(m_ArgsInfo.sRef_arg,m_Verbose);
+    std::vector<std::string> filenames;
+    for (unsigned int i=0;i<pointLists.size();i++)
+      filenames.push_back(m_ArgsInfo.sInput_arg[i]);
+    sPointLists.Write(filenames,m_Verbose);
+
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkSelectPointsGenericFilter_cxx
diff --git a/registration/clitkSelectPointsGenericFilter.h b/registration/clitkSelectPointsGenericFilter.h
new file mode 100755 (executable)
index 0000000..0236d9d
--- /dev/null
@@ -0,0 +1,103 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkSelectPointsGenericFilter_h
+#define clitkSelectPointsGenericFilter_h
+
+/* =================================================
+ * @file   clitkSelectPointsGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkSelectPoints_ggo.h"
+#include "clitkList.h"
+#include "clitkLists.h"
+
+//itk include
+#include "itkLightObject.h"
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT SelectPointsGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef SelectPointsGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( SelectPointsGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkSelectPoints & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    SelectPointsGenericFilter();
+    ~SelectPointsGenericFilter() {};
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkSelectPoints m_ArgsInfo;
+    bool m_Verbose;
+
+  };
+
+
+} // end namespace clitk
+
+
+#endif // #define clitkSelectPointsGenericFilter_h
diff --git a/registration/clitkShapedBLUTSpatioTemporalDIR.cxx b/registration/clitkShapedBLUTSpatioTemporalDIR.cxx
new file mode 100755 (executable)
index 0000000..2ea11fc
--- /dev/null
@@ -0,0 +1,51 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+
+/* =================================================
+ * @file   clitkShapedBLUTSpatioTemporalDIR.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk
+#include "clitkShapedBLUTSpatioTemporalDIR_ggo.h"
+#include "clitkIO.h"
+#include "clitkShapedBLUTSpatioTemporalDIRGenericFilter.h"
+
+
+//--------------------------------------------------------------------
+int main(int argc, char * argv[]) {
+
+  // Init command line
+  GGO(clitkShapedBLUTSpatioTemporalDIR, args_info);
+  CLITK_INIT;
+
+  // Filter
+  clitk::ShapedBLUTSpatioTemporalDIRGenericFilter::Pointer genericFilter=clitk::ShapedBLUTSpatioTemporalDIRGenericFilter::New();
+  
+  genericFilter->SetArgsInfo(args_info);
+  genericFilter->Update();
+
+  return EXIT_SUCCESS;
+}// end main
+
+//--------------------------------------------------------------------
diff --git a/registration/clitkShapedBLUTSpatioTemporalDIR.ggo b/registration/clitkShapedBLUTSpatioTemporalDIR.ggo
new file mode 100755 (executable)
index 0000000..43b7ea1
--- /dev/null
@@ -0,0 +1,90 @@
+#File clitkShapedBLUTSpatioTemporalDIR.ggo
+#Author: Jef Vandemeulebroucke <jefvdmb@gmail.com>
+#Date : Tue 15 Jan 2009 10.35 
+
+Package "clitk"
+Version "Deform a volume to match a temporal sequence using a spatio-temporal deformation model. By setting the shape of the model, you modify the temporal constraints applied to the cyclic trajectory model."
+
+option "config"                -       "Config file"                   string          no
+
+
+section "Run Time"
+
+option "verbose"       v       "Verbose"                       flag            off
+option "threads"       -       "Number of threads to use (default=min(#cores,8))"      int      no
+
+
+section "Input"
+
+option "reference"             r       "Input reference 3D image (float)"      string          yes
+option "target"                        t       "Input target    2D image (float)"      string          yes
+option "referenceMask"                 m       "Mask to placed over the reference image"                 string                no
+option "targetMask"            -       "Mask to placed over the target image"            string                no
+
+
+section "Output"
+
+option "vf"                    -       "Result DVF"                                                    string          yes
+option "coeff"                 -       "Result coefficient images"                                     string          no      
+option "padCoeff"              -       "Result padded coefficient images"                      string          no      
+option "output"                        o       "Deformed target image"                                         string          yes
+option "before"                        -       "Difference image before (but after rigid transform)"           string          no
+option "after"                 -       "Difference image after "                                       string          no
+option "current"               -       "Write the current coefficient image every N evaluations"       int             no
+option "intermediate"          -       "Write the coefficient image at resolution levels (provide N filenames)"                string  no      multiple                                                
+
+
+section "Transform (Note that only one of --control, --spacing is required. The other will be adjusted to fit the region and allow exact representation. SamplingFactor will be set accordingly"
+
+option "shape"                 -       "Even=4 internal CP, Odd 5 internal CP: 0,1=egg; 2,3= rabbit; 4,5=sputnik; 6,7=diamond"         int             no      default="3"
+option "initCoeff"             -       "Initial coefficient image (without borders)"                   string          no
+option "initPadCoeff"          -       "Initial padded coefficient image (with borders)"               string          no              
+option "rigid"                 -       "Prior rigid transform matrix from reference to target space"   string          no      
+option "order"                 -       "Spline Order FFD"                                              int             no      multiple        default="3"
+option "control"               -       "Internal control points for each dimension"                    int             no      multiple        
+option "spacing"               -       "Control point spacing for each dimension (mm)"                 double          no      multiple        
+option "samplingFactor"                -       "LUT sampling factor"                                           int             no      multiple        
+
+
+section "Interpolator"
+
+option "interp"                -       "Interpolation: 0=NN, 1=Linear, 2=BSpline, 3=BLUT"      int     no  default="1"
+option "interpOrder"   -       "Order if BLUT or BSpline (0-5)"                        int     no  default="3"
+option "interpSF"      -       "Sampling factor if BLUT"                               int     no  default="20"
+
+
+section "Metric (optimized, threaded versions are available for *, compile ITK with REVIEW and OPT_REGISTRATION enabled. Further optimized versions ** for  BLUT FFD optimizing a !3D! vector field)"
+
+option "metric"        -       "Type: 0=SSD*, 1=Normalized CC*, 2=Histogram CC, 3=Gradient-Difference, 4=Viola-Wells MI, 5=Histogram MI, 6=Mattes' MI*, 7=Normalized MI, 8=CR, 9=SSD for BLUT FFD**, 10=CC for BLUT FFD**, 11=Mattes' MI for BLUT FFD**"       int     no      default="0"
+option "samples"       -       "Specify fraction [0, 1] of samples of the reference image used for the metric (* only). Use high fraction for detailed images (eg. 0.2, 0.5), for smooth images 0.01 might be enough." float   no      default="1"
+option "intThreshold"  -       "Fixed image samples intensity threshold (* only)"                                                      float   no              
+option "subtractMean"  -       "1: Subtract mean for NCC calculation (narrows optimal)"                                                flag    on      
+option "bins"          -       "2,5-8: Number of histogram bins"                                                                       int     no      default="50"
+option "random"        -       "4,6: Samples should be taken randomly, otherwise uniformly"                                            flag    off     
+option "stdDev"                -       "4: specify the standard deviation in mm of the gaussian kernels for both PDF estimations"              float   no      default="0.4"   
+option "explicitPDFDerivatives"        -       "6: Calculate PDF derivatives explicitly (rigid=true; FFD=false)"                               flag    off
+
+
+section "Optimizer"
+
+option "optimizer"     -       "0=Simplex, 1=Powell, 2=FRPR, 3=Regular Step GD, 4=VersorRigid3D, 5=Conjugated Gradient, 6=L-BFGS, 7=L-BFGS-B" int no default="7" 
+option "delta"         -       "0: Initial delta, otherwise automatic"                                                 double  no                      
+option "step"          -       "1,2,3,4: Initial stepsize (to be multiplied with the gradient)"                        double  no      default="2.0"   
+option "relax"                 -       "3,4: Relaxation of the stepsize (multiplied each time the gradient changes sign)"      double  no      default="0.7"
+option "valueTol"      -       "0,1,2: Tolerance on the function"                                                      double  no      default="0.01"
+option "stepTol"       -       "0,1,3,4: Tolerance on the step size"                                                   double  no      default="0.1"
+option "gradTol"       -       "3,4,6,7: Tolerance on the (projected) gradient magnitude (7: 1=low->1e-10=high precision)"     double  no      default="1e-5"                  
+option "lineAcc"       -       "6: Line accuracy (eg: high=0.1, low=0.9)"      double  no      default="0.9"
+option "convFactor"    -       "7: Convergence factor: terminate if factor*machine_precision>reduction in cost (1e+12 low -> 1e+1 high precision) "    double          no      default="1e+7"
+option "maxIt"         -       "0-7: Maximum number of iterations"                                     int     no      default="500"
+option "maxLineIt"     -       "1,2: Maximum number of line iterations"                                        int     no      default="50"    
+option "maxEval"       -       "6,7: Maximum number of evaluations"                                            int     no      default="500"
+option "maxCorr"       -       "7: Maximum number of corrections"                                              int     no      default="5"
+option "selectBound"   -       "7: Select the type of bound: 0=none, 1=u, 2=u&l, 3=l"                  int     no      default="0"
+option "lowerBound"    -       "7: The lower bound"                                                    double  no      default="0.0"
+option "upperBound"    -       "7: The upper bound"                                                    double  no      default="0.0"
+
+
+Section "Registration"
+
+option "levels"                -       "Number of resolution levels"                                   int     no      default="1"                                             
diff --git a/registration/clitkShapedBLUTSpatioTemporalDIRGenericFilter.cxx b/registration/clitkShapedBLUTSpatioTemporalDIRGenericFilter.cxx
new file mode 100755 (executable)
index 0000000..34cf7d3
--- /dev/null
@@ -0,0 +1,70 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkShapedBLUTSpatioTemporalDIRGenericFilter_cxx
+#define clitkShapedBLUTSpatioTemporalDIRGenericFilter_cxx
+
+/* =================================================
+ * @file   clitkShapedBLUTSpatioTemporalDIRGenericFilter.cxx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkShapedBLUTSpatioTemporalDIRGenericFilter.h"
+
+
+namespace clitk
+{
+
+
+  //-----------------------------------------------------------
+  // Constructor
+  //-----------------------------------------------------------
+  ShapedBLUTSpatioTemporalDIRGenericFilter::ShapedBLUTSpatioTemporalDIRGenericFilter()
+  {
+    m_Verbose=false;
+    m_ReferenceFileName="";
+  }
+
+
+  //-----------------------------------------------------------
+  // Update
+  //-----------------------------------------------------------
+  void ShapedBLUTSpatioTemporalDIRGenericFilter::Update()
+  {
+    // Read the Dimension and PixelType
+    int Dimension;
+    std::string PixelType;
+    ReadImageDimensionAndPixelType(m_ReferenceFileName, Dimension, PixelType);
+
+    //if(Dimension==3) UpdateWithDim<3>(PixelType);
+    //else 
+    if (Dimension==4)UpdateWithDim<4>(PixelType); 
+    else 
+      {
+       std::cout<<"Error, Only for 4  Dimensions!!!"<<std::endl ;
+       return;
+      }
+  }
+
+
+} //end clitk
+
+#endif  //#define clitkShapedBLUTSpatioTemporalDIRGenericFilter_cxx
diff --git a/registration/clitkShapedBLUTSpatioTemporalDIRGenericFilter.h b/registration/clitkShapedBLUTSpatioTemporalDIRGenericFilter.h
new file mode 100755 (executable)
index 0000000..e97d9da
--- /dev/null
@@ -0,0 +1,130 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkShapedBLUTSpatioTemporalDIRGenericFilter_h
+#define clitkShapedBLUTSpatioTemporalDIRGenericFilter_h
+
+/* =================================================
+ * @file   clitkShapedBLUTSpatioTemporalDIRGenericFilter.h
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+
+// clitk include
+#include "clitkShapedBLUTSpatioTemporalDIR_ggo.h"
+#include "clitkIO.h"
+#include "clitkCommon.h"
+#include "clitkGenericOptimizer.h"
+#include "clitkGenericMetric.h"
+#include "clitkGenericInterpolator.h"
+#include "clitkShapedBLUTSpatioTemporalDeformableTransform.h"
+#include "clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.h"
+#include "clitkSpatioTemporalMultiResolutionImageRegistrationMethod.h"
+#include "clitkSpatioTemporalMultiResolutionPyramidImageFilter.h"
+#include "clitkDifferenceImageFilter.h"
+#include "clitkMultiResolutionPyramidRegionFilter.h"
+
+//itk include
+#include "itkLightObject.h"
+#include "itkLabelStatisticsImageFilter.h"
+#include "itkImageMaskSpatialObject.h"
+#include "itkImageToImageMetric.h"
+#include "itkInterpolateImageFunction.h"
+#include "itkWarpImageFilter.h"
+#include "itkImageDuplicator.h"
+#include "itkExtractImageFilter.h"
+#include "itkCropImageFilter.h"
+
+namespace clitk 
+{
+
+
+  class ITK_EXPORT ShapedBLUTSpatioTemporalDIRGenericFilter : public itk::LightObject
+  {
+  public:
+    //----------------------------------------
+    // ITK
+    //----------------------------------------
+    typedef ShapedBLUTSpatioTemporalDIRGenericFilter                   Self;
+    typedef itk::LightObject                   Superclass;
+    typedef itk::SmartPointer<Self>            Pointer;
+    typedef itk::SmartPointer<const Self>      ConstPointer;
+   
+    // Method for creation through the object factory
+    itkNewMacro(Self);  
+
+    // Run-time type information (and related methods)
+    itkTypeMacro( ShapedBLUTSpatioTemporalDIRGenericFilter, LightObject );
+
+
+    //----------------------------------------
+    // Typedefs
+    //----------------------------------------
+
+
+    //----------------------------------------
+    // Set & Get
+    //----------------------------------------    
+    void SetArgsInfo(const args_info_clitkShapedBLUTSpatioTemporalDIR & a)
+    {
+      m_ArgsInfo=a;
+      m_Verbose=m_ArgsInfo.verbose_flag;
+      m_ReferenceFileName=m_ArgsInfo.reference_arg;
+    }
+    
+    
+    //----------------------------------------  
+    // Update
+    //----------------------------------------  
+    void Update();
+
+  protected:
+
+    //----------------------------------------  
+    // Constructor & Destructor
+    //----------------------------------------  
+    ShapedBLUTSpatioTemporalDIRGenericFilter();
+    ~ShapedBLUTSpatioTemporalDIRGenericFilter() {};
+
+    
+    //----------------------------------------  
+    // Templated members
+    //----------------------------------------  
+    template <unsigned int Dimension>  void UpdateWithDim(std::string PixelType);
+    template <unsigned int Dimension, class PixelType>  void UpdateWithDimAndPixelType();
+
+
+    //----------------------------------------  
+    // Data members
+    //----------------------------------------
+    args_info_clitkShapedBLUTSpatioTemporalDIR m_ArgsInfo;
+    bool m_Verbose;
+    std::string m_ReferenceFileName;
+  };
+
+
+} // end namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkShapedBLUTSpatioTemporalDIRGenericFilter.txx"
+#endif
+
+#endif // #define clitkShapedBLUTSpatioTemporalDIRGenericFilter_h
diff --git a/registration/clitkShapedBLUTSpatioTemporalDIRGenericFilter.txx b/registration/clitkShapedBLUTSpatioTemporalDIRGenericFilter.txx
new file mode 100755 (executable)
index 0000000..1610936
--- /dev/null
@@ -0,0 +1,929 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef clitkShapedBLUTSpatioTemporalDIRGenericFilter_txx
+#define clitkShapedBLUTSpatioTemporalDIRGenericFilter_txx
+
+/* =================================================
+ * @file   clitkShapedBLUTSpatioTemporalDIRGenericFilter.txx
+ * @author 
+ * @date   
+ * 
+ * @brief 
+ * 
+ ===================================================*/
+
+#include "clitkShapedBLUTSpatioTemporalDIRGenericFilter.h"
+
+namespace clitk
+{
+
+  //==============================================================================
+  // Creating an observer class that allows output at each iteration
+  //==============================================================================
+  template <typename TRegistration, class args_info_clitkShapedBLUTSpatioTemporalDIR>
+  class CommandIterationUpdate : public itk::Command 
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<Self>  Pointer;
+    itkNewMacro( Self );
+
+    // Registration
+    typedef   TRegistration                              RegistrationType;
+    typedef   RegistrationType *                         RegistrationPointer;
+
+    // Transform
+    typedef typename RegistrationType::FixedImageType FixedImageType;
+    typedef typename FixedImageType::RegionType RegionType;
+    itkStaticConstMacro(ImageDimension, unsigned int,FixedImageType::ImageDimension); 
+    typedef clitk::ShapedBLUTSpatioTemporalDeformableTransform<double, ImageDimension, ImageDimension> TransformType;
+    typedef clitk::ShapedBLUTSpatioTemporalDeformableTransformInitializer<TransformType, FixedImageType> InitializerType;
+    typedef typename InitializerType::CoefficientImageType CoefficientImageType;
+    typedef itk::CastImageFilter<CoefficientImageType, CoefficientImageType> CastImageFilterType;
+    typedef typename TransformType::ParametersType ParametersType;
+    typedef typename InitializerType::Pointer InitializerPointer;
+
+  protected:
+    CommandIterationUpdate() { m_IterationCounter=0;}
+  public:
+    typedef   clitk::GenericOptimizer<args_info_clitkShapedBLUTSpatioTemporalDIR>     OptimizerType;
+    typedef   const OptimizerType   *           OptimizerPointer;
+  
+    // Execute
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+    {
+      Execute( (const itk::Object *)caller, event);
+    }
+  
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+    {  
+      if( !(itk::IterationEvent().CheckEvent( &event )) )
+       {
+         return;
+       }
+      
+      // Output
+      m_Optimizer->OutputIterationInfo();
+      m_IterationCounter++;
+
+      // Write intermediate result
+      if (m_ArgsInfo.current_given && (m_IterationCounter> m_ArgsInfo.current_arg) )
+       {
+         // Write && Reset
+         writeImage<CoefficientImageType>(m_Initializer->GetTransform()->GetCoefficientImage(), m_ArgsInfo.coeff_arg, m_ArgsInfo.verbose_flag );
+         m_IterationCounter=0;
+       }
+    }
+
+   // Members
+    void SetOptimizer(OptimizerPointer o){m_Optimizer=o;}
+    OptimizerPointer m_Optimizer;
+
+    void SetInitializer(InitializerPointer i){m_Initializer=i;}
+    InitializerPointer m_Initializer;
+    
+    void SetArgsInfo(args_info_clitkShapedBLUTSpatioTemporalDIR a){m_ArgsInfo=a;}
+    args_info_clitkShapedBLUTSpatioTemporalDIR m_ArgsInfo;
+
+    int m_IterationCounter;
+  };
+
+
+  //==============================================================================
+  //Creating an observer class that allows us to change parameters at subsequent levels
+  //==============================================================================
+  template <typename TRegistration, class args_info_clitkShapedBLUTSpatioTemporalDIR>
+  class RegistrationInterfaceCommand : public itk::Command 
+  {
+  public:
+    typedef RegistrationInterfaceCommand   Self;
+    typedef itk::Command             Superclass;
+    typedef itk::SmartPointer<Self>  Pointer;
+    itkNewMacro( Self );
+  protected:
+    RegistrationInterfaceCommand() {};
+  public:
+
+    // Registration
+    typedef   TRegistration                              RegistrationType;
+    typedef   RegistrationType *                         RegistrationPointer;
+
+    // Transform
+    typedef typename RegistrationType::FixedImageType FixedImageType;
+    typedef typename FixedImageType::RegionType RegionType;
+    itkStaticConstMacro(ImageDimension, unsigned int,FixedImageType::ImageDimension); 
+    typedef clitk::ShapedBLUTSpatioTemporalDeformableTransform<double, ImageDimension, ImageDimension> TransformType;
+    typedef clitk::ShapedBLUTSpatioTemporalDeformableTransformInitializer<TransformType, FixedImageType> InitializerType;
+    typedef typename InitializerType::CoefficientImageType CoefficientImageType;
+    typedef itk::CastImageFilter<CoefficientImageType, CoefficientImageType> CastImageFilterType;
+    typedef typename TransformType::ParametersType ParametersType;
+    typedef typename InitializerType::Pointer InitializerPointer;
+    typedef  typename  CommandIterationUpdate< TRegistration, args_info_clitkShapedBLUTSpatioTemporalDIR>::Pointer CommandIterationUpdatePointer;
+
+    // Optimizer
+    typedef clitk::GenericOptimizer<args_info_clitkShapedBLUTSpatioTemporalDIR> GenericOptimizerType;
+    typedef typename GenericOptimizerType::Pointer GenericOptimizerPointer;
+
+    // Metric
+    typedef typename RegistrationType::FixedImageType    InternalImageType;
+    typedef clitk::GenericMetric<args_info_clitkShapedBLUTSpatioTemporalDIR, InternalImageType, InternalImageType> GenericMetricType;
+    typedef typename GenericMetricType::Pointer GenericMetricPointer;
+
+    // Two arguments are passed to the Execute() method: the first
+    // is the pointer to the object which invoked the event and the 
+    // second is the event that was invoked.
+    void Execute(itk::Object * object, const itk::EventObject & event)
+    {
+      if( !(itk::IterationEvent().CheckEvent( &event )) )
+       {
+         return;
+       }
+
+      // Get the levels
+      RegistrationPointer registration = dynamic_cast<RegistrationPointer>( object );
+      unsigned int numberOfLevels=registration->GetNumberOfLevels();
+      unsigned int currentLevel=registration->GetCurrentLevel()+1;
+
+      // Output the levels
+      std::cout<<std::endl;
+      std::cout<<"========================================"<<std::endl;
+      std::cout<<"Starting resolution level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
+      std::cout<<"========================================"<<std::endl;        
+      std::cout<<std::endl;
+
+      // Higher level?
+      if (currentLevel>1)
+       {
+         // fixed image region pyramid
+         typedef clitk::MultiResolutionPyramidRegionFilter<InternalImageType> FixedImageRegionPyramidType;
+         typename FixedImageRegionPyramidType::Pointer fixedImageRegionPyramid=FixedImageRegionPyramidType::New();
+         fixedImageRegionPyramid->SetRegion(m_MetricRegion);
+         fixedImageRegionPyramid->SetSchedule(registration->GetFixedImagePyramid()->GetSchedule());
+
+         // Reinitialize the metric (!= number of samples)
+         m_GenericMetric= GenericMetricType::New();
+         m_GenericMetric->SetArgsInfo(m_ArgsInfo);
+         m_GenericMetric->SetFixedImage(registration->GetFixedImagePyramid()->GetOutput(registration->GetCurrentLevel()));
+         if (m_ArgsInfo.referenceMask_given)  m_GenericMetric->SetFixedImageMask(registration->GetMetric()->GetFixedImageMask());
+         m_GenericMetric->SetFixedImageRegion(fixedImageRegionPyramid->GetOutput(registration->GetCurrentLevel()));
+         typedef itk::ImageToImageMetric< InternalImageType, InternalImageType >  MetricType;
+         typename  MetricType::Pointer metric=m_GenericMetric->GetMetricPointer();
+         registration->SetMetric(metric);      
+
+         // Get the current coefficient image and make a COPY
+         typename itk::ImageDuplicator<CoefficientImageType>::Pointer caster=itk::ImageDuplicator<CoefficientImageType>::New();
+         caster->SetInputImage(m_Initializer->GetTransform()->GetCoefficientImage());
+         caster->Update();
+         typename CoefficientImageType::Pointer currentCoefficientImage=caster->GetOutput();
+
+         // Write the intermediate result?
+         if (m_ArgsInfo.intermediate_given>=numberOfLevels)
+           writeImage<CoefficientImageType>(currentCoefficientImage, m_ArgsInfo.intermediate_arg[currentLevel-2], m_ArgsInfo.verbose_flag);
+         
+         // Set the new transform properties
+         m_Initializer->SetImage(registration->GetFixedImagePyramid()->GetOutput(currentLevel-1));
+         if( m_Initializer->m_ControlPointSpacingIsGiven) 
+           m_Initializer->SetControlPointSpacing(m_Initializer->m_ControlPointSpacingArray[registration->GetCurrentLevel()]);
+         if( m_Initializer->m_NumberOfControlPointsIsGiven) 
+           m_Initializer->SetNumberOfControlPointsInsideTheImage(m_Initializer->m_NumberOfControlPointsInsideTheImageArray[registration->GetCurrentLevel()]);
+  
+         // Reinitialize the transform
+         if (m_ArgsInfo.verbose_flag) std::cout<<"Initializing transform for level "<<currentLevel<<" of "<<numberOfLevels<<"..."<<std::endl;
+         m_Initializer->InitializeTransform();
+         ParametersType* newParameters= new typename TransformType::ParametersType(m_Initializer->GetTransform()->GetNumberOfParameters());
+
+         // Reinitialize an Optimizer (!= number of parameters)
+         m_GenericOptimizer = GenericOptimizerType::New();
+         m_GenericOptimizer->SetArgsInfo(m_ArgsInfo);
+         m_GenericOptimizer->SetMaximize(m_Maximize);
+         m_GenericOptimizer->SetNumberOfParameters(m_Initializer->GetTransform()->GetNumberOfParameters());
+         typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
+         OptimizerType::Pointer optimizer = m_GenericOptimizer->GetOptimizerPointer();
+         optimizer->AddObserver( itk::IterationEvent(), m_CommandIterationUpdate);
+         registration->SetOptimizer(optimizer);                                                  
+         m_CommandIterationUpdate->SetOptimizer(m_GenericOptimizer);
+         
+         // Set the previous transform parameters to the registration
+         // if(m_Initializer->m_Parameters!=NULL )delete m_Initializer->m_Parameters;
+         m_Initializer->SetInitialParameters(currentCoefficientImage,*newParameters); 
+         registration->SetInitialTransformParametersOfNextLevel(*newParameters);  
+       }
+    }
+
+    void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+
+
+    // Members
+    void SetInitializer(InitializerPointer i){m_Initializer=i;}
+    InitializerPointer m_Initializer;
+
+    void SetArgsInfo(args_info_clitkShapedBLUTSpatioTemporalDIR a){m_ArgsInfo=a;}
+    args_info_clitkShapedBLUTSpatioTemporalDIR m_ArgsInfo;
+
+    void SetCommandIterationUpdate(CommandIterationUpdatePointer c){m_CommandIterationUpdate=c;};
+    CommandIterationUpdatePointer m_CommandIterationUpdate;
+
+    GenericOptimizerPointer m_GenericOptimizer;
+    void SetMaximize(bool b){m_Maximize=b;}
+    bool m_Maximize;
+
+    GenericMetricPointer m_GenericMetric;
+    void SetMetricRegion(RegionType i){m_MetricRegion=i;}
+    RegionType m_MetricRegion;
+    
+  };
+
+
+  //==============================================================================
+  // Update with the number of dimensions
+  //==============================================================================
+  template<unsigned int Dimension>
+  void 
+  ShapedBLUTSpatioTemporalDIRGenericFilter::UpdateWithDim(std::string PixelType)
+  {
+    if (m_Verbose) std::cout << "Image was detected to be "<<Dimension<<"D and "<< PixelType<<"..."<<std::endl;
+
+    if(PixelType == "short"){  
+      if (m_Verbose) std::cout << "Launching filter in "<< Dimension <<"D and signed short..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, signed short>(); 
+    }
+    //    else if(PixelType == "unsigned_short"){  
+    //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_short..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, unsigned short>(); 
+    //     }
+    
+    //     else if (PixelType == "unsigned_char"){ 
+    //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and unsigned_char..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, unsigned char>();
+    //     }
+    
+    //     else if (PixelType == "char"){ 
+    //       if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and signed_char..." << std::endl;
+    //       UpdateWithDimAndPixelType<Dimension, signed char>();
+    //    }
+    else {
+      if (m_Verbose) std::cout  << "Launching filter in "<< Dimension <<"D and float..." << std::endl;
+      UpdateWithDimAndPixelType<Dimension, float>();
+    }
+  }
+
+
+  //==============================================================================
+  // Update with the number of dimensions and pixeltype
+  //==============================================================================
+  template<unsigned int ImageDimension, class PixelType> 
+  void 
+  ShapedBLUTSpatioTemporalDIRGenericFilter::UpdateWithDimAndPixelType()
+  {
+
+
+    //=============================================================================
+    //Input
+    //=============================================================================
+    bool threadsGiven=m_ArgsInfo.threads_given;
+    int threads=m_ArgsInfo.threads_arg;
+    
+    typedef itk::Image< PixelType, ImageDimension >  FixedImageType;
+    typedef itk::Image< PixelType, ImageDimension >  MovingImageType;
+    const unsigned int SpaceDimension = ImageDimension-1;
+    typedef double TCoordRep;
+
+
+    //=======================================================
+    //Input
+    //=======================================================
+    typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
+    typedef itk::ImageFileReader< MovingImageType > MovingImageReaderType;
+
+    typename FixedImageReaderType::Pointer  fixedImageReader  = FixedImageReaderType::New();
+    typename MovingImageReaderType::Pointer movingImageReader = MovingImageReaderType::New();
+
+    fixedImageReader->SetFileName(  m_ArgsInfo.reference_arg );
+    movingImageReader->SetFileName( m_ArgsInfo.target_arg );
+    if (m_Verbose) std::cout<<"Reading images..."<<std::endl;
+    fixedImageReader->Update();
+    movingImageReader->Update();
+
+    typename FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+    typename MovingImageType::Pointer movingImage =movingImageReader->GetOutput();
+    typename FixedImageType::Pointer croppedFixedImage=fixedImage;
+
+
+    //=======================================================
+    // Regions
+    //=======================================================
+
+    // The original input region    
+    typename FixedImageType::RegionType fixedImageRegion = fixedImage->GetLargestPossibleRegion();
+
+    // The transform region with respect to the input region:
+    // where should the transform be DEFINED (depends on mask)
+    typename FixedImageType::RegionType transformRegion = fixedImage->GetLargestPossibleRegion();
+    typename FixedImageType::RegionType::SizeType transformRegionSize=transformRegion.GetSize();
+    typename FixedImageType::RegionType::IndexType transformRegionIndex=transformRegion.GetIndex();
+    typename FixedImageType::PointType transformRegionOrigin=fixedImage->GetOrigin();
+
+    // The metric region with respect to the extracted transform region: 
+    // where should the metric be CALCULATED (depends on transform)
+    typename FixedImageType::RegionType metricRegion = fixedImage->GetLargestPossibleRegion();
+    typename FixedImageType::RegionType::SizeType metricRegionSize=metricRegion.GetSize();
+    typename FixedImageType::RegionType::IndexType metricRegionIndex=metricRegion.GetIndex();
+    typename FixedImageType::PointType metricRegionOrigin=fixedImage->GetOrigin();
+
+    //===========================================================================
+    // If given, we connect a mask to reference or target
+    //============================================================================
+    typedef itk::ImageMaskSpatialObject<  ImageDimension >   MaskType;
+    typename MaskType::Pointer  fixedMask=NULL;
+    if (m_ArgsInfo.referenceMask_given)
+      {
+       fixedMask= MaskType::New();
+       typedef itk::Image< unsigned char, ImageDimension >   ImageMaskType;
+       typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
+       typename MaskReaderType::Pointer  maskReader = MaskReaderType::New();
+       maskReader->SetFileName(m_ArgsInfo.referenceMask_arg);
+       try 
+         { 
+           maskReader->Update(); 
+         } 
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught while reading mask !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         } 
+       if (m_Verbose)std::cout <<"Reference image mask was read..." <<std::endl;
+
+       // Set the image to the spatialObject
+       fixedMask->SetImage( maskReader->GetOutput() );
+
+       // Find the bounding box of the "inside" label
+       typedef itk::LabelStatisticsImageFilter<ImageMaskType, ImageMaskType> StatisticsImageFilterType;
+       typename StatisticsImageFilterType::Pointer statisticsImageFilter=StatisticsImageFilterType::New();
+       statisticsImageFilter->SetInput(maskReader->GetOutput());
+       statisticsImageFilter->SetLabelInput(maskReader->GetOutput());
+       statisticsImageFilter->Update();
+       typename StatisticsImageFilterType::BoundingBoxType boundingBox = statisticsImageFilter->GetBoundingBox(1);
+
+       // Limit the transform region to the mask
+       for (unsigned int i=0; i<ImageDimension; i++)
+         {
+           transformRegionIndex[i]=boundingBox[2*i];
+           transformRegionSize[i]=boundingBox[2*i+1]-boundingBox[2*i]+1;
+         }
+       transformRegion.SetSize(transformRegionSize);
+       transformRegion.SetIndex(transformRegionIndex);
+       fixedImage->TransformIndexToPhysicalPoint(transformRegion.GetIndex(), transformRegionOrigin);
+       
+       // Crop the fixedImage to the bounding box to facilitate multi-resolution 
+       typedef itk::ExtractImageFilter<FixedImageType,FixedImageType> ExtractImageFilterType; 
+       typename ExtractImageFilterType::Pointer extractImageFilter=ExtractImageFilterType::New();
+       extractImageFilter->SetInput(fixedImage);
+       extractImageFilter->SetExtractionRegion(transformRegion);
+       extractImageFilter->Update();
+       croppedFixedImage=extractImageFilter->GetOutput();
+
+       // Update the metric region     
+       metricRegion = croppedFixedImage->GetLargestPossibleRegion();
+       metricRegionIndex=metricRegion.GetIndex();
+       metricRegionSize=metricRegion.GetSize();
+       croppedFixedImage->TransformIndexToPhysicalPoint(metricRegionIndex, metricRegionOrigin);
+
+       // Set start index to zero (with respect to croppedFixedImage/transform region)
+       metricRegionIndex.Fill(0);
+       metricRegion.SetIndex(metricRegionIndex);
+       croppedFixedImage->SetRegions(metricRegion);
+       croppedFixedImage->SetOrigin(metricRegionOrigin);
+
+      }
+
+    typedef itk::ImageMaskSpatialObject<  ImageDimension >   MaskType;
+    typename MaskType::Pointer  movingMask=NULL;
+    if (m_ArgsInfo.targetMask_given)
+      {
+       movingMask= MaskType::New();
+       typedef itk::Image< unsigned char, ImageDimension >   ImageMaskType;
+       typedef itk::ImageFileReader< ImageMaskType >    MaskReaderType;
+       typename MaskReaderType::Pointer  maskReader = MaskReaderType::New();
+       maskReader->SetFileName(m_ArgsInfo.targetMask_arg);
+       try 
+         { 
+           maskReader->Update(); 
+         } 
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught !" << std::endl; 
+           std::cerr << err << std::endl; 
+         } 
+       if (m_Verbose)std::cout <<"Target image mask was read..." <<std::endl;
+       
+       movingMask->SetImage( maskReader->GetOutput() );
+      }
+
+
+    //=======================================================
+    // Output Regions
+    //=======================================================
+
+    if (m_Verbose)
+      {
+       // Fixed image region
+       std::cout<<"The fixed image has its origin at "<<fixedImage->GetOrigin()<<std::endl 
+                <<"The fixed image region starts at index "<<fixedImageRegion.GetIndex()<<std::endl
+                <<"The fixed image region has size "<< fixedImageRegion.GetSize()<<std::endl;
+
+       // Transform region
+       std::cout<<"The transform has its origin at "<<transformRegionOrigin<<std::endl 
+                <<"The transform region will start at index "<<transformRegion.GetIndex()<<std::endl
+                <<"The transform region has size "<< transformRegion.GetSize()<<std::endl;
+
+       // Metric region
+       std::cout<<"The metric region has its origin at "<<metricRegionOrigin<<std::endl 
+                <<"The metric region will start at index "<<metricRegion.GetIndex()<<std::endl
+                <<"The metric region has size "<< metricRegion.GetSize()<<std::endl;
+       
+      }  
+
+
+    //=======================================================
+    // Pyramids (update them for transform initializer)
+    //=======================================================
+    typedef clitk::RecursiveSpatioTemporalMultiResolutionPyramidImageFilter< FixedImageType, FixedImageType>    FixedImagePyramidType;
+    typedef clitk::RecursiveSpatioTemporalMultiResolutionPyramidImageFilter< MovingImageType, MovingImageType>    MovingImagePyramidType;
+    typename FixedImagePyramidType::Pointer fixedImagePyramid = FixedImagePyramidType::New();
+    typename MovingImagePyramidType::Pointer movingImagePyramid = MovingImagePyramidType::New();
+    fixedImagePyramid->SetUseShrinkImageFilter(false);
+    fixedImagePyramid->SetInput(croppedFixedImage);
+    fixedImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
+    movingImagePyramid->SetUseShrinkImageFilter(false);    
+    movingImagePyramid->SetInput(movingImage);
+    movingImagePyramid->SetNumberOfLevels(m_ArgsInfo.levels_arg);
+    if (m_Verbose) std::cout<<"Creating the image pyramid..."<<std::endl;
+    fixedImagePyramid->Update();
+    movingImagePyramid->Update();
+    typedef clitk::MultiResolutionPyramidRegionFilter<FixedImageType> FixedImageRegionPyramidType;
+    typename FixedImageRegionPyramidType::Pointer fixedImageRegionPyramid=FixedImageRegionPyramidType::New();
+    fixedImageRegionPyramid->SetRegion(metricRegion);
+    fixedImageRegionPyramid->SetSchedule(fixedImagePyramid->GetSchedule());
+
+
+
+
+    //     //=======================================================
+    //     // Rigid Transform
+    //     //=======================================================
+    //     typedef itk::Euler3DTransform <double> RigidTransformType;
+    //     RigidTransformType::Pointer rigidTransform;
+    //     if (m_ArgsInfo.rigid_given)
+    //       {
+    //         rigidTransform=RigidTransformType::New();
+    //         itk::Matrix<double,4,4> rigidTransformMatrix=clitk::ReadMatrix3D(m_ArgsInfo.rigid_arg);
+    
+    //         //Set the rotation
+    //         itk::Matrix<double,3,3> finalRotation = clitk::GetRotationalPartMatrix3D(rigidTransformMatrix);
+    //         rigidTransform->SetMatrix(finalRotation);
+    
+    //         //Set the translation
+    //         itk::Vector<double,3> finalTranslation = clitk::GetTranslationPartMatrix3D(rigidTransformMatrix);
+    //         rigidTransform->SetTranslation(finalTranslation);
+    
+    //       }
+
+
+    //=======================================================
+    // ShapedBSplineSpatioTemporal Transform
+    //=======================================================
+    typedef  clitk::ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep,ImageDimension, ImageDimension > TransformType;
+    typename TransformType::Pointer transform= TransformType::New();
+    transform->SetTransformShape(m_ArgsInfo.shape_arg);
+    if (fixedMask) transform->SetMask( fixedMask );
+    // if (rigidTransform) transform->SetBulkTransform( rigidTransform );      
+
+    //-------------------------------------------------------------------------
+    // The transform initializer
+    //-------------------------------------------------------------------------
+    typedef clitk::ShapedBLUTSpatioTemporalDeformableTransformInitializer< TransformType,FixedImageType> InitializerType;
+    typename InitializerType::Pointer initializer = InitializerType::New();
+    initializer->SetVerbose(m_Verbose);
+    initializer->SetImage(fixedImagePyramid->GetOutput(0));
+    initializer->SetTransform(transform);
+
+    //-------------------------------------------------------------------------
+    // Order
+    //-------------------------------------------------------------------------
+    typename FixedImageType::RegionType::SizeType splineOrders ;
+    splineOrders.Fill(3);
+    if (m_ArgsInfo.order_given)
+      for(unsigned int i=0; i<ImageDimension;i++) 
+       splineOrders[i]=m_ArgsInfo.order_arg[i];
+    if (m_Verbose) std::cout<<"Setting the spline orders  to "<<splineOrders<<"..."<<std::endl;
+    initializer->SetSplineOrders(splineOrders);
+
+    //-------------------------------------------------------------------------
+    // Levels
+    //-------------------------------------------------------------------------
+  
+    // Spacing
+    if (m_ArgsInfo.spacing_given)
+      {
+       initializer->m_ControlPointSpacingArray.resize(m_ArgsInfo.levels_arg);
+       initializer->SetControlPointSpacing(m_ArgsInfo.spacing_arg);
+       initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1]=initializer->m_ControlPointSpacing;
+       if (m_Verbose) std::cout<<"Using a control point spacing of "<<initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1]
+                               <<" at level "<<m_ArgsInfo.levels_arg<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;   
+       
+       for (int i=1; i<m_ArgsInfo.levels_arg; i++ )
+         {
+           initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1-i]=initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-i]*2;
+           initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1-i][ImageDimension-1]=2;
+           if (m_Verbose) std::cout<<"Using a control point spacing of "<<initializer->m_ControlPointSpacingArray[m_ArgsInfo.levels_arg-1-i]
+                                   <<" at level "<<m_ArgsInfo.levels_arg-i<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;   
+         }
+         
+      }  
+    
+    // Control
+    if (m_ArgsInfo.control_given)
+      {
+       initializer->m_NumberOfControlPointsInsideTheImageArray.resize(m_ArgsInfo.levels_arg);
+       initializer->SetNumberOfControlPointsInsideTheImage(m_ArgsInfo.control_arg);
+       initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1]=initializer->m_NumberOfControlPointsInsideTheImage;
+       if (m_Verbose) std::cout<<"Using "<< initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1]<<"control points inside the image"
+                               <<" at level "<<m_ArgsInfo.levels_arg<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;   
+       
+       for (int i=1; i<m_ArgsInfo.levels_arg; i++ )
+         {
+           for(unsigned int j=0;j<ImageDimension-1;j++)
+             initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1-i][j]=ceil ((double)initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-i][j]/2.);
+             //            initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1-i]=ceil ((double)initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-i]/2.);
+           if (m_Verbose) std::cout<<"Using "<< initializer->m_NumberOfControlPointsInsideTheImageArray[m_ArgsInfo.levels_arg-1-i]<<"control points inside the image"
+                                   <<" at level "<<m_ArgsInfo.levels_arg<<" of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;   
+       
+         }
+      }  
+
+    // Inialize on the first level 
+    if (m_ArgsInfo.verbose_flag) std::cout<<"Initializing transform for level 1 of "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
+    if (m_ArgsInfo.spacing_given) initializer->SetControlPointSpacing( initializer->m_ControlPointSpacingArray[0]);
+    if (m_ArgsInfo.control_given) initializer->SetNumberOfControlPointsInsideTheImage(initializer->m_NumberOfControlPointsInsideTheImageArray[0]);     
+    if (m_ArgsInfo.samplingFactor_given) initializer->SetSamplingFactors(m_ArgsInfo.samplingFactor_arg);       
+    // Initialize 
+    initializer->InitializeTransform();
+
+    //-------------------------------------------------------------------------
+    // Initial parameters (passed by reference)
+    //-------------------------------------------------------------------------
+    typedef typename TransformType::ParametersType     ParametersType;
+    const unsigned int numberOfParameters =    transform->GetNumberOfParameters();
+    ParametersType parameters(numberOfParameters);
+    parameters.Fill( 0.0 );
+    transform->SetParameters( parameters );
+    if (m_ArgsInfo.initCoeff_given) initializer->SetInitialParameters(m_ArgsInfo.initCoeff_arg, parameters);
+
+           
+    //=======================================================
+    // Interpolator
+    //=======================================================
+    typedef clitk::GenericInterpolator<args_info_clitkShapedBLUTSpatioTemporalDIR, FixedImageType,TCoordRep > GenericInterpolatorType;
+    typename   GenericInterpolatorType::Pointer genericInterpolator=GenericInterpolatorType::New();
+    genericInterpolator->SetArgsInfo(m_ArgsInfo);
+    typedef itk::InterpolateImageFunction< FixedImageType, TCoordRep >  InterpolatorType;
+    typename  InterpolatorType::Pointer interpolator=genericInterpolator->GetInterpolatorPointer();
+
+
+    //=======================================================
+    // Metric
+    //=======================================================
+    typedef clitk::GenericMetric< args_info_clitkShapedBLUTSpatioTemporalDIR, FixedImageType,MovingImageType > GenericMetricType;
+    typename GenericMetricType::Pointer genericMetric=GenericMetricType::New();
+    genericMetric->SetArgsInfo(m_ArgsInfo);
+    genericMetric->SetFixedImage(fixedImagePyramid->GetOutput(0));
+    if (fixedMask) genericMetric->SetFixedImageMask(fixedMask);
+    genericMetric->SetFixedImageRegion(fixedImageRegionPyramid->GetOutput(0));
+    typedef itk::ImageToImageMetric< FixedImageType, MovingImageType >  MetricType;
+    typename  MetricType::Pointer metric=genericMetric->GetMetricPointer();
+    if (movingMask) metric->SetMovingImageMask(movingMask);
+
+#ifdef ITK_USE_OPTIMIZED_REGISTRATION_METHODS
+    if (threadsGiven) metric->SetNumberOfThreads( threads );
+#else
+    if (m_Verbose) std::cout<<"Not setting the number of threads (not compiled with USE_OPTIMIZED_REGISTRATION_METHODS)..."<<std::endl;
+#endif
+
+
+    //=======================================================
+    // Optimizer
+    //=======================================================
+    typedef clitk::GenericOptimizer<args_info_clitkShapedBLUTSpatioTemporalDIR> GenericOptimizerType;
+    GenericOptimizerType::Pointer genericOptimizer = GenericOptimizerType::New();
+    genericOptimizer->SetArgsInfo(m_ArgsInfo);
+    genericOptimizer->SetMaximize(genericMetric->GetMaximize());
+    genericOptimizer->SetNumberOfParameters(transform->GetNumberOfParameters());
+    typedef itk::SingleValuedNonLinearOptimizer OptimizerType;
+    OptimizerType::Pointer optimizer = genericOptimizer->GetOptimizerPointer();
+
+
+    //=======================================================
+    // Registration
+    //=======================================================
+    typedef clitk::SpatioTemporalMultiResolutionImageRegistrationMethod<  FixedImageType, MovingImageType >    RegistrationType;
+    typename RegistrationType::Pointer   registration  = RegistrationType::New();
+    registration->SetMetric(        metric        );
+    registration->SetOptimizer(     optimizer     );
+    registration->SetInterpolator(  interpolator  );
+    registration->SetTransform (transform);
+    if(threadsGiven) registration->SetNumberOfThreads(threads);
+    registration->SetFixedImage(  croppedFixedImage   );
+    registration->SetMovingImage(  movingImage   );
+    registration->SetFixedImageRegion( metricRegion );
+    registration->SetFixedImagePyramid( fixedImagePyramid );
+    registration->SetMovingImagePyramid( movingImagePyramid );
+    registration->SetInitialTransformParameters( transform->GetParameters() );
+    registration->SetNumberOfLevels( m_ArgsInfo.levels_arg );
+    if (m_Verbose) std::cout<<"Setting the number of resolution levels to "<<m_ArgsInfo.levels_arg<<"..."<<std::endl;
+       
+  
+    //================================================================================================
+    // Observers
+    //================================================================================================
+    if (m_Verbose)
+      {
+       // Output iteration info
+       typedef CommandIterationUpdate <RegistrationType,args_info_clitkShapedBLUTSpatioTemporalDIR> CommandIterationUpdateType;
+       typename CommandIterationUpdateType::Pointer observer = CommandIterationUpdateType::New();
+       observer->SetInitializer(initializer);
+       observer->SetArgsInfo(m_ArgsInfo);
+       observer->SetOptimizer(genericOptimizer);
+       optimizer->AddObserver( itk::IterationEvent(), observer );
+       
+       // Output level info
+       typedef RegistrationInterfaceCommand<RegistrationType,args_info_clitkShapedBLUTSpatioTemporalDIR> CommandType;
+       typename CommandType::Pointer command = CommandType::New();
+       command->SetInitializer(initializer);
+       command->SetArgsInfo(m_ArgsInfo);
+       command->SetCommandIterationUpdate(observer);
+       command->SetMaximize(genericMetric->GetMaximize());
+       command->SetMetricRegion(metricRegion);
+       registration->AddObserver( itk::IterationEvent(), command );
+      }
+
+
+    //=======================================================
+    // Let's go
+    //=======================================================
+    if (m_Verbose) std::cout << std::endl << "Starting Registration" << std::endl;
+
+    try 
+      { 
+       registration->StartRegistration(); 
+      } 
+    catch( itk::ExceptionObject & err ) 
+      { 
+       std::cerr << "ExceptionObject caught while registering!" << std::endl; 
+       std::cerr << err << std::endl; 
+       return;
+      } 
+  
+
+    //=======================================================
+    // Get the result
+    //=======================================================
+    OptimizerType::ParametersType finalParameters =  registration->GetLastTransformParameters();
+    transform->SetParameters( finalParameters );
+    if (m_Verbose)
+      {
+       std::cout<<"Stop condition description: "
+                <<registration->GetOptimizer()->GetStopConditionDescription()<<std::endl;
+      }
+
+    //=======================================================
+    // Get the BSplineSpatioTemporal coefficient images and write them
+    //=======================================================
+    if (m_ArgsInfo.coeff_given)
+      { 
+       typedef typename TransformType::CoefficientImageType CoefficientImageType;
+       typename CoefficientImageType::Pointer coefficientImage =transform->GetCoefficientImage();
+       typedef itk::ImageFileWriter<CoefficientImageType> CoeffWriterType;
+       typename CoeffWriterType::Pointer coeffWriter=CoeffWriterType::New();
+       coeffWriter->SetInput(coefficientImage);
+       coeffWriter->SetFileName(m_ArgsInfo.coeff_arg);
+       coeffWriter->Update();
+       
+      }
+    if (m_ArgsInfo.padCoeff_given)
+      { 
+       typedef  itk::Image<itk::Vector<TCoordRep, SpaceDimension>, ImageDimension> CoefficientImageType;
+       typename CoefficientImageType::Pointer coefficientImage =transform->GetPaddedCoefficientImage();
+       typedef itk::ImageFileWriter<CoefficientImageType> CoeffWriterType;
+       typename CoeffWriterType::Pointer coeffWriter=CoeffWriterType::New();
+       coeffWriter->SetInput(coefficientImage);
+       coeffWriter->SetFileName(m_ArgsInfo.padCoeff_arg);
+       coeffWriter->Update();
+      }    
+  
+
+    //=======================================================
+    // Generate the DVF (4D with 3 comps and 4D with 4 comps)
+    //=======================================================
+    typedef itk::Vector< float, SpaceDimension >  DisplacementType;
+    typedef itk::Vector< float, ImageDimension >  Displacement4DType;
+    typedef itk::Image< DisplacementType, ImageDimension >  DeformationFieldType;
+    typedef itk::Image< Displacement4DType, ImageDimension >  DeformationField4DType;
+  
+    typename DeformationFieldType::Pointer field = DeformationFieldType::New();
+    typename DeformationField4DType::Pointer field4D = DeformationField4DType::New();
+    field->SetRegions( fixedImageRegion );
+    field->SetOrigin( fixedImage->GetOrigin() );
+    field->SetSpacing( fixedImage->GetSpacing() );
+    field->SetDirection( fixedImage->GetDirection() );
+    field->Allocate();
+    field4D->SetRegions( fixedImageRegion );
+    field4D->SetOrigin( fixedImage->GetOrigin() );
+    field4D->SetSpacing( fixedImage->GetSpacing() );
+    field4D->SetDirection( fixedImage->GetDirection() );
+    field4D->Allocate();
+  
+    typedef itk::ImageRegionIteratorWithIndex< DeformationFieldType > FieldIterator;
+    typedef itk::ImageRegionIteratorWithIndex< DeformationField4DType > Field4DIterator;
+    FieldIterator fi( field, fixedImageRegion );
+    Field4DIterator fi4D( field4D, fixedImageRegion );
+    fi.GoToBegin();
+    fi4D.GoToBegin();
+  
+    typename TransformType::InputPointType  fixedPoint;
+    typename TransformType::OutputPointType movingPoint;
+    typename DeformationFieldType::IndexType index;
+  
+    DisplacementType displacement;
+    Displacement4DType displacement4D;
+    displacement4D[ImageDimension-1]=0;
+    while( ! fi.IsAtEnd() )
+      {
+       index = fi.GetIndex();
+       field->TransformIndexToPhysicalPoint( index, fixedPoint );
+       movingPoint = transform->TransformPoint( fixedPoint );
+       for (unsigned int i=0; i<SpaceDimension; i++)
+         {
+           displacement[i] = movingPoint[i] - fixedPoint[i];
+           displacement4D[i] = movingPoint[i] - fixedPoint[i];
+         }
+       fi.Set( displacement );
+       fi4D.Set(displacement4D);
+       ++fi;
+       ++fi4D;
+      }
+
+    //=======================================================
+    // Write the DVF
+    //=======================================================
+    typedef itk::ImageFileWriter< DeformationFieldType >  FieldWriterType;
+    typename FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+    fieldWriter->SetFileName( m_ArgsInfo.vf_arg );
+    fieldWriter->SetInput( field );
+    try
+      {
+       fieldWriter->Update();
+      }
+    catch( itk::ExceptionObject & excp )
+      {
+       std::cerr << "Exception thrown writing the DVF" << std::endl;
+       std::cerr << excp << std::endl;
+       return;
+      }
+  
+  
+    //=======================================================
+    // Resample the moving image
+    //=======================================================
+    typedef itk::WarpImageFilter< MovingImageType, FixedImageType, DeformationField4DType >    WarpFilterType;
+    typename WarpFilterType::Pointer warp = WarpFilterType::New();
+
+    warp->SetDeformationField( field4D );
+    warp->SetInput( movingImageReader->GetOutput() );
+    warp->SetOutputOrigin(  fixedImage->GetOrigin() );
+    warp->SetOutputSpacing( fixedImage->GetSpacing() );
+    warp->SetOutputDirection( fixedImage->GetDirection() );
+    warp->SetEdgePaddingValue( 0.0 );
+    warp->Update();
+
+    //=======================================================
+    // Write the warped image
+    //=======================================================
+    typedef itk::ImageFileWriter< FixedImageType >  WriterType;
+    typename WriterType::Pointer      writer =  WriterType::New();
+    writer->SetFileName( m_ArgsInfo.output_arg );
+    writer->SetInput( warp->GetOutput()    );
+
+    try
+      {
+       writer->Update();
+      }
+    catch( itk::ExceptionObject & err ) 
+      { 
+       std::cerr << "ExceptionObject caught !" << std::endl; 
+       std::cerr << err << std::endl; 
+       return;
+      } 
+
+    //=======================================================
+    // Calculate the difference after the deformable transform
+    //=======================================================
+    typedef clitk::DifferenceImageFilter<  FixedImageType, FixedImageType> DifferenceFilterType;
+    if (m_ArgsInfo.after_given)
+      {
+       typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
+       difference->SetValidInput( fixedImage );
+       difference->SetTestInput( warp->GetOutput() );
+      
+       try
+         {
+           difference->Update();
+         }
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught calculating the difference !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         }
+      
+       typename WriterType::Pointer differenceWriter=WriterType::New();
+       differenceWriter->SetInput(difference->GetOutput());
+       differenceWriter->SetFileName(m_ArgsInfo.after_arg);
+       differenceWriter->Update(); 
+      
+      }
+
+
+    //=======================================================
+    // Calculate the difference before the deformable transform
+    //=======================================================
+    if( m_ArgsInfo.before_given )
+      {
+
+       typename FixedImageType::Pointer moving=FixedImageType::New();
+       if (m_ArgsInfo.rigid_given)
+         {
+           typedef itk::ResampleImageFilter<MovingImageType, FixedImageType> ResamplerType;
+           typename ResamplerType::Pointer resampler=ResamplerType::New();
+           resampler->SetInput(movingImage);
+           resampler->SetOutputOrigin(fixedImage->GetOrigin());
+           resampler->SetSize(fixedImage->GetLargestPossibleRegion().GetSize());
+           resampler->SetOutputSpacing(fixedImage->GetSpacing());  
+           resampler->SetDefaultPixelValue( 0. );
+           //resampler->SetTransform(rigidTransform);
+           resampler->Update();
+           moving=resampler->GetOutput();
+         }
+       else
+         moving=movingImage;
+
+       typename DifferenceFilterType::Pointer difference = DifferenceFilterType::New();
+       difference->SetValidInput( fixedImage );
+       difference->SetTestInput( moving );
+    
+       try
+         {
+           difference->Update();
+         }
+       catch( itk::ExceptionObject & err ) 
+         { 
+           std::cerr << "ExceptionObject caught calculating the difference !" << std::endl; 
+           std::cerr << err << std::endl; 
+           return;
+         }
+
+       typename WriterType::Pointer differenceWriter=WriterType::New();
+       writer->SetFileName( m_ArgsInfo.before_arg  );
+       writer->SetInput( difference->GetOutput()  );
+       writer->Update( );
+      }
+
+    return;
+  
+  }
+}//end clitk
+
+#endif //#define clitkShapedBLUTSpatioTemporalDIRGenericFilter_txx
diff --git a/registration/clitkShapedBLUTSpatioTemporalDeformableTransform.h b/registration/clitkShapedBLUTSpatioTemporalDeformableTransform.h
new file mode 100755 (executable)
index 0000000..2d4b9e0
--- /dev/null
@@ -0,0 +1,445 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkShapedBLUTSpatioTemporalDeformableTransform_h
+#define __clitkShapedBLUTSpatioTemporalDeformableTransform_h
+#include "clitkVectorBSplineResampleImageFunctionWithLUT.h"
+#include "clitkExtractImageFilter.h"
+#include "clitkLinearCombinationImageFilter.h"
+
+//itk include
+#include "itkTransform.h"
+#include "itkImage.h"
+#include "itkImageRegion.h"
+#include "itkSpatialObject.h"
+#include "itkPasteImageFilter.h"
+#include "itkMultiplyByConstantImageFilter.h"
+
+namespace clitk
+{
+
+  template <
+    class TCoordRep = double,               // Data type for scalars, coordinate representation,vectors
+    unsigned int NInputDimensions = 3,        // Number of input dimensions
+    unsigned int NOutputDimensions = 3 >      // Number of output dimensions
+  class ITK_EXPORT ShapedBLUTSpatioTemporalDeformableTransform : 
+    public itk::Transform< TCoordRep, NInputDimensions, NOutputDimensions >
+  {
+  public:
+
+    //====================================================================
+    // Typedefs
+    //====================================================================
+    typedef ShapedBLUTSpatioTemporalDeformableTransform                         Self;
+    typedef itk::Transform< TCoordRep, NInputDimensions, NOutputDimensions > Superclass;
+    typedef itk::SmartPointer<Self>                                 Pointer;
+    typedef itk::SmartPointer<const Self>                           ConstPointer;
+      
+    /** New macro for creation of through the object factory.*/
+    itkNewMacro( Self );
+
+    /** Run-time type information (and related methods). */
+    itkTypeMacro( ShapedBLUTSpatioTemporalDeformableTransform, Transform );
+
+    /** Dimension of the output space. */
+    itkStaticConstMacro(OutputDimension, unsigned int, NOutputDimensions);
+
+    /** Dimension of the input space. */
+    itkStaticConstMacro(InputDimension, unsigned int, NInputDimensions);
+
+    //JV the number of spatial dimensions
+    itkStaticConstMacro(SpaceDimension, unsigned int, NInputDimensions-1);
+
+    /** Standard scalar type for this class. */
+    typedef typename Superclass::ScalarType ScalarType;
+
+    /** Standard parameters container. */
+    typedef typename Superclass::ParametersType ParametersType;
+
+    /** Standard Jacobian container. */
+    typedef typename Superclass::JacobianType JacobianType;
+
+    /** Standard vector type for this class. */
+    typedef itk::Vector<TCoordRep,
+                       InputDimension> InputVectorType;
+    typedef itk::Vector<TCoordRep,
+                       OutputDimension> OutputVectorType;
+  
+    /** Standard covariant vector type for this class. */
+    typedef itk::CovariantVector<TCoordRep,
+                                InputDimension> InputCovariantVectorType;
+    typedef itk::CovariantVector<TCoordRep,
+                                OutputDimension> OutputCovariantVectorType;
+
+    /** Standard vnl_vector type for this class. */
+    typedef vnl_vector_fixed<TCoordRep,
+                            InputDimension> InputVnlVectorType;
+    typedef vnl_vector_fixed<TCoordRep,
+                            OutputDimension> OutputVnlVectorType;
+
+    /** Standard coordinate point type for this class. */
+    typedef itk::Point<TCoordRep,
+                      InputDimension> InputPointType;
+    typedef itk::Point<TCoordRep,
+                      OutputDimension> OutputPointType;
+
+    //JV Parameters as images with OutputDimension number of components per Pixel
+    typedef typename ParametersType::ValueType                          ParametersValueType;
+    typedef typename itk::Vector<ParametersValueType, SpaceDimension>   PixelType;
+    typedef itk::Image<PixelType, InputDimension>                       CoefficientImageType;
+    typedef typename CoefficientImageType::Pointer                      CoefficientImagePointer;
+
+  
+    /** Typedefs for specifying the extend to the grid. */
+    typedef itk::ImageRegion<InputDimension>                RegionType;
+    typedef typename RegionType::IndexType                  IndexType;
+    typedef typename RegionType::SizeType                   SizeType;
+    typedef typename CoefficientImageType::SpacingType      SpacingType;
+    typedef typename CoefficientImageType::DirectionType    DirectionType;
+    typedef typename CoefficientImageType::PointType        OriginType;
+    typedef itk::ContinuousIndex<TCoordRep, InputDimension> ContinuousIndexType;
+  
+    //JV added for the BLUT interpolator
+    typedef itk::Vector<TCoordRep, InputDimension> OutputSpacingType;
+
+    //JV m_VectorInterpolator
+    typedef VectorBSplineResampleImageFunctionWithLUT
+    <CoefficientImageType, TCoordRep> VectorInterpolatorType;
+    typedef  typename  VectorInterpolatorType::CoefficientDataType CoefficientDataType;
+    typedef  typename  VectorInterpolatorType::CoefficientDataType WeightsDataType;
+
+    /** Typedef of the bulk transform. */
+    typedef itk::Transform<ScalarType, InputDimension, OutputDimension> BulkTransformType;
+    typedef BulkTransformType*                  BulkTransformPointer;
+
+    /** Typedef of the mask */
+    typedef itk::SpatialObject<  InputDimension >   MaskType;
+    typedef MaskType*    MaskPointer;
+
+    //====================================================================
+    // Set et Gets
+    //====================================================================
+    //JV  added for the BLUT interpolator
+    void SetSplineOrder(const unsigned int &  splineOrder);
+    void SetSplineOrders(const SizeType &  splineOrders);
+    itkGetMacro( SplineOrders, SizeType );
+    itkGetConstMacro( SplineOrders, SizeType );
+    void SetLUTSamplingFactor(const int &  samplingFactor);
+    void SetLUTSamplingFactors(const SizeType &  samplingFactors);
+    itkGetMacro( LUTSamplingFactors, SizeType );
+    itkGetConstMacro( LUTSamplingFactors,SizeType );
+
+    void SetParameters(const ParametersType & parameters);
+  
+    void SetFixedParameters(const ParametersType & parameters);
+
+    void SetParametersByValue(const ParametersType & parameters);
+
+    void SetIdentity();
+
+    /** Get the Transformation Parameters. */
+    virtual const ParametersType& GetParameters(void) const;
+
+    /** Get the Transformation Fixed Parameters. */
+    virtual const ParametersType& GetFixedParameters(void) const;
+  
+    // The coefficientImage
+    virtual CoefficientImagePointer GetCoefficientImage()
+    { return m_CoefficientImage; }
+    virtual const CoefficientImagePointer  GetCoefficientImage() const
+    { return m_CoefficientImage; }
+    virtual void SetCoefficientImage(CoefficientImagePointer image);  
+
+    // The padded coefficient image
+    virtual CoefficientImagePointer GetPaddedCoefficientImage()
+    { return m_PaddedCoefficientImage; }
+    virtual const CoefficientImagePointer  GetPaddedCoefficientImage() const
+    { return m_PaddedCoefficientImage; }
+    // virtual void SetPaddedCoefficientImage(CoefficientImagePointer image);  
+
+    /** This method specifies the region over which the grid resides. */
+    virtual void SetGridRegion( const RegionType& region );
+    itkGetMacro( GridRegion, RegionType );
+    itkGetConstMacro( GridRegion, RegionType );
+
+    /** This method specifies the grid spacing or resolution. */
+    virtual void SetGridSpacing( const SpacingType& spacing );
+    itkGetMacro( GridSpacing, SpacingType );
+    itkGetConstMacro( GridSpacing, SpacingType );
+
+    /** This method specifies the grid directions . */
+    virtual void SetGridDirection( const DirectionType & spacing );
+    itkGetMacro( GridDirection, DirectionType );
+    itkGetConstMacro( GridDirection, DirectionType );
+
+    /** This method specifies the grid origin. */
+    virtual void SetGridOrigin( const OriginType& origin );
+    itkGetMacro( GridOrigin, OriginType );
+    itkGetConstMacro( GridOrigin, OriginType );
+    
+    // Set the bulk transform, real pointer
+    // itkSetConstObjectMacro( BulkTransform, BulkTransformType );
+    // itkGetConstObjectMacro( BulkTransform, BulkTransformType );
+    void SetBulkTransform(BulkTransformPointer b){m_BulkTransform=b;}
+    BulkTransformPointer GetBulkTransform(void) {return m_BulkTransform;}
+
+    //Set mask, inside transform applies, outside zero, real pointer
+    void SetMask(MaskPointer m){m_Mask=m;}
+
+    // JV the shape
+    itkSetMacro( TransformShape , unsigned int  );
+    itkGetMacro( TransformShape , unsigned int  );
+    itkGetConstMacro( TransformShape, unsigned int  );
+
+    /** Transform points by a BSpline deformable transformation. */
+    OutputPointType  TransformPoint(const InputPointType  &point ) const;
+  
+    // JV added for just the deformable part, without bulk
+    OutputPointType  DeformablyTransformPoint(const InputPointType  &point ) const;
+  
+    /** Parameter index array type. */
+    typedef itk::Array<unsigned long> ParameterIndexArrayType;
+
+    /** Transform points by a BSpline deformable transformation. 
+     * On return, weights contains the interpolation weights used to compute the 
+     * deformation and indices of the x (zeroth) dimension coefficient parameters
+     * in the support region used to compute the deformation.
+     * Parameter indices for the i-th dimension can be obtained by adding
+     * ( i * this->GetNumberOfParametersPerDimension() ) to the indices array.
+     */
+
+    // JV not implemented
+    //  virtual void TransformPoint( const InputPointType & inputPoint,
+    //                                  OutputPointType & outputPoint,
+    //                                  WeightsType & weights,
+    //                                  ParameterIndexArrayType & indices, 
+    //                                  bool & inside ) const;
+    //     virtual void DeformablyTransformPoint( const InputPointType & inputPoint,
+    //                                            OutputPointType & outputPoint,
+    //                                            WeightsType & weights,
+    //                                            ParameterIndexArrayType & indices, 
+    //                                            bool & inside ) const;
+    //     virtual void GetJacobian( const InputPointType & inputPoint,
+    //                               WeightsType & weights,
+    //                               ParameterIndexArrayType & indices
+    //                               ) const;
+   
+    /** Method to transform a vector - 
+     *  not applicable for this type of transform. */
+    virtual OutputVectorType TransformVector(const InputVectorType &) const
+    { 
+      itkExceptionMacro(<< "Method not applicable for deformable transform." );
+      return OutputVectorType(); 
+    }
+
+    /** Method to transform a vnl_vector - 
+     *  not applicable for this type of transform */
+    virtual OutputVnlVectorType TransformVector(const InputVnlVectorType &) const
+    { 
+      itkExceptionMacro(<< "Method not applicable for deformable transform. ");
+      return OutputVnlVectorType(); 
+    }
+
+    /** Method to transform a CovariantVector - 
+     *  not applicable for this type of transform */
+    virtual OutputCovariantVectorType TransformCovariantVector(
+                                                              const InputCovariantVectorType &) const
+    { 
+      itkExceptionMacro(<< "Method not applicable for deformable transfrom. ");
+      return OutputCovariantVectorType(); 
+    } 
+    
+    /** Compute the Jacobian Matrix of the transformation at one point */
+    virtual const JacobianType& GetJacobian(const InputPointType  &point ) const;
+
+    /** Return the number of parameters that completely define the Transfom */
+    virtual unsigned int GetNumberOfParameters(void) const;
+
+    //JV Return the padded number of parameters
+    virtual unsigned int GetPaddedNumberOfParameters(void) const;
+
+    /** Return the number of parameters per dimension */
+    unsigned int GetNumberOfParametersPerDimension(void) const;
+
+    /** Return the region of the grid wholly within the support region */
+    itkGetConstReferenceMacro( ValidRegion, RegionType );
+
+    /** Indicates that this transform is linear. That is, given two
+     * points P and Q, and scalar coefficients a and b, then
+     *
+     *           T( a*P + b*Q ) = a * T(P) + b * T(Q)
+     */
+    virtual bool IsLinear() const { return false; }
+
+   //unsigned int GetNumberOfAffectedWeights() const;
+
+  protected:
+    /** Print contents of an BSplineSpatioTemporalDeformableTransform. */
+    void PrintSelf(std::ostream &os, itk::Indent indent) const;
+
+
+    ShapedBLUTSpatioTemporalDeformableTransform();
+    virtual ~ShapedBLUTSpatioTemporalDeformableTransform();
+
+    /** Wrap flat array into images of coefficients. */
+    void WrapAsImages();
+
+    // JV Pad/Extract the coefficient image
+    void PadCoefficientImage(void);
+    typename  CoefficientImageType::Pointer ExtractTemporalRow(const typename CoefficientImageType::Pointer& coefficientImage, unsigned int temporalIndex);
+    //void ExtractCoefficientImage(void);
+
+    /** Wrap flat array into images of coefficients. */
+    inline void WrapRegion(const RegionType& support, 
+                          RegionType& first, 
+                          RegionType& second, 
+                          RegionType& third, 
+                          std::vector<RegionType>& bc, 
+                          std::vector<double>& bcValues,
+                          std::vector<RegionType>& bc2, 
+                          std::vector<double>& bc2Values,
+                          std::vector<RegionType>& bc3, 
+                          std::vector<double>& bc3Values,
+                          unsigned int& m_InitialOffset ) const;
+
+    /** Convert an input point to a continuous index inside the BSpline grid */
+    void TransformPointToContinuousIndex( const InputPointType & point, ContinuousIndexType & index ) const;
+
+  private:
+    ShapedBLUTSpatioTemporalDeformableTransform(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+
+    /** The bulk transform. */
+    BulkTransformPointer  m_BulkTransform;
+    MaskPointer m_Mask;
+
+    // JV added for BLUT interpolator
+    SizeType m_SplineOrders;
+    //OutputSpacingType m_OutputSpacing;
+    SizeType m_LUTSamplingFactors;
+
+    /** Variables defining the coefficient grid extend. */
+    RegionType    m_GridRegion;
+    SpacingType   m_GridSpacing;
+    DirectionType m_GridDirection;
+    OriginType    m_GridOrigin;
+
+    // JV additional variables for the padded region
+    RegionType    m_PaddedGridRegion;
+    OriginType    m_PaddedGridOrigin;    
+  
+
+    DirectionType m_PointToIndex;
+    DirectionType m_IndexToPoint;
+  
+    RegionType    m_ValidRegion;
+
+    /** Variables defining the interpolation support region. */
+    SizeType m_Offset;
+    itk::FixedArray<bool,InputDimension>    m_SplineOrderOdd;
+    SizeType      m_SupportSize;
+    IndexType     m_ValidRegionLast;
+  
+    /** Array holding images wrapped from the flat parameters. */
+    CoefficientImagePointer   m_WrappedImage;
+
+    /** Vector image representing the B-spline coefficients 
+     *  in each dimension. */
+    CoefficientImagePointer   m_CoefficientImage;
+    CoefficientImagePointer   m_PaddedCoefficientImage;
+
+    /** Jacobian as OutputDimension number of images. */
+    typedef typename JacobianType::ValueType JacobianValueType;
+    typedef typename itk::Vector<JacobianValueType,SpaceDimension> JacobianPixelType;
+    typedef itk::Image<JacobianPixelType, OutputDimension> JacobianImageType;
+    typename JacobianImageType::Pointer m_JacobianImage[OutputDimension];
+    typename JacobianImageType::Pointer m_PaddedJacobianImage[OutputDimension];
+    typedef itk::ImageRegionIterator<JacobianImageType> IteratorType;
+
+    //JV for J calculation
+    IndexType m_NullIndex;
+    SizeType m_NullSize;
+
+    mutable RegionType    m_SupportRegion;
+    mutable IndexType    m_SupportIndex;
+    mutable RegionType    m_FirstRegion;
+    mutable RegionType    m_SecondRegion;
+    mutable RegionType    m_ThirdRegion;
+    mutable unsigned int m_ThirdSize;
+    mutable unsigned int m_InitialOffset;
+
+    mutable std::vector<IteratorType>  m_BCIterators[SpaceDimension];
+    mutable std::vector<double>   m_BCValues;
+    mutable std::vector<RegionType>  m_BCRegions;
+    mutable unsigned int m_BCSize;
+
+    mutable std::vector<IteratorType>  m_BC2Iterators[SpaceDimension];
+    mutable std::vector<double>   m_BC2Values;
+    mutable std::vector<RegionType>  m_BC2Regions;
+    mutable unsigned int m_BC2Size;
+
+    mutable std::vector<IteratorType>  m_BC3Iterators[SpaceDimension];
+    mutable std::vector<double>   m_BC3Values;
+    mutable std::vector<RegionType>  m_BC3Regions;
+    mutable unsigned int m_BC3Size;
+
+    mutable RegionType m_BCRegion;
+    mutable IteratorType m_FirstIterator[SpaceDimension];
+    mutable IteratorType m_SecondIterator[SpaceDimension];
+    mutable IteratorType m_ThirdIterator[SpaceDimension];
+    mutable ContinuousIndexType m_Index;
+
+    //JV add a padded Jacobian matrix
+    mutable JacobianType m_PaddedJacobian;
+    mutable JacobianPixelType m_ZeroVector;
+
+    /** Keep track of last support region used in computing the Jacobian
+     * for fast resetting of Jacobian to zero.
+     */
+    mutable IndexType m_LastJacobianIndex;
+   
+    /** Keep a pointer to the input parameters. */
+    const ParametersType *  m_InputParametersPointer;
+
+    /** Internal parameters buffer. */
+    ParametersType          m_InternalParametersBuffer;
+
+    //JV  the BLUT interpolator
+    typename VectorInterpolatorType::Pointer m_VectorInterpolator;
+
+    // the coefficients to apply the BC
+    std::vector<std::vector<double> > m_Weights;
+    std::vector<std::vector<double> > m_WeightRatio;
+  
+    /** Check if a continuous index is inside the valid region. */
+    bool InsideValidRegion( const ContinuousIndexType& index ) const;
+
+    // JV Shape
+    unsigned int m_TransformShape;
+
+
+  }; //class ShapedBLUTSpatioTemporalDeformableTransform
+
+
+}  // namespace itk
+
+#if ITK_TEMPLATE_TXX
+# include "clitkShapedBLUTSpatioTemporalDeformableTransform.txx"
+#endif
+
+
+#endif // __clitkShapedBLUTSpatioTemporalDeformableTransform_h 
diff --git a/registration/clitkShapedBLUTSpatioTemporalDeformableTransform.txx b/registration/clitkShapedBLUTSpatioTemporalDeformableTransform.txx
new file mode 100755 (executable)
index 0000000..7600276
--- /dev/null
@@ -0,0 +1,4340 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkShapedBLUTSpatioTemporalDeformableTransform_txx
+#define __clitkShapedBLUTSpatioTemporalDeformableTransform_txx
+#include "clitkShapedBLUTSpatioTemporalDeformableTransform.h"
+
+//itk
+#include "itkContinuousIndex.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkImageRegionConstIteratorWithIndex.h"
+#include "itkIdentityTransform.h"
+
+namespace clitk
+{
+
+  // Constructor with default arguments
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::ShapedBLUTSpatioTemporalDeformableTransform():Superclass(OutputDimension,0)
+  {
+    unsigned int i;
+    
+    //JV default spline order
+    for ( i=0;i<InputDimension; i++)
+      m_SplineOrders[i]=3;
+
+    //JV default LUTSamplingfactor
+    for ( i=0;i<InputDimension; i++)
+      m_LUTSamplingFactors[i]=20;
+
+    for (i=0;i<InputDimension; i++)
+      m_SupportSize[i] = m_SplineOrders[i]+1;
+
+    //Instantiate a Vector Bspline Interpolator
+    m_VectorInterpolator =VectorInterpolatorType::New();
+    m_VectorInterpolator->SetLUTSamplingFactors(m_LUTSamplingFactors);
+    m_VectorInterpolator->SetSplineOrders(m_SplineOrders);
+
+    // Set Bulk transform to NULL (no bulk performed)
+    m_BulkTransform = NULL;
+
+    // Mask
+    m_Mask=NULL;
+
+    // Shape
+    m_TransformShape=0;
+
+    // Default grid size is zero
+    m_NullSize.Fill(0);
+    m_NullIndex.Fill(0);
+  
+    //JV region containing the parameters
+    m_GridRegion.SetSize( m_NullSize);
+    m_GridRegion.SetIndex( m_NullIndex );
+
+    //JV use second region over the images
+    m_PaddedGridRegion.SetSize(m_NullSize);
+    m_PaddedGridRegion.SetIndex(m_NullIndex);
+    
+    //JV Maintain two origins
+    m_GridOrigin.Fill( 0.0 );  // default origin is all zeros
+    m_PaddedGridOrigin.Fill( 0.0 );  // default origin is all zeros
+    
+    m_GridSpacing.Fill( 1.0 ); // default spacing is all ones
+    m_GridDirection.SetIdentity(); // default spacing is all ones
+
+    m_InternalParametersBuffer = ParametersType(0);
+    // Make sure the parameters pointer is not NULL after construction.
+    m_InputParametersPointer = &m_InternalParametersBuffer;
+
+    // Initialize coeffient images
+    m_WrappedImage = CoefficientImageType::New();
+    m_WrappedImage->SetRegions( m_GridRegion );
+    m_WrappedImage->SetOrigin( m_GridOrigin.GetDataPointer() );
+    m_WrappedImage->SetSpacing( m_GridSpacing.GetDataPointer() );
+    m_WrappedImage->SetDirection( m_GridDirection );
+
+    // JV Initialize the padded version
+    m_PaddedCoefficientImage = CoefficientImageType::New();
+    m_PaddedCoefficientImage->SetRegions( m_PaddedGridRegion );
+    m_PaddedCoefficientImage->SetOrigin( m_GridOrigin.GetDataPointer() );
+    m_PaddedCoefficientImage->SetSpacing( m_GridSpacing.GetDataPointer() );
+    m_PaddedCoefficientImage->SetDirection( m_GridDirection );
+
+    m_CoefficientImage = NULL;
+  
+    // Variables for computing interpolation
+    for (i=0; i <InputDimension;i++)
+      {
+       m_Offset[i] = m_SplineOrders[i] / 2;
+       if ( m_SplineOrders[i] % 2 ) 
+         {
+           m_SplineOrderOdd[i] = true;
+         }
+       else
+         {
+           m_SplineOrderOdd[i] = false;
+         }
+      }
+
+    //JV padded should be used when checking
+    m_ValidRegion = m_PaddedGridRegion;
+       
+    // Initialize jacobian images 
+    for (i=0; i <OutputDimension;i++)
+      {
+       m_JacobianImage[i] = JacobianImageType::New();
+       m_JacobianImage[i]->SetRegions( m_GridRegion );
+       m_JacobianImage[i]->SetOrigin( m_GridOrigin.GetDataPointer() );
+       m_JacobianImage[i]->SetSpacing( m_GridSpacing.GetDataPointer() );
+       m_JacobianImage[i]->SetDirection( m_GridDirection );
+      }
+    
+    /** Fixed Parameters store the following information:
+     *     Grid Size
+     *     Grid Origin
+     *     Grid Spacing
+     *     Grid Direction */
+    //JV we add the splineOrders, LUTsamplingfactor, m_Mask  and m_BulkTransform
+    /*
+      Spline orders
+      Sampling factors
+      m_Mask
+      m_BulkTransform
+      The size of these is equal to the  NInputDimensions
+    *********************************************************/
+    this->m_FixedParameters.SetSize ( NInputDimensions * (NInputDimensions + 5)+3 );
+    this->m_FixedParameters.Fill ( 0.0 );
+    for ( i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[2*NInputDimensions+i] = m_GridSpacing[i];
+      }
+    for (unsigned int di=0; di<NInputDimensions; di++)
+      {
+       for (unsigned int dj=0; dj<NInputDimensions; dj++)
+         {
+           this->m_FixedParameters[3*NInputDimensions+(di*NInputDimensions+dj)] = m_GridDirection[di][dj];
+         }
+      }
+
+    //JV add splineOrders
+    for ( i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[ ( (3+NInputDimensions)*NInputDimensions)+i] = (this->GetSplineOrders())[i];
+      }
+    
+    //JV add LUTsamplingFactors
+    for ( i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[( (4+NInputDimensions)*NInputDimensions)+i ] = this->GetLUTSamplingFactors()[i];
+      }
+
+    // JV add the mask pointer
+    this->m_FixedParameters[( (5+NInputDimensions)*NInputDimensions)]=(double)((size_t)m_Mask);
+
+    // JV add the bulkTransform pointer
+    this->m_FixedParameters[( (5+NInputDimensions)*NInputDimensions) +1]=(double)((size_t)m_BulkTransform);
+
+    // JV add the Transform shape
+    this->m_FixedParameters[( (5+NInputDimensions)*NInputDimensions) +2]=(double)(m_TransformShape);
+
+
+    // Calculate the PointToIndex matrices
+    DirectionType scale;
+    for( unsigned int i=0; i<OutputDimension; i++)
+      {
+       scale[i][i] = m_GridSpacing[i];
+      }
+
+    m_IndexToPoint = m_GridDirection * scale;
+    m_PointToIndex = m_IndexToPoint.GetInverse();
+    m_LastJacobianIndex = m_ValidRegion.GetIndex();
+
+
+    //Weights to be used for the BC
+    m_Weights.resize(4);
+    std::vector<double> weights(5);
+    for (i=0; i<4; i++) 
+      weights[0]=0;
+    // NN
+    weights[0]=1;
+    weights[1]=1./2;
+    weights[2]=0;
+    weights[3]=0;
+    weights[4]=0;
+    m_Weights[0]=weights;
+
+    // Linear
+    weights[0]=1;
+    weights[1]=1./2;
+    weights[2]=0;
+    weights[3]=0;
+    weights[4]=0;
+    m_Weights[1]=weights;
+
+    // quadratic
+    weights[0]=3./4.;
+    weights[1]=1./2.;
+    weights[2]=1./8.;
+    weights[3]=0;
+    weights[4]=0;
+    m_Weights[2]=weights;
+
+    // cubic
+    weights[0]=2./3.;
+    weights[1]=23./48. ;
+    weights[2]=1./6.;
+    weights[3]=1./48.;
+    weights[4]=0;
+    m_Weights[3]=weights;
+
+    // Update the WeightRatios
+    m_WeightRatio.resize(4);
+    for (unsigned int i=0; i<4; i++)
+      {
+       m_WeightRatio[i].resize(4);
+       for (unsigned int j=0; j<4; j++)
+         m_WeightRatio[i][j]=m_Weights[m_SplineOrders[InputDimension-1]][i]/ m_Weights[m_SplineOrders[InputDimension-1]][j];
+      }
+
+    //JV initialize some variables for jacobian calculation
+    m_SupportRegion.SetSize(m_SupportSize);
+    m_SupportIndex.Fill(0);
+    m_SupportRegion.SetIndex(m_SupportIndex);
+    for (  i = 0; i < SpaceDimension ; i++ ) 
+      m_ZeroVector[i]=itk::NumericTraits<JacobianValueType>::Zero;
+    
+    m_InitialOffset=0;
+    m_FirstRegion.SetSize(m_NullSize);
+    m_FirstRegion.SetIndex(m_NullIndex);
+    m_SecondRegion.SetSize(m_NullSize);
+    m_SecondRegion.SetIndex(m_NullIndex);
+    m_ThirdRegion.SetSize(m_NullSize);
+    m_ThirdRegion.SetIndex(m_NullIndex);
+        
+    m_BCValues.resize(0);
+    m_BCRegions.resize(0);
+    m_BCSize=0;
+    m_BC2Values.resize(0);
+    m_BC2Regions.resize(0);
+    m_BC2Size=0;
+    m_BC3Values.resize(0);
+    m_BC3Regions.resize(0);
+    m_BC3Size=0;
+
+
+    for (  i = 0; i < SpaceDimension ; i++ )
+      {
+       m_FirstIterator[i]= IteratorType( m_JacobianImage[i], m_FirstRegion);
+       m_SecondIterator[i]= IteratorType( m_JacobianImage[i], m_SecondRegion);
+       m_ThirdIterator[i]= IteratorType( m_JacobianImage[i], m_ThirdRegion);
+       m_BCIterators[i].resize(0);
+       m_BC2Iterators[i].resize(0);
+       m_BC3Iterators[i].resize(0);
+      }
+
+    this->Modified();
+
+  }
+    
+
+  // Destructor
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::~ShapedBLUTSpatioTemporalDeformableTransform()
+  {
+
+  }
+
+
+  // JV set Spline Order
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetSplineOrder(const unsigned int & splineOrder)
+  {
+    SizeType splineOrders;
+    for (unsigned int i=0;i<InputDimension;i++)splineOrders[i]=splineOrder;
+
+    this->SetSplineOrders(splineOrders);
+  }
+   
+
+  // JV set Spline Orders
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetSplineOrders(const SizeType & splineOrders)
+  {
+    if(m_SplineOrders!=splineOrders)
+      {
+       m_SplineOrders=splineOrders;
+       
+       //update the interpolation function
+       m_VectorInterpolator->SetSplineOrders(m_SplineOrders);
+       
+       //update the varaibles for computing interpolation
+       for (unsigned int i=0; i <InputDimension;i++)
+         {
+           m_SupportSize[i] = m_SplineOrders[i]+1;
+           m_Offset[i] = m_SplineOrders[i] / 2;
+           
+           if ( m_SplineOrders[i] % 2 ) 
+             {
+               m_SplineOrderOdd[i] = true;
+             }
+           else
+             {
+               m_SplineOrderOdd[i] = false;
+             }
+         }
+
+       //SupportSize is updated!, update regions
+       //JV initialize some variables for jacobian calculation
+       m_SupportRegion.SetSize(m_SupportSize);
+       m_SupportIndex.Fill(0);
+       m_SupportRegion.SetIndex(m_SupportIndex);
+       
+       // Update the WeightRatios
+       for (unsigned int i=0; i<4; i++)
+         for (unsigned int j=0; j<4; j++)
+           m_WeightRatio[i][j]=m_Weights[m_SplineOrders[InputDimension-1]][i]/ m_Weights[m_SplineOrders[InputDimension-1]][j];
+
+       this->Modified();
+      }
+  }
+   
+
+  // JV set sampling factor
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetLUTSamplingFactor( const int & samplingFactor)
+  {
+    SizeType samplingFactors;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      samplingFactors[i]=samplingFactor;
+    
+    //update the interpolation function
+    this->SetLUTSamplingFactors(samplingFactors);
+  }
+
+
+  // JV set sampling factors
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetLUTSamplingFactors( const SizeType & samplingFactors)
+  {
+    if(m_LUTSamplingFactors!=samplingFactors)
+      {
+       for (unsigned int i=0; i<NInputDimensions; i++)
+         m_LUTSamplingFactors[i]=samplingFactors[i];
+       
+       //update the interpolation function
+       m_VectorInterpolator->SetLUTSamplingFactors(m_LUTSamplingFactors);
+       
+       this->Modified();
+      }
+  }
+
+
+  // Get the number of parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  unsigned int
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetNumberOfParameters(void) const
+  {
+
+    // The number of parameters equal SpaceDimension * number of
+    // of pixels in the grid region.
+    return ( static_cast<unsigned int>( SpaceDimension ) *
+            static_cast<unsigned int>( m_GridRegion.GetNumberOfPixels() ) );
+
+  }
+
+
+  // Get the padded number of parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  unsigned int
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetPaddedNumberOfParameters(void) const
+  {
+
+    // The number of parameters equal SpaceDimension * number of
+    // of pixels in the grid region.
+    return ( static_cast<unsigned int>( SpaceDimension ) *
+            static_cast<unsigned int>( m_PaddedGridRegion.GetNumberOfPixels() ) );
+
+  }
+
+
+
+  // Get the number of parameters per dimension
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  unsigned int
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetNumberOfParametersPerDimension(void) const
+  {
+    // The number of parameters per dimension equal number of
+    // of pixels in the grid region.
+    return ( static_cast<unsigned int>( m_GridRegion.GetNumberOfPixels() ) );
+
+  }
+
+
+  // Set the grid region
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridRegion( const RegionType & region )
+  {
+    if ( m_GridRegion != region )
+      {
+       m_GridRegion = region;
+       m_PaddedGridRegion=region;
+       
+       // JV set the padded region
+       typename CoefficientImageType::RegionType::SizeType paddedSize= region.GetSize();
+       
+       //JV   size dependes on shape
+       switch (m_TransformShape)
+         {
+         case 0:
+         case 1:
+           paddedSize[InputDimension-1]+=4;
+           break;
+         case 2:
+         case 3:
+           paddedSize[InputDimension-1]+=4;
+           break;
+         case 4:
+         case 5:
+           paddedSize[InputDimension-1]+=3;
+           break;
+         case 6:
+         case 7:
+           paddedSize[InputDimension-1]+=2;
+           break;
+         case 8:
+         case 9:
+           paddedSize[InputDimension-1]+=3;
+           break;
+         default:
+           paddedSize[InputDimension-1]=+1;
+         }
+       m_PaddedGridRegion.SetSize(paddedSize);
+       
+       // Set regions for each coefficient and jacobian image
+       m_WrappedImage->SetRegions( m_GridRegion );
+       m_PaddedCoefficientImage->SetRegions( m_PaddedGridRegion );
+       m_PaddedCoefficientImage->Allocate();
+       for (unsigned int j=0; j <OutputDimension;j++)
+         {
+           m_JacobianImage[j]->SetRegions( m_GridRegion );
+         }
+       
+       // JV used the padded version for the valid region
+       // Set the valid region
+       // If the grid spans the interval [start, last].
+       // The valid interval for evaluation is [start+offset, last-offset]
+       // when spline order is even.
+       // The valid interval for evaluation is [start+offset, last-offset)
+       // when spline order is odd.
+       // Where offset = vcl_floor(spline / 2 ).
+       // Note that the last pixel is not included in the valid region
+       // with odd spline orders.
+       typename RegionType::SizeType size = m_PaddedGridRegion.GetSize();
+       typename RegionType::IndexType index = m_PaddedGridRegion.GetIndex();
+       for ( unsigned int j = 0; j < NInputDimensions; j++ )
+         {
+           index[j] += 
+             static_cast< typename RegionType::IndexValueType >( m_Offset[j] );
+           size[j] -= 
+             static_cast< typename RegionType::SizeValueType> ( 2 * m_Offset[j] );
+           m_ValidRegionLast[j] = index[j] +
+             static_cast< typename RegionType::IndexValueType >( size[j] ) - 1;
+         }
+       m_ValidRegion.SetSize( size );
+       m_ValidRegion.SetIndex( index );
+       
+       // If we are using the default parameters, update their size and set to identity.
+       // Input parameters point to internal buffer => using default parameters.
+       if (m_InputParametersPointer == &m_InternalParametersBuffer)
+         {
+           // Check if we need to resize the default parameter buffer.
+           if ( m_InternalParametersBuffer.GetSize() != this->GetNumberOfParameters() )
+             {
+               m_InternalParametersBuffer.SetSize( this->GetNumberOfParameters() );
+               // Fill with zeros for identity.
+               m_InternalParametersBuffer.Fill( 0 );
+             }
+         }
+
+       this->Modified();
+      }
+  }
+
+
+  // Set the grid spacing
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridSpacing( const SpacingType & spacing )
+  {
+    if ( m_GridSpacing != spacing )
+      {
+       m_GridSpacing = spacing;
+
+       // Set spacing for each coefficient and jacobian image
+       m_WrappedImage->SetSpacing( m_GridSpacing.GetDataPointer() );
+       m_PaddedCoefficientImage->SetSpacing( m_GridSpacing.GetDataPointer() );
+       for (unsigned int j=0; j <OutputDimension; j++) m_JacobianImage[j]->SetSpacing( m_GridSpacing.GetDataPointer() );
+       
+       // Set scale
+       DirectionType scale;
+       for( unsigned int i=0; i<OutputDimension; i++)
+         {
+           scale[i][i] = m_GridSpacing[i];
+         }
+
+       m_IndexToPoint = m_GridDirection * scale;
+       m_PointToIndex = m_IndexToPoint.GetInverse();
+
+       this->Modified();
+      }
+
+  }
+
+  // Set the grid direction
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridDirection( const DirectionType & direction )
+  {
+    if ( m_GridDirection != direction )
+      {
+       m_GridDirection = direction;
+
+       // Set direction for each coefficient and jacobian image
+       m_WrappedImage->SetDirection( m_GridDirection );
+       m_PaddedCoefficientImage->SetDirection( m_GridDirection );
+       for (unsigned int j=0; j <OutputDimension; j++) m_JacobianImage[j]->SetDirection( m_GridDirection );
+       
+       // Set scale
+       DirectionType scale;
+       for( unsigned int i=0; i<OutputDimension; i++)
+         {
+           scale[i][i] = m_GridSpacing[i];
+         }
+
+       m_IndexToPoint = m_GridDirection * scale;
+       m_PointToIndex = m_IndexToPoint.GetInverse();
+
+       this->Modified();
+      }
+
+  }
+
+
+  // Set the grid origin
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridOrigin( const OriginType& origin )
+  {
+    if( m_GridOrigin!=origin)
+      {
+       m_GridOrigin = origin;
+       
+       // JV The origin depends on the shape 
+       switch (m_TransformShape)
+         {
+         case 0:
+         case 1:
+           m_PaddedGridOrigin=origin;
+           m_PaddedGridOrigin[InputDimension-1]=origin[InputDimension-1]-2* m_GridSpacing[InputDimension-1];
+           break;
+         case 2:
+         case 3:
+           m_PaddedGridOrigin=origin;
+           m_PaddedGridOrigin[InputDimension-1]=origin[InputDimension-1]-1* m_GridSpacing[InputDimension-1];
+           break;
+         case 4:
+         case 5:
+           m_PaddedGridOrigin=origin;
+           m_PaddedGridOrigin[InputDimension-1]=origin[InputDimension-1]-1* m_GridSpacing[InputDimension-1];
+           break;
+         case 6:
+         case 7:
+           m_PaddedGridOrigin=origin;
+           break;
+         case 8:
+         case 9:
+           m_PaddedGridOrigin=origin;
+           m_PaddedGridOrigin[InputDimension-1]=origin[InputDimension-1]-1* m_GridSpacing[InputDimension-1];
+           break;
+         default: 
+           m_PaddedGridOrigin=origin;
+         }
+    
+       // Set origin for each coefficient and jacobianimage
+       m_WrappedImage->SetOrigin( m_GridOrigin.GetDataPointer() );
+       m_PaddedCoefficientImage->SetOrigin( m_PaddedGridOrigin.GetDataPointer() );
+       for (unsigned int j=0; j <OutputDimension; j++) m_JacobianImage[j]->SetOrigin( m_GridOrigin.GetDataPointer() );
+       
+       this->Modified();
+      }
+  }
+
+
+  // Set the parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetIdentity()
+  {
+    if( m_InputParametersPointer )
+      {
+       ParametersType * parameters =
+         const_cast<ParametersType *>( m_InputParametersPointer );
+       parameters->Fill( 0.0 );
+       this->Modified();
+      }
+    else 
+      {
+       itkExceptionMacro( << "Input parameters for the spline haven't been set ! "
+                          << "Set them using the SetParameters or SetCoefficientImage method first." );
+      }
+  }
+
+
+  // Set the parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetParameters( const ParametersType & parameters )
+  {
+
+    // Check if the number of parameters match the
+    // Expected number of parameters
+    if ( parameters.Size() != this->GetNumberOfParameters() )
+      {
+       itkExceptionMacro(<<"Mismatched between parameters size "
+                         << parameters.size() 
+                         << " and region size "
+                         << m_GridRegion.GetNumberOfPixels() );
+      }
+
+    // Clean up buffered parameters
+    m_InternalParametersBuffer = ParametersType( 0 );
+
+    // Keep a reference to the input parameters
+    m_InputParametersPointer = &parameters;
+
+    // Wrap flat array as images of coefficients
+    this->WrapAsImages();
+
+    //JV Set padded input to vector interpolator
+    m_VectorInterpolator->SetInputImage(this->GetPaddedCoefficientImage());
+
+    // Modified is always called since we just have a pointer to the
+    // parameters and cannot know if the parameters have changed.
+    this->Modified();
+  }
+
+
+  // Set the Fixed Parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetFixedParameters( const ParametersType & parameters )
+  {
+    // JV number should be exact, no defaults for spacing
+    if ( parameters.Size() != NInputDimensions * (5 + NInputDimensions)+3 )
+      {
+       itkExceptionMacro(<< "Mismatched between parameters size "
+                         << parameters.size() 
+                         << " and number of fixed parameters "
+                         << NInputDimensions * (5 + NInputDimensions)+3 );
+      }
+    /********************************************************* 
+    Fixed Parameters store the following information:
+        Grid Size
+        Grid Origin
+        Grid Spacing
+        Grid Direction */
+    // JV we add the splineOrders, LUTsamplingfactor, mask pointer and bulktransform pointer
+    /*
+      Spline orders
+      Sampling factors
+      m_Mask
+      m_BulkTransform
+      m_TransformShape
+
+      The size of these is equal to the  NInputDimensions
+    *********************************************************/
+  
+    /** Set the Grid Parameters */
+    SizeType   gridSize;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       gridSize[i] = static_cast<int> (parameters[i]);
+      }
+    RegionType bsplineRegion;
+    bsplineRegion.SetSize( gridSize );
+  
+    /** Set the Origin Parameters */
+    OriginType origin;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       origin[i] = parameters[NInputDimensions+i];
+      }
+  
+    /** Set the Spacing Parameters */
+    SpacingType spacing;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       spacing[i] = parameters[2*NInputDimensions+i];
+      }
+
+    /** Set the Direction Parameters */
+    DirectionType direction;
+    for (unsigned int di=0; di<NInputDimensions; di++)
+      {
+       for (unsigned int dj=0; dj<NInputDimensions; dj++)
+         {
+           direction[di][dj] = parameters[3*NInputDimensions+(di*NInputDimensions+dj)];
+         }
+      }
+
+    //JV add the spline orders
+    SizeType splineOrders;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       splineOrders[i]=parameters[(3+NInputDimensions)*NInputDimensions+i];
+      }
+
+    //JV add the LUT sampling factor
+    SizeType  samplingFactors;
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       samplingFactors[i]=parameters[(4+NInputDimensions)*NInputDimensions+i];
+      }
+
+    //JV add the MaskPointer
+    m_Mask=((MaskPointer)( (size_t)parameters[(5+NInputDimensions)*NInputDimensions]));
+
+    //JV add the MaskPointer
+    m_BulkTransform=((BulkTransformPointer)( (size_t)parameters[(5+NInputDimensions)*NInputDimensions+1]));
+
+    //JV add the TransformShape
+    m_TransformShape=((unsigned int)parameters[(5+NInputDimensions)*NInputDimensions+2]);
+
+    // Set the members 
+    this->SetSplineOrders( splineOrders );
+    this->SetGridSpacing( spacing );
+    this->SetGridDirection( direction );
+    this->SetGridOrigin( origin );
+    this->SetGridRegion( bsplineRegion );
+    this->SetLUTSamplingFactors( samplingFactors );
+      
+  }
+
+
+  // Wrap flat parameters as images
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::WrapAsImages()
+  {
+    //JV Wrap parameter array in vectorial image, changed parameter order: A1x A1y A1z, A2x ....
+    PixelType * dataPointer =reinterpret_cast<PixelType *>( const_cast<double *>(m_InputParametersPointer->data_block() )) ;
+    unsigned int numberOfPixels = m_GridRegion.GetNumberOfPixels();
+    
+    m_WrappedImage->GetPixelContainer()->SetImportPointer( dataPointer,numberOfPixels);//InputDimension
+    m_CoefficientImage = m_WrappedImage;
+
+    //=====================================
+    //JV Create padded structure adding BC
+    //=====================================
+    PadCoefficientImage();
+        
+    //=====================================
+    //JV Wrap jacobian into OutputDimension X Vectorial images
+    //=====================================
+    this->m_Jacobian.set_size( OutputDimension, this->GetNumberOfParameters() );
+
+    // Use memset to set the memory
+    // JV four rows of three comps of parameters
+    JacobianPixelType * jacobianDataPointer = reinterpret_cast<JacobianPixelType *>(this->m_Jacobian.data_block());
+    memset(jacobianDataPointer, 0,  OutputDimension*numberOfPixels*sizeof(JacobianPixelType));
+
+    for (unsigned int j=0; j<OutputDimension; j++)
+      {
+       m_JacobianImage[j]->GetPixelContainer()->
+         SetImportPointer( jacobianDataPointer, numberOfPixels );
+       jacobianDataPointer += numberOfPixels;
+      }
+
+    // Reset the J parameters 
+    m_LastJacobianIndex = m_ValidRegion.GetIndex();
+    m_FirstRegion.SetSize(m_NullSize);
+    m_SecondRegion.SetSize(m_NullSize);
+    for ( unsigned int j = 0; j < SpaceDimension ; j++ )
+      {
+       m_FirstIterator[j]= IteratorType( m_JacobianImage[j], m_FirstRegion);
+       m_SecondIterator[j]= IteratorType( m_JacobianImage[j], m_SecondRegion);
+      }
+
+    m_BCValues.resize(0);
+    m_BCRegions.resize(0);
+    m_BCSize=0;
+    m_BC2Values.resize(0);
+    m_BC2Regions.resize(0);
+    m_BC2Size=0;
+    m_BC3Values.resize(0);
+    m_BC3Regions.resize(0);
+    m_BC3Size=0;
+
+  }
+
+
+  // Set the parameters by value
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetParametersByValue( const ParametersType & parameters )
+  {
+
+    // Check if the number of parameters match the
+    // Expected number of parameters
+    if ( parameters.Size() != this->GetNumberOfParameters() )
+      {
+       itkExceptionMacro(<<"Mismatched between parameters size "
+                         << parameters.size() 
+                         << " and region size "
+                         << m_GridRegion.GetNumberOfPixels() );
+      }
+
+    // Copy it
+    m_InternalParametersBuffer = parameters;
+    m_InputParametersPointer = &m_InternalParametersBuffer;
+
+    // Wrap flat array as images of coefficients
+    this->WrapAsImages();
+
+    //JV Set padded input to vector interpolator
+    m_VectorInterpolator->SetInputImage(this->GetPaddedCoefficientImage());
+
+    // Modified is always called since we just have a pointer to the
+    // Parameters and cannot know if the parameters have changed.
+    this->Modified();
+
+  }
+
+  // Get the parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  const 
+  typename ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::ParametersType &
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetParameters( void ) const
+  {
+    /** NOTE: For efficiency, this class does not keep a copy of the parameters - 
+     * it just keeps pointer to input parameters. 
+     */
+    if (NULL == m_InputParametersPointer)
+      {
+       itkExceptionMacro( <<"Cannot GetParameters() because m_InputParametersPointer is NULL. Perhaps SetCoefficientImage() has been called causing the NULL pointer." );
+      }
+
+    return (*m_InputParametersPointer);
+  }
+
+
+  // Get the parameters
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  const 
+  typename ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::ParametersType &
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetFixedParameters( void ) const
+  {
+    RegionType resRegion = this->GetGridRegion(  );
+  
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[i] = (resRegion.GetSize())[i];
+      }
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[NInputDimensions+i] = (this->GetGridOrigin())[i];
+      } 
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[2*NInputDimensions+i] =  (this->GetGridSpacing())[i];
+      }
+    for (unsigned int di=0; di<NInputDimensions; di++)
+      {
+       for (unsigned int dj=0; dj<NInputDimensions; dj++)
+         {
+           this->m_FixedParameters[3*NInputDimensions+(di*NInputDimensions+dj)] = (this->GetGridDirection())[di][dj];
+         }
+      }
+
+    //JV add splineOrders
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[(3+NInputDimensions)*NInputDimensions+i] = (this->GetSplineOrders())[i];
+      }
+    
+    //JV add LUTsamplingFactor
+    for (unsigned int i=0; i<NInputDimensions; i++)
+      {
+       this->m_FixedParameters[(4+NInputDimensions)*NInputDimensions+i] = (this->GetLUTSamplingFactors())[i];
+      }
+    
+    //JV add the mask
+    this->m_FixedParameters[(5+NInputDimensions)*NInputDimensions]=(double)((size_t) m_Mask);
+
+    //JV add the bulktransform pointer
+    this->m_FixedParameters[(5+NInputDimensions)*NInputDimensions+1]=(double)((size_t) m_BulkTransform);
+
+    //JV add the transform shape
+    this->m_FixedParameters[(5+NInputDimensions)*NInputDimensions+2]=(double)( m_TransformShape);
+    
+    return (this->m_FixedParameters);
+  }
+
+  
+  // Set the B-Spline coefficients using input images
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void 
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetCoefficientImage( CoefficientImagePointer image )
+  {
+    this->SetGridSpacing( image->GetSpacing() );
+    this->SetGridOrigin( image->GetOrigin() );
+    this->SetGridDirection( image->GetDirection() );
+    this->SetGridRegion( image->GetBufferedRegion() );
+    m_CoefficientImage = image;
+    
+    //JV
+    //   m_WrappedImage=m_CoefficientImage;
+
+    // Update the interpolator
+    this->PadCoefficientImage();
+    m_VectorInterpolator->SetInputImage(this->GetPaddedCoefficientImage());
+
+    // Clean up buffered parameters
+    m_InternalParametersBuffer = ParametersType( 0 );
+    m_InputParametersPointer  = NULL;
+      
+  }  
+
+
+  //   // Set the B-Spline coefficients using input images
+  //   template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  //   void 
+  //   ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  //   ::SetPaddedCoefficientImage( CoefficientImagePointer image )
+  //   {  
+  //     //JV modify the region
+  //     typename CoefficientImageType::RegionType region=image->GetBufferedRegion();
+  //     typename CoefficientImageType::RegionType::SizeType size=region.GetSize();
+  //     size[InputDimension-1]-=2;
+  //     region.SetSize(size);
+    
+  //     //Set properties
+  //     this->SetGridRegion( region );
+  //     this->SetGridSpacing( image->GetSpacing() );
+  //     this->SetGridDirection( image->GetDirection() );
+  //     this->SetGridOrigin( image->GetOrigin() );
+  //     m_PaddedCoefficientImage = image;
+  //     this->ExtractCoefficientImage();
+  //     m_VectorInterpolator->SetInputImage(this->GetPaddedCoefficientImage());
+    
+  //     // Clean up buffered parameters
+  //     m_InternalParametersBuffer = ParametersType( 0 );
+  //     m_InputParametersPointer  = NULL;
+      
+  //   } 
+
+  // Set the B-Spline coefficients using input images
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  typename   ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>::CoefficientImageType::Pointer
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::ExtractTemporalRow(const typename CoefficientImageType::Pointer& coefficientImage, unsigned int temporalIndex)
+  {
+    // Region
+    typename   CoefficientImageType::RegionType sourceRegion=coefficientImage->GetLargestPossibleRegion();
+    sourceRegion.SetSize(InputDimension-1, 1);
+    sourceRegion.SetIndex(InputDimension-1, temporalIndex);
+
+    // Extract
+    typedef clitk::ExtractImageFilter<CoefficientImageType, CoefficientImageType> ExtractImageFilterType;
+    typename ExtractImageFilterType::Pointer extract=ExtractImageFilterType::New();
+    extract->SetInput(coefficientImage);
+    extract->SetExtractionRegion(sourceRegion);
+    extract->Update();
+    typename CoefficientImageType::Pointer row= extract->GetOutput();
+
+    // Set index to zero
+    sourceRegion.SetIndex(InputDimension-1, 0);
+    row->SetRegions(sourceRegion);
+    return row;
+
+  }
+
+  // Set the B-Spline coefficients using input images
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void 
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::PadCoefficientImage(void)
+  {
+  
+    // Define paste, extract and combine filters 
+    typedef itk::PasteImageFilter<CoefficientImageType, CoefficientImageType, CoefficientImageType> PasteImageFilterType;
+    typedef clitk::ExtractImageFilter<CoefficientImageType, CoefficientImageType> ExtractImageFilterType;
+    typedef clitk::LinearCombinationImageFilter<CoefficientImageType, CoefficientImageType> LinearCombinationFilterType;
+    typedef itk::MultiplyByConstantImageFilter<CoefficientImageType, double, CoefficientImageType> MultiplicationFilterType;
+
+    // Regions
+    typename   CoefficientImageType::RegionType sourceRegion=m_PaddedCoefficientImage->GetLargestPossibleRegion();
+    typename   CoefficientImageType::RegionType destinationRegion=m_PaddedCoefficientImage->GetLargestPossibleRegion();
+    typename   CoefficientImageType::RegionType::SizeType sourceSize=sourceRegion.GetSize();
+    typename   CoefficientImageType::RegionType::SizeType destinationSize=destinationRegion.GetSize();    
+    typename   CoefficientImageType::IndexType sourceIndex=sourceRegion.GetIndex();
+    typename   CoefficientImageType::IndexType destinationIndex=destinationRegion.GetIndex();
+    // JV Padding depends on the shape 
+    switch (m_TransformShape)
+      {
+       /*  The shapes are
+           0: egg     4 CP  3 DOF
+           1: egg     5 CP  4 DOF 
+           2: rabbit  4 CP  3 DOF 
+           3: rabbit  5 CP  4 DOF
+           4: sputnik 4 CP  4 DOF
+           5: sputnik 5 CP  5 DOF
+           6: diamond 6 CP  5 DOF
+           7: diamond 7 CP  6 DOF
+       */
+       
+      case 0:
+       {
+         // ----------------------------------------------------------------------
+         // The egg with 4 internal CP (starting from inhale)
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and
+         // Coeff      row  BC1 BC2  0  BC3  1   2  BC4
+         // PaddedCoeff  R:  0   1   2   3   4   5   6 
+         // BC1= R4
+         // BC2= R5
+         // BC3= -weights[2]/weights[0] ( R2+R4 ) 
+         // BC4= R2
+         // ---------------------------------------------------------------------
+       
+         //---------------------------------
+         // 1. First two temporal rows are identical: paste 1-2 to 0-1
+         typename PasteImageFilterType::Pointer paster0=PasteImageFilterType::New();
+         paster0->SetDestinationImage(m_PaddedCoefficientImage);
+         paster0->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(NInputDimensions-1,1);
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         destinationIndex[InputDimension-1]=0;
+         paster0->SetDestinationIndex(destinationIndex);
+         paster0->SetSourceRegion(sourceRegion);
+         
+         //---------------------------------
+         // 1. Next temporal row = paste 0 to 2 
+         typename CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+         typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+         paster1->SetDestinationImage(paster0->GetOutput());
+         paster1->SetSourceImage(row0);
+         destinationIndex[InputDimension-1]=2;
+         paster1->SetDestinationIndex(destinationIndex);
+         paster1->SetSourceRegion(row0->GetLargestPossibleRegion());
+         
+         //---------------------------------
+         // 2. Middle row at index 3=BC
+         // Extract row at index 1, 2 (of coeff image)
+         typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+         combine1->SetInput(0,row0);
+         combine1->SetInput(1,row1);
+         combine1->SetA(-m_WeightRatio[2][0]);
+         combine1->SetB(-m_WeightRatio[2][0]);
+         combine1->Update();
+         typename CoefficientImageType::Pointer bc3Row=combine1->GetOutput();
+
+         // Paste middleRow at index 3 (padded coeff)
+         typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+         paster2->SetDestinationImage(paster1->GetOutput());
+         paster2->SetSourceImage(bc3Row);
+         destinationIndex[InputDimension-1]=3;
+         paster2->SetDestinationIndex(destinationIndex);
+         paster2->SetSourceRegion(bc3Row->GetLargestPossibleRegion());
+       
+         //---------------------------------
+         // 3. Next two temporal rows identical: paste 1,2 to 4,5
+         typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+         paster3->SetDestinationImage(paster2->GetOutput());
+         paster3->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(InputDimension-1,1);
+         sourceRegion.SetSize(InputDimension-1,2);
+         destinationIndex[InputDimension-1]=4;
+         paster3->SetDestinationIndex(destinationIndex);
+         paster3->SetSourceRegion(sourceRegion);
+       
+         // ---------------------------------
+         // 4. Row at index 6=BC4= R2
+         // Paste BC3 row at index 5
+         typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+         paster4->SetDestinationImage(paster3->GetOutput());
+         paster4->SetSourceImage(row0);
+         destinationIndex[InputDimension-1]=6;
+         paster4->SetDestinationIndex(destinationIndex);
+         paster4->SetSourceRegion(row0->GetLargestPossibleRegion());
+       
+         // Update the chain!
+         paster4->Update();
+         m_PaddedCoefficientImage= paster4->GetOutput();
+
+         break;
+       }
+       
+      case 1:
+       {
+         // ----------------------------------------------------------------------
+         // The egg with 5 internal CP (starting from inhale)
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and
+         // Coeff      row  BC1 BC2  0  BC3  1   2   3  BC4
+         // PaddedCoeff  R:  0   1   2   3   4   5   6   7
+         // BC1= R5
+         // BC2= R6
+         // BC3= -weights[3]/weights[1] ( R2+R5 ) - R4 
+         // BC4= R2
+         // ---------------------------------------------------------------------
+         //---------------------------------
+         // 1. First two temporal rows are identical: paste 2-3 to 0-1
+         typename PasteImageFilterType::Pointer paster0=PasteImageFilterType::New();
+         paster0->SetDestinationImage(m_PaddedCoefficientImage);
+         paster0->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(NInputDimensions-1,2);
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         destinationIndex[InputDimension-1]=0;
+         paster0->SetDestinationIndex(destinationIndex);
+         paster0->SetSourceRegion(sourceRegion);
+         
+         //---------------------------------
+         // 1. Next temporal row = paste 0 to 2 
+         typename CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+         typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+         paster1->SetDestinationImage(paster0->GetOutput());
+         paster1->SetSourceImage(row0);
+         destinationIndex[InputDimension-1]=2;
+         paster1->SetDestinationIndex(destinationIndex);
+         paster1->SetSourceRegion(row0->GetLargestPossibleRegion());
+         
+         //---------------------------------
+         // 2. Middle row at index 3=BC
+         // Extract row at index 1, 2 (of coeff image)
+         typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         typename CoefficientImageType::Pointer row2=this->ExtractTemporalRow(m_CoefficientImage, 2);
+         
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+         combine1->SetInput(0,row0);
+         combine1->SetInput(1,row2);
+         combine1->SetA(1);
+         combine1->SetB(1);
+         // combine1->Update();
+         typename LinearCombinationFilterType::Pointer combine2=LinearCombinationFilterType::New();
+         combine2->SetInput(0,row1);
+         combine2->SetInput(1,combine1->GetOutput());
+         combine2->SetA(-1.);
+         combine2->SetB(-m_WeightRatio[3][1]);
+         combine2->Update();
+         typename CoefficientImageType::Pointer bc3Row=combine2->GetOutput();
+
+         // Paste middleRow at index 3 (padded coeff)
+         typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+         paster2->SetDestinationImage(paster1->GetOutput());
+         paster2->SetSourceImage(bc3Row);
+         destinationIndex[InputDimension-1]=3;
+         paster2->SetDestinationIndex(destinationIndex);
+         paster2->SetSourceRegion(bc3Row->GetLargestPossibleRegion());
+       
+         //---------------------------------
+         // 3. Next three temporal rows identical: paste 1,2,3 to 4,5,6
+         typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+         paster3->SetDestinationImage(paster2->GetOutput());
+         paster3->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(InputDimension-1,1);
+         sourceRegion.SetSize(InputDimension-1,3);
+         destinationIndex[InputDimension-1]=4;
+         paster3->SetDestinationIndex(destinationIndex);
+         paster3->SetSourceRegion(sourceRegion);
+       
+         // ---------------------------------
+         // 4. Row at index 7=BC4= R2
+         // Paste BC3 row at index 5
+         typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+         paster4->SetDestinationImage(paster3->GetOutput());
+         paster4->SetSourceImage(row0);
+         destinationIndex[InputDimension-1]=7;
+         paster4->SetDestinationIndex(destinationIndex);
+         paster4->SetSourceRegion(row0->GetLargestPossibleRegion());
+       
+         // Update the chain!
+         paster4->Update();
+         m_PaddedCoefficientImage= paster4->GetOutput();
+
+         break;
+       }
+
+
+//       // ----------------------------------------------------------------------
+//       // The egg with 5 internal CP: 
+//       // Periodic, C2 smooth everywhere and constrained to zero at the reference
+//       // Coeff       row R5 BC1  0   1   2   3  BC2  R2  
+//       // PaddedCoeff R:  0   1   2   3   4   5   6   7    
+//       // BC1= -weights[2]/weights[0] ( R2+R5)
+//       // BC2= BC1  
+//       // ---------------------------------------------------------------------
+
+//       // Extract rows with index 0 and 3
+//       typename    CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+//       typename    CoefficientImageType::Pointer row3=this->ExtractTemporalRow(m_CoefficientImage, 3);
+         
+//       // Paste the first row
+//       typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+//       destinationIndex.Fill(0);
+//       paster1->SetDestinationIndex(destinationIndex);
+//       paster1->SetSourceRegion(row3->GetLargestPossibleRegion());
+//       paster1->SetSourceImage(row3);
+//       paster1->SetDestinationImage(m_PaddedCoefficientImage);
+
+//       // Linearly Combine rows for BC1 and BC2
+//       typedef clitk::LinearCombinationImageFilter<CoefficientImageType, CoefficientImageType> LinearCombinationFilterType;
+//       typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+//       combine1->SetFirstInput(row0);
+//       combine1->SetSecondInput(row3);
+//       combine1->SetA(-m_WeightRatio[2][0]);
+//       combine1->SetB(-m_WeightRatio[2][0]);
+//       combine1->Update();
+//       typename CoefficientImageType::Pointer bcRow=combine1->GetOutput();
+
+//       // Paste the second row
+//       typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+//       destinationIndex[InputDimension-1]=1;
+//       paster2->SetDestinationIndex(destinationIndex);
+//       paster2->SetSourceRegion(bcRow->GetLargestPossibleRegion());
+//       paster2->SetSourceImage(bcRow);
+//       paster2->SetDestinationImage(paster1->GetOutput());
+
+//       // Paste the coefficientImage
+//       typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+//       destinationIndex[InputDimension-1]=2;
+//       paster3->SetDestinationIndex(destinationIndex);
+//       paster3->SetSourceRegion(m_CoefficientImage->GetLargestPossibleRegion());
+//       paster3->SetSourceImage(m_CoefficientImage);
+//       paster3->SetDestinationImage(paster2->GetOutput());
+
+//       // Paste the last two rows
+//       typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+//       destinationIndex[InputDimension-1]=6;
+//       paster4->SetDestinationIndex(destinationIndex);
+//       paster4->SetSourceRegion(bcRow->GetLargestPossibleRegion());
+//       paster4->SetSourceImage(bcRow);
+//       paster4->SetDestinationImage(paster3->GetOutput());
+
+//       typename PasteImageFilterType::Pointer paster5=PasteImageFilterType::New();
+//       destinationIndex[InputDimension-1]=7;
+//       paster5->SetDestinationIndex(destinationIndex);
+//       paster5->SetSourceRegion(row0->GetLargestPossibleRegion());
+//       paster5->SetSourceImage(row0);
+//       paster5->SetDestinationImage(paster4->GetOutput());
+         
+//       // Update the chain!
+//       paster5->Update();
+//       m_PaddedCoefficientImage= paster5->GetOutput();
+         
+//       break;
+//     }
+
+      case 2:
+       {
+         // ----------------------------------------------------------------------
+         // The rabbit with 4 internal CP
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and the extremes fixed with anit-symm bc
+         // Coeff      row  BC1  0   1  BC2  2  BC3 BC4 
+         // PaddedCoeff  R:  0   1   2   3   4   5   6 
+         // BC1= 2*R1-R2
+         // BC2= -weights[2]/weights[0] ( R2+R4 )
+         // BC3=  R1
+         // BC4= 2*R1-R4
+         // ---------------------------------------------------------------------
+
+         // ---------------------------------
+         // 0. First Row =BC1
+         typename CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+         typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         typename LinearCombinationFilterType::Pointer combine0=LinearCombinationFilterType::New();
+         combine0->SetInput(0,row0);
+         combine0->SetInput(1,row1);
+         combine0->SetA(2.);
+         combine0->SetB(-1.);
+         combine0->Update();
+         typename CoefficientImageType::Pointer bc1Row=combine0->GetOutput();
+
+         typename PasteImageFilterType::Pointer paster0=PasteImageFilterType::New();
+         paster0->SetDestinationImage(m_PaddedCoefficientImage);
+         paster0->SetSourceImage(bc1Row);
+         destinationIndex[InputDimension-1]=0;
+         paster0->SetDestinationIndex(destinationIndex);
+         paster0->SetSourceRegion(bc1Row->GetLargestPossibleRegion());
+
+         //---------------------------------
+         // 1. Next two temporal rows are identical: paste 0-1 to 1-2
+         typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+         paster1->SetDestinationImage(paster0->GetOutput());
+         paster1->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(NInputDimensions-1,0);
+         destinationIndex[InputDimension-1]=1;
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         paster1->SetDestinationIndex(destinationIndex);
+         paster1->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 2. Middle row at index 3=BC
+         // Extract row at index 1, 2 (of coeff image)
+         typename CoefficientImageType::Pointer row2=this->ExtractTemporalRow(m_CoefficientImage, 2);
+  
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+         combine1->SetInput(0,row1);
+         combine1->SetInput(1,row2);
+         combine1->SetA(-m_WeightRatio[2][0]);
+         combine1->SetB(-m_WeightRatio[2][0]);
+         combine1->Update();
+         typename CoefficientImageType::Pointer bc2Row=combine1->GetOutput();
+
+         // Paste middleRow at index 3 (padded coeff)
+         typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+         paster2->SetDestinationImage(paster1->GetOutput());
+         paster2->SetSourceImage(bc2Row);
+         destinationIndex[InputDimension-1]=3;
+         paster2->SetDestinationIndex(destinationIndex);
+         paster2->SetSourceRegion(bc2Row->GetLargestPossibleRegion());
+         
+         //---------------------------------
+         // 3. Next temporal row is identical: paste 2 to 4
+         typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+         paster3->SetDestinationImage(paster2->GetOutput());
+         paster3->SetSourceImage(row2);
+         destinationIndex[InputDimension-1]=4;
+         paster3->SetDestinationIndex(destinationIndex);
+         paster3->SetSourceRegion(row2->GetLargestPossibleRegion());
+
+         // ---------------------------------
+         // 4. Row at index 5=BC (paddedcoeff image) R1
+         // Paste BC3 row at index 5
+         typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+         paster4->SetDestinationImage(paster3->GetOutput());
+         paster4->SetSourceImage(row0);
+         destinationIndex[InputDimension-1]=5;
+         paster4->SetDestinationIndex(destinationIndex);
+         paster4->SetSourceRegion(row0->GetLargestPossibleRegion());
+    
+         // ---------------------------------
+         // 5. Paste BC4 row at index 6
+         typename LinearCombinationFilterType::Pointer combine3=LinearCombinationFilterType::New();
+         combine3->SetInput(0,row0);
+         combine3->SetInput(1,row2);
+         combine3->SetA(2.);
+         combine3->SetB(-1.);
+         combine3->Update();
+         typename CoefficientImageType::Pointer bc4Row=combine3->GetOutput();
+         typename PasteImageFilterType::Pointer paster5=PasteImageFilterType::New();
+         paster5->SetDestinationImage(paster4->GetOutput());
+         paster5->SetSourceImage(bc4Row);
+         destinationIndex[InputDimension-1]=6;
+         paster5->SetDestinationIndex(destinationIndex);
+         paster5->SetSourceRegion(bc4Row->GetLargestPossibleRegion());
+         
+         // Update the chain!
+         paster5->Update();
+         m_PaddedCoefficientImage= paster5->GetOutput();
+
+         break;
+       }
+     
+      case 3: 
+       {
+         // ----------------------------------------------------------------------
+         // The rabbit with 5 internal CP
+         // Periodic, constrained to zero at the reference at position 3.5 
+         // and the extremes fixed with anti-symmetrical BC
+         // Coeff      row  BC1  0   1  BC2  2   3  BC3 BC4
+         // PaddedCoeff  R:  0   1   2   3   4   5   6   7    
+         // BC1= 2*R1-R2
+         // BC2= -weights[3]/weights[1] ( R2+R5 ) - R4
+         // BC3= R1
+         // BC4= 2*R1-R5
+         // ---------------------------------------------------------------------
+
+         // ---------------------------------
+         // 0. First Row =BC1
+         typename CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+         typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         typename LinearCombinationFilterType::Pointer combine0=LinearCombinationFilterType::New();
+         combine0->SetInput(0,row0);
+         combine0->SetInput(1,row1);
+         combine0->SetA(2.);
+         combine0->SetB(-1.);
+         combine0->Update();
+         typename CoefficientImageType::Pointer bc1Row=combine0->GetOutput();
+
+         typename PasteImageFilterType::Pointer paster0=PasteImageFilterType::New();
+         paster0->SetDestinationImage(m_PaddedCoefficientImage);
+         paster0->SetSourceImage(bc1Row);
+         destinationIndex[InputDimension-1]=0;
+         paster0->SetDestinationIndex(destinationIndex);
+         paster0->SetSourceRegion(bc1Row->GetLargestPossibleRegion());
+
+         //---------------------------------
+         // 1. Next two temporal rows are identical: paste 0-1 to 1-2
+         typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+         paster1->SetDestinationImage(paster0->GetOutput());
+         paster1->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(InputDimension-1,0);
+         destinationIndex[InputDimension-1]=1;
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         paster1->SetDestinationIndex(destinationIndex);
+         paster1->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 2. Middle row at index 3=BC
+         // Extract row at index 1, 3 (of coeff image)
+         //typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         typename CoefficientImageType::Pointer row3=this->ExtractTemporalRow(m_CoefficientImage, 3);
+  
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+         combine1->SetInput(0,row1);
+         combine1->SetInput(1,row3);
+         combine1->SetA(1.);
+         combine1->SetB(1.);
+         combine1->Update();
+         
+         // Extract row at index 2 (coeff image)
+         typename CoefficientImageType::Pointer row2=this->ExtractTemporalRow(m_CoefficientImage, 2);
+
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine2=LinearCombinationFilterType::New();
+         combine2->SetInput(0,combine1->GetOutput());
+         combine2->SetInput(1,row2);
+         combine2->SetA(-m_WeightRatio[3][1]);
+         combine2->SetB(-1.);
+         combine2->Update();
+         typename CoefficientImageType::Pointer bc2Row=combine2->GetOutput();
+
+         // Paste middleRow at index 3 (padded coeff)
+         typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+         paster2->SetDestinationImage(paster1->GetOutput());
+         paster2->SetSourceImage(bc2Row);
+         destinationIndex[InputDimension-1]=3;
+         paster2->SetDestinationIndex(destinationIndex);
+         paster2->SetSourceRegion(bc2Row->GetLargestPossibleRegion());
+         
+         //---------------------------------
+         // 3. Next two temporal rows are identical: paste 2,3 to 4,5
+         typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+         paster3->SetDestinationImage(paster2->GetOutput());
+         paster3->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(InputDimension-1,2);
+         destinationIndex[InputDimension-1]=4;
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         paster3->SetDestinationIndex(destinationIndex);
+         paster3->SetSourceRegion(sourceRegion);
+
+         // ---------------------------------
+         // 4. Row at index 6=BC (paddedcoeff image)R1
+         // Paste BC3 row at index 6
+         typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+         paster4->SetDestinationImage(paster3->GetOutput());
+         paster4->SetSourceImage(row0);
+         destinationIndex[InputDimension-1]=6;
+         paster4->SetDestinationIndex(destinationIndex);
+         paster4->SetSourceRegion(row0->GetLargestPossibleRegion());
+
+         // ---------------------------------
+         // 5. Paste BC4 row at index 7
+         typename LinearCombinationFilterType::Pointer combine3=LinearCombinationFilterType::New();
+         combine3->SetInput(0,row0);
+         combine3->SetInput(1,row3);
+         combine3->SetA(2.);
+         combine3->SetB(-1.);
+         combine3->Update();
+         typename CoefficientImageType::Pointer bc4Row=combine3->GetOutput();
+         typename PasteImageFilterType::Pointer paster5=PasteImageFilterType::New();
+         paster5->SetDestinationImage(paster4->GetOutput());
+         paster5->SetSourceImage(bc4Row);
+         destinationIndex[InputDimension-1]=7;
+         paster5->SetDestinationIndex(destinationIndex);
+         paster5->SetSourceRegion(bc4Row->GetLargestPossibleRegion());
+         
+         // Update the chain!
+         paster5->Update();
+         m_PaddedCoefficientImage= paster5->GetOutput();
+
+         break;
+       }
+       
+      case 4: 
+       {
+         // ----------------------------------------------------------------------
+         // The sputnik with 4 internal CP
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and one indepent extremes copied
+         // Coeff     row BC1  0   1  BC2  2  BC2  3
+         // PaddedCoeff R: 0   1   2   3   4   5   6      
+         // BC1= R6
+         // BC2= -weights[2]/weights[0] ( R2+R4 )
+         // BC3=  weights[2]/weights[0] ( R2-R4) + R1
+         // ---------------------------------------------------------------------
+
+         //---------------------------------
+         // 1. First Row is equal to last row: paste 3 row to 0
+         typename CoefficientImageType::Pointer row3=this->ExtractTemporalRow(m_CoefficientImage, 3);
+         typename PasteImageFilterType::Pointer paster0=PasteImageFilterType::New();
+         paster0->SetDestinationImage(m_PaddedCoefficientImage);
+         paster0->SetSourceImage(row3);
+         destinationIndex[InputDimension-1]=0;
+         paster0->SetDestinationIndex(destinationIndex);
+         paster0->SetSourceRegion(row3->GetLargestPossibleRegion());
+
+         //---------------------------------
+         // 1. Next two temporal rows are identical: paste 0-1 to 1-2
+         typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+         paster1->SetDestinationImage(paster0->GetOutput());
+         paster1->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(NInputDimensions-1,0);
+         destinationIndex[InputDimension-1]=1;
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         paster1->SetDestinationIndex(destinationIndex);
+         paster1->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 2. Middle row at index 3=BC
+         // Extract row at index 1, 2 (of coeff image)
+         typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         typename CoefficientImageType::Pointer row2=this->ExtractTemporalRow(m_CoefficientImage, 2);
+  
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+         combine1->SetInput(0,row1);
+         combine1->SetInput(1,row2);
+         combine1->SetA(-m_WeightRatio[2][0]);
+         combine1->SetB(-m_WeightRatio[2][0]);
+         combine1->Update();
+         typename CoefficientImageType::Pointer bc1Row=combine1->GetOutput();
+
+         // Paste middleRow at index 3 (padded coeff)
+         typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+         paster2->SetDestinationImage(paster1->GetOutput());
+         paster2->SetSourceImage(bc1Row);
+         destinationIndex[InputDimension-1]=3;
+         paster2->SetDestinationIndex(destinationIndex);
+         paster2->SetSourceRegion(bc1Row->GetLargestPossibleRegion());
+         
+         //---------------------------------
+         // 3. Next temporal row is identical: paste 2 to 4
+         typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+         paster3->SetDestinationImage(paster2->GetOutput());
+         paster3->SetSourceImage(row2);
+         destinationIndex[InputDimension-1]=4;
+         paster3->SetDestinationIndex(destinationIndex);
+         paster3->SetSourceRegion(row2->GetLargestPossibleRegion());
+
+         //---------------------------------
+         // 4. Final row at index 5=BC3 (paddedcoeff image)R1 R2 R4 corresponds to index in coeff image 0 1 2
+         // Extract row at index 1, 2 (of coeff image)already done
+         typename CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+    
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine3=LinearCombinationFilterType::New();
+         combine3->SetInput(0,row1);
+         combine3->SetInput(1,row2);
+         combine3->SetA(1.);
+         combine3->SetB(-1.);
+
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine4=LinearCombinationFilterType::New();
+         combine4->SetInput(0,combine3->GetOutput());
+         combine4->SetInput(1,row0);
+         combine4->SetA(m_WeightRatio[2][0]);
+         combine4->SetB(1.);
+         combine4->Update();
+         typename CoefficientImageType::Pointer bc2Row=combine4->GetOutput();
+
+         // Paste BC row at index 5
+         typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+         paster4->SetDestinationImage(paster3->GetOutput());
+         paster4->SetSourceImage(bc2Row);
+         destinationIndex[InputDimension-1]=5;
+         paster4->SetDestinationIndex(destinationIndex);
+         paster4->SetSourceRegion(bc2Row->GetLargestPossibleRegion());
+    
+         // Paste row 3  at index 6
+         typename PasteImageFilterType::Pointer paster5=PasteImageFilterType::New();
+         paster5->SetDestinationImage(paster4->GetOutput());
+         paster5->SetSourceImage(row3);
+         destinationIndex[InputDimension-1]=6;
+         paster5->SetDestinationIndex(destinationIndex);
+         paster5->SetSourceRegion(row3->GetLargestPossibleRegion());
+         
+         // Update the chain!
+         paster5->Update();
+         m_PaddedCoefficientImage= paster5->GetOutput();
+
+         break;
+       }
+
+      case 5: 
+       {
+
+         // ----------------------------------------------------------------------
+         // The sputnik with 5 internal CP
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and one indepent extreme
+         // Coeff     row BC1  0   1  BC2  2   3  BC3  4
+         // PaddedCoeff R: 0   1   2   3   4   5   6   7   
+         // BC1= R2 + R5 - R7
+         // BC2= -weights[3]/weights[1] ( R2+R5 ) - R4
+         // BC3= R1 + 0.5 R2 - 0.5 R7
+         // ----------------------------------------------------------------------
+         //---------------------------------
+         // 1. First Row =BC 
+         typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         typename CoefficientImageType::Pointer row3=this->ExtractTemporalRow(m_CoefficientImage, 3);
+         typename CoefficientImageType::Pointer row4=this->ExtractTemporalRow(m_CoefficientImage, 4);
+
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine0=LinearCombinationFilterType::New();
+         combine0->SetInput(0,row1);
+         combine0->SetInput(1,row3);
+         combine0->SetA(1.);
+         combine0->SetB(1.);
+         //combine0->Update();
+         typename LinearCombinationFilterType::Pointer combine0bis=LinearCombinationFilterType::New();
+         combine0bis->SetInput(0,combine0->GetOutput());
+         combine0bis->SetInput(1,row4);
+         combine0bis->SetA(1.);
+         combine0bis->SetB(-1.);
+         combine0bis->Update();
+         typename CoefficientImageType::Pointer bc1Row=combine0bis->GetOutput();
+
+         typename PasteImageFilterType::Pointer paster0=PasteImageFilterType::New();
+         paster0->SetDestinationImage(m_PaddedCoefficientImage);
+         paster0->SetSourceImage(bc1Row);
+         destinationIndex[InputDimension-1]=0;
+         paster0->SetDestinationIndex(destinationIndex);
+         paster0->SetSourceRegion(bc1Row->GetLargestPossibleRegion());
+
+         //---------------------------------
+         // 1. Next two temporal rows are identical: paste 0-1 to 1-2
+         typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+         paster1->SetDestinationImage(paster0->GetOutput());
+         paster1->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(NInputDimensions-1,0);
+         destinationIndex[InputDimension-1]=1;
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         paster1->SetDestinationIndex(destinationIndex);
+         paster1->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 2. Middle row at index 3=BC
+         // Extract row at index 1, 2 (of coeff image)
+         //typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         typename CoefficientImageType::Pointer row2=this->ExtractTemporalRow(m_CoefficientImage, 2);
+  
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+         combine1->SetInput(0,row1);
+         combine1->SetInput(1,row3);
+         combine1->SetA(1.);
+         combine1->SetB(1.);
+         combine1->Update();
+
+         typename LinearCombinationFilterType::Pointer combine2=LinearCombinationFilterType::New();
+         combine2->SetInput(0,combine1->GetOutput());
+         combine2->SetInput(1,row2);
+         combine2->SetA(-m_WeightRatio[3][1]);
+         combine2->SetB(-1.);
+         combine2->Update();
+         typename CoefficientImageType::Pointer bc2Row=combine2->GetOutput();
+
+         // Paste middleRow at index 3 (padded coeff)
+         typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+         paster2->SetDestinationImage(paster1->GetOutput());
+         paster2->SetSourceImage(bc2Row);
+         destinationIndex[InputDimension-1]=3;
+         paster2->SetDestinationIndex(destinationIndex);
+         paster2->SetSourceRegion(bc2Row->GetLargestPossibleRegion());
+         
+         //---------------------------------
+         // 3. Next two temporal rows are identical: paste 2,3 to 4,5
+         typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+         paster3->SetDestinationImage(paster2->GetOutput());
+         paster3->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(InputDimension-1,2);
+         destinationIndex[InputDimension-1]=4;
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         paster3->SetDestinationIndex(destinationIndex);
+         paster3->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 4. Final row at index 6=BC3
+         typename CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+    
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine3=LinearCombinationFilterType::New();
+         combine3->SetInput(0,row1);
+         combine3->SetInput(1,row4);
+         combine3->SetA(1.);
+         combine3->SetB(-1.);
+         typename LinearCombinationFilterType::Pointer combine4=LinearCombinationFilterType::New();
+         combine4->SetInput(0,row0);
+         combine4->SetInput(1,combine3->GetOutput());
+         combine4->SetA(1.);
+         combine4->SetB(.5);
+         combine4->Update();
+         typename CoefficientImageType::Pointer bc3Row=combine4->GetOutput();
+
+         // Paste BC row at index 6
+         typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+         paster4->SetDestinationImage(paster3->GetOutput());
+         paster4->SetSourceImage(bc3Row);
+         destinationIndex[InputDimension-1]=6;
+         paster4->SetDestinationIndex(destinationIndex);
+         paster4->SetSourceRegion(bc3Row->GetLargestPossibleRegion());
+    
+         // Paste row 4  at index 7
+         typename PasteImageFilterType::Pointer paster5=PasteImageFilterType::New();
+         paster5->SetDestinationImage(paster4->GetOutput());
+         paster5->SetSourceImage(row4);
+         destinationIndex[InputDimension-1]=7;
+         paster5->SetDestinationIndex(destinationIndex);
+         paster5->SetSourceRegion(row4->GetLargestPossibleRegion());
+         
+         // Update the chain!
+         paster5->Update();
+         m_PaddedCoefficientImage= paster5->GetOutput();
+
+         break;
+       }
+
+      case 6: 
+       {
+         // ----------------------------------------------------------------------
+         // The diamond with 4 internal CP:
+         // Periodic, constrained to zero at the reference at position 3
+         // Coeff      row 0   1   2  BC1  3  BC2  4
+         // PaddedCoeff  R:0   1   2   3   4   5   6    
+         // BC1= -weights[2]/weights[0] ( R2+R4 )
+         // BC2= weights[2]/weights[0]  ( R0+R2-R4-R6 ) + R1
+         // ---------------------------------------------------------------------
+
+         //---------------------------------
+         // 1. First Three temporal rows are identical: paste 0-2 to 0-2
+         typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+         paster1->SetDestinationImage(m_PaddedCoefficientImage);
+         paster1->SetSourceImage(m_CoefficientImage);
+         sourceIndex.Fill(0);
+         destinationIndex.Fill(0);
+         sourceSize[NInputDimensions-1]=3;
+         sourceRegion.SetSize(sourceSize);
+         sourceRegion.SetIndex(sourceIndex);
+         paster1->SetDestinationIndex(destinationIndex);
+         paster1->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 2. Middle row at index 3=BC
+         // Extract row at index 0, 4 (of coeff image)
+         typename CoefficientImageType::Pointer row2=this->ExtractTemporalRow(m_CoefficientImage, 2);
+         typename CoefficientImageType::Pointer row3=this->ExtractTemporalRow(m_CoefficientImage, 3);
+  
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+         combine1->SetInput(0,row2);
+         combine1->SetInput(1,row3);
+         combine1->SetA(-m_WeightRatio[2][0]);
+         combine1->SetB(-m_WeightRatio[2][0]);
+         combine1->Update();
+         typename CoefficientImageType::Pointer bc1Row=combine1->GetOutput();
+
+         // Paste middleRow at index 3 (padded coeff)
+         typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+         paster2->SetDestinationImage(paster1->GetOutput());
+         paster2->SetSourceImage(bc1Row);
+         destinationIndex[InputDimension-1]=3;
+         paster2->SetDestinationIndex(destinationIndex);
+         paster2->SetSourceRegion(bc1Row->GetLargestPossibleRegion());
+         
+         //---------------------------------
+         // 3. Next  row identical: paste 3 to 4
+         typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+         paster3->SetDestinationImage(paster2->GetOutput());
+         paster3->SetSourceImage(row3);
+         destinationIndex[InputDimension-1]=4;
+         paster3->SetDestinationIndex(destinationIndex);
+         paster3->SetSourceRegion(row3->GetLargestPossibleRegion());
+
+         //---------------------------------
+         // 4. Final row at index 6=BC (paddedcoeff image)R0 R2 R5 R7 R1 corresponds to index in coeff image 0 2 4 5 1
+         // Extract row at index 0, 2 (of coeff image)already done
+         typename CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+         typename CoefficientImageType::Pointer row4=this->ExtractTemporalRow(m_CoefficientImage, 4);
+         typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+    
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine3=LinearCombinationFilterType::New();
+         combine3->SetInput(0,row0);
+         combine3->SetInput(1,row2);
+         combine3->SetA(1.);
+         combine3->SetB(1.);
+
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine4=LinearCombinationFilterType::New();
+         combine4->SetInput(0,row3);
+         combine4->SetInput(1,row4);
+         combine4->SetA(1.);
+         combine4->SetB(1.);
+         
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine5=LinearCombinationFilterType::New();
+         combine5->SetInput(0,combine3->GetOutput());
+         combine5->SetInput(1,combine4->GetOutput());
+         combine5->SetA(1.);
+         combine5->SetB(-1.);
+
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine6=LinearCombinationFilterType::New();
+         combine6->SetInput(0,combine5->GetOutput());
+         combine6->SetInput(1,row1);
+         combine6->SetA(m_WeightRatio[2][0]);
+         combine6->SetB(1.);
+         combine6->Update();
+         typename CoefficientImageType::Pointer bc2Row=combine6->GetOutput();
+
+         // Paste BC row at index 5
+         typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+         paster4->SetDestinationImage(paster3->GetOutput());
+         paster4->SetSourceImage(bc2Row);
+         destinationIndex[InputDimension-1]=5;
+         paster4->SetDestinationIndex(destinationIndex);
+         paster4->SetSourceRegion(bc2Row->GetLargestPossibleRegion());
+    
+         // Paste last row at index 6
+         typename PasteImageFilterType::Pointer paster5=PasteImageFilterType::New();
+         paster5->SetDestinationImage(paster4->GetOutput());
+         paster5->SetSourceImage(row4);
+         destinationIndex[InputDimension-1]=6;
+         paster5->SetDestinationIndex(destinationIndex);
+         paster5->SetSourceRegion(row4->GetLargestPossibleRegion());
+         
+         // Update the chain!
+         paster5->Update();
+         m_PaddedCoefficientImage= paster5->GetOutput();
+
+         break;
+       }
+      case 7: 
+       {
+         // ----------------------------------------------------------------------
+         // The diamond with 5 internal CP: 
+         // periodic, constrained to zero at the reference at position 3.5
+         // Coeff      row 0   1   2  BC1  3   4  BC2  5
+         // PaddedCoeff  R:0   1   2   3   4   5   6   7    
+         // BC1= -weights[3]/weights[1] ( R2+R5 ) - R4
+         // BC2= weights[2]/weights[0] ( R0+R2-R5-R7 ) + R1
+         // ---------------------------------------------------------------------
+
+         //---------------------------------
+         // 1. First Three temporal rows are identical: paste 0-2 to 0-2
+         typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+         paster1->SetDestinationImage(m_PaddedCoefficientImage);
+         paster1->SetSourceImage(m_CoefficientImage);
+         sourceIndex.Fill(0);
+         destinationIndex.Fill(0);
+         sourceSize[NInputDimensions-1]=3;
+         sourceRegion.SetSize(sourceSize);
+         sourceRegion.SetIndex(sourceIndex);
+         paster1->SetDestinationIndex(destinationIndex);
+         paster1->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 2. Middle row at index 3=BC
+         // Extract row at index 0, 4 (of coeff image)
+         typename CoefficientImageType::Pointer row2=this->ExtractTemporalRow(m_CoefficientImage, 2);
+         typename CoefficientImageType::Pointer row4=this->ExtractTemporalRow(m_CoefficientImage, 4);
+  
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+         combine1->SetInput(0,row2);
+         combine1->SetInput(1,row4);
+         combine1->SetA(1.);
+         combine1->SetB(1.);
+         combine1->Update();
+         
+         // Extract row at index 3 (coeff image)
+         typename CoefficientImageType::Pointer row3=this->ExtractTemporalRow(m_CoefficientImage, 3);
+
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine2=LinearCombinationFilterType::New();
+         combine2->SetInput(0,combine1->GetOutput());
+         combine2->SetInput(1,row3);
+         combine2->SetA(-m_WeightRatio[3][1] );
+         combine2->SetB(-1.);
+         combine2->Update();
+         typename CoefficientImageType::Pointer bc1Row=combine2->GetOutput();
+
+         // Paste middleRow at index 3 (padded coeff)
+         typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+         paster2->SetDestinationImage(paster1->GetOutput());
+         paster2->SetSourceImage(bc1Row);
+         destinationIndex[InputDimension-1]=3;
+         paster2->SetDestinationIndex(destinationIndex);
+         paster2->SetSourceRegion(bc1Row->GetLargestPossibleRegion());
+         
+         //---------------------------------
+         // 3. Next two temporal rows are identical: paste 3,4 to 4,5
+         typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+         paster3->SetDestinationImage(paster2->GetOutput());
+         paster3->SetSourceImage(m_CoefficientImage);
+         sourceIndex[InputDimension-1]=3;
+         destinationIndex[InputDimension-1]=4;
+         sourceSize[NInputDimensions-1]=2;
+         sourceRegion.SetSize(sourceSize);
+         sourceRegion.SetIndex(sourceIndex);
+         paster3->SetDestinationIndex(destinationIndex);
+         paster3->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 4. Final row at index 6=BC (paddedcoeff image)R0 R2 R5 R7 R1 corresponds to index in coeff image 0 2 4 5 1
+         // Extract row at index 0, 2 (of coeff image)already done
+         typename CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+         typename CoefficientImageType::Pointer row5=this->ExtractTemporalRow(m_CoefficientImage, 5);
+         typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+    
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine3=LinearCombinationFilterType::New();
+         combine3->SetInput(0,row0);
+         combine3->SetInput(1,row2);
+         combine3->SetA(1.);
+         combine3->SetB(1.);
+
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine4=LinearCombinationFilterType::New();
+         combine4->SetInput(0,row4);
+         combine4->SetInput(1,row5);
+         combine4->SetA(1.);
+         combine4->SetB(1.);
+         
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine5=LinearCombinationFilterType::New();
+         combine5->SetInput(0,combine3->GetOutput());
+         combine5->SetInput(1,combine4->GetOutput());
+         combine5->SetA(1.);
+         combine5->SetB(-1.);
+
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine6=LinearCombinationFilterType::New();
+         combine6->SetInput(0,combine5->GetOutput());
+         combine6->SetInput(1,row1);
+         combine6->SetA(m_WeightRatio[2][0]);
+         combine6->SetB(1.);
+         combine6->Update();
+         typename CoefficientImageType::Pointer bc2Row=combine6->GetOutput();
+
+         // Paste BC row at index 6
+         typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+         paster4->SetDestinationImage(paster3->GetOutput());
+         paster4->SetSourceImage(bc2Row);
+         destinationIndex[InputDimension-1]=6;
+         paster4->SetDestinationIndex(destinationIndex);
+         paster4->SetSourceRegion(bc2Row->GetLargestPossibleRegion());
+    
+         // Paste last row at index 7
+         typename PasteImageFilterType::Pointer paster5=PasteImageFilterType::New();
+         paster5->SetDestinationImage(paster4->GetOutput());
+         paster5->SetSourceImage(row5);
+         destinationIndex[InputDimension-1]=7;
+         paster5->SetDestinationIndex(destinationIndex);
+         paster5->SetSourceRegion(row5->GetLargestPossibleRegion());
+         
+         // Update the chain!
+         paster5->Update();
+         m_PaddedCoefficientImage= paster5->GetOutput();
+
+         break;
+       }
+
+      case 9:
+       {
+         // ----------------------------------------------------------------------
+         // The sputnik with 5 internal CP T''(0)=T''(10)
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and one indepent extreme
+         // Coeff     row BC1  0   1  BC2  2   3  BC3  4
+         // PaddedCoeff R: 0   1   2   3   4   5   6   7   
+         // BC1= -R2+R5+R7
+         // BC2= -weights[3]/weights[1] ( R2+R5 ) - R4
+         // BC3= R1
+         // ---------------------------------------------------------------------
+        
+         //---------------------------------
+         // 1. First Row =BC 
+         typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         typename CoefficientImageType::Pointer row3=this->ExtractTemporalRow(m_CoefficientImage, 3);
+         typename CoefficientImageType::Pointer row4=this->ExtractTemporalRow(m_CoefficientImage, 4);
+
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine0=LinearCombinationFilterType::New();
+         combine0->SetInput(0,row3);
+         combine0->SetInput(1,row4);
+         combine0->SetA(1.);
+         combine0->SetB(1.);
+         typename LinearCombinationFilterType::Pointer combine0bis=LinearCombinationFilterType::New();
+         combine0bis->SetInput(0,combine0->GetOutput());
+         combine0bis->SetInput(1,row1);
+         combine0bis->SetA(1.);
+         combine0bis->SetB(-1.);
+         combine0bis->Update();
+         typename CoefficientImageType::Pointer bc1Row=combine0bis->GetOutput();
+
+         typename PasteImageFilterType::Pointer paster0=PasteImageFilterType::New();
+         paster0->SetDestinationImage(m_PaddedCoefficientImage);
+         paster0->SetSourceImage(bc1Row);
+         destinationIndex[InputDimension-1]=0;
+         paster0->SetDestinationIndex(destinationIndex);
+         paster0->SetSourceRegion(bc1Row->GetLargestPossibleRegion());
+
+         //---------------------------------
+         // 1. Next two temporal rows are identical: paste 0-1 to 1-2
+         typename PasteImageFilterType::Pointer paster1=PasteImageFilterType::New();
+         paster1->SetDestinationImage(paster0->GetOutput());
+         paster1->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(NInputDimensions-1,0);
+         destinationIndex[InputDimension-1]=1;
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         paster1->SetDestinationIndex(destinationIndex);
+         paster1->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 2. Middle row at index 3=BC
+         // Extract row at index 1, 2 (of coeff image)
+         // typename CoefficientImageType::Pointer row1=this->ExtractTemporalRow(m_CoefficientImage, 1);
+         typename CoefficientImageType::Pointer row2=this->ExtractTemporalRow(m_CoefficientImage, 2);
+  
+         // Combine
+         typename LinearCombinationFilterType::Pointer combine1=LinearCombinationFilterType::New();
+         combine1->SetInput(0,row1);
+         combine1->SetInput(1,row3);
+         combine1->SetA(1.);
+         combine1->SetB(1.);
+         combine1->Update();
+
+         typename LinearCombinationFilterType::Pointer combine2=LinearCombinationFilterType::New();
+         combine2->SetInput(0,combine1->GetOutput());
+         combine2->SetInput(1,row2);
+         combine2->SetA(-m_WeightRatio[3][1]);
+         combine2->SetB(-1.);
+         combine2->Update();
+         typename CoefficientImageType::Pointer bc2Row=combine2->GetOutput();
+
+         // Paste middleRow at index 3 (padded coeff)
+         typename PasteImageFilterType::Pointer paster2=PasteImageFilterType::New();
+         paster2->SetDestinationImage(paster1->GetOutput());
+         paster2->SetSourceImage(bc2Row);
+         destinationIndex[InputDimension-1]=3;
+         paster2->SetDestinationIndex(destinationIndex);
+         paster2->SetSourceRegion(bc2Row->GetLargestPossibleRegion());
+         
+         //---------------------------------
+         // 3. Next two temporal rows are identical: paste 2,3 to 4,5
+         typename PasteImageFilterType::Pointer paster3=PasteImageFilterType::New();
+         paster3->SetDestinationImage(paster2->GetOutput());
+         paster3->SetSourceImage(m_CoefficientImage);
+         sourceRegion.SetIndex(InputDimension-1,2);
+         destinationIndex[InputDimension-1]=4;
+         sourceRegion.SetSize(NInputDimensions-1,2);
+         paster3->SetDestinationIndex(destinationIndex);
+         paster3->SetSourceRegion(sourceRegion);
+
+         //---------------------------------
+         // 4. Final row at index 6=BC3
+         typename CoefficientImageType::Pointer row0=this->ExtractTemporalRow(m_CoefficientImage, 0);
+    
+         //      // Combine
+         //      typename LinearCombinationFilterType::Pointer combine3=LinearCombinationFilterType::New();
+         //      combine3->SetInput(0,row0);
+         //      combine3->SetInput(1,row1);
+         //      combine3->SetA(1.);
+         //      combine3->SetB(0.5);
+         //      combine3->Update();
+         //      typename CoefficientImageType::Pointer bc3Row=combine3->GetOutput();
+
+         // Paste BC row at index 6
+         typename PasteImageFilterType::Pointer paster4=PasteImageFilterType::New();
+         paster4->SetDestinationImage(paster3->GetOutput());
+         paster4->SetSourceImage(row0);
+         destinationIndex[InputDimension-1]=6;
+         paster4->SetDestinationIndex(destinationIndex);
+         paster4->SetSourceRegion(row0->GetLargestPossibleRegion());
+    
+         // Paste row 4  at index 7
+         typename PasteImageFilterType::Pointer paster5=PasteImageFilterType::New();
+         paster5->SetDestinationImage(paster4->GetOutput());
+         paster5->SetSourceImage(row4);
+         destinationIndex[InputDimension-1]=7;
+         paster5->SetDestinationIndex(destinationIndex);
+         paster5->SetSourceRegion(row4->GetLargestPossibleRegion());
+         
+         // Update the chain!
+         paster5->Update();
+         m_PaddedCoefficientImage= paster5->GetOutput();
+
+         break;
+       }
+
+      default:
+       DD ("Shape not available");
+      }
+    
+  }
+  
+  
+  // // Extract coefficients from padded version
+  // template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  // void 
+  // ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  // ::ExtractCoefficientImage( )
+  // {
+  //   ////DD("extract coeff image");
+  //   typename ExtractImageFilterType::Pointer extractImageFilter = ExtractImageFilterType::New();
+  //   typename CoefficientImageType::RegionType extractionRegion=m_PaddedCoefficientImage->GetLargestPossibleRegion();
+  //   typename CoefficientImageType::RegionType::SizeType extractionSize=extractionRegion.GetSize();
+  //   typename CoefficientImageType::RegionType::IndexType extractionIndex = extractionRegion.GetIndex();
+  //   extractionSize[InputDimension-1]-=4;    
+  //   extractionIndex[InputDimension-1]=2;
+  //   extractionRegion.SetSize(extractionSize);
+  //   extractionRegion.SetIndex(extractionIndex);
+  //   extractImageFilter->SetInput(m_PaddedCoefficientImage);
+  //   extractImageFilter->SetExtractionRegion(extractionRegion);
+  //   extractImageFilter->Update();
+  //   m_CoefficientImage=extractImageFilter->GetOutput();
+  // } 
+
+
+  // Print self
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::PrintSelf(std::ostream &os, itk::Indent indent) const
+  {
+
+    this->Superclass::PrintSelf(os, indent);
+
+    os << indent << "GridRegion: " << m_GridRegion << std::endl;
+    os << indent << "GridOrigin: " << m_GridOrigin << std::endl;
+    os << indent << "GridSpacing: " << m_GridSpacing << std::endl;
+    os << indent << "GridDirection: " << m_GridDirection << std::endl;
+    os << indent << "IndexToPoint: " << m_IndexToPoint << std::endl;
+    os << indent << "PointToIndex: " << m_PointToIndex << std::endl;
+
+    os << indent << "CoefficientImage: [ ";
+    os << m_CoefficientImage.GetPointer() << " ]" << std::endl;
+
+    os << indent << "WrappedImage: [ ";
+    os << m_WrappedImage.GetPointer() << " ]" << std::endl;
+    os << indent << "InputParametersPointer: " 
+       << m_InputParametersPointer << std::endl;
+    os << indent << "ValidRegion: " << m_ValidRegion << std::endl;
+    os << indent << "LastJacobianIndex: " << m_LastJacobianIndex << std::endl;
+    os << indent << "BulkTransform: ";
+    os << m_BulkTransform << std::endl;
+
+    if ( m_BulkTransform )
+      {
+       os << indent << "BulkTransformType: " 
+          << m_BulkTransform->GetNameOfClass() << std::endl;
+      }
+    os << indent << "VectorBSplineInterpolator: ";
+    os << m_VectorInterpolator.GetPointer() << std::endl;
+    os << indent << "Mask: ";
+    os << m_Mask<< std::endl;
+  }
+
+
+  // Verify 
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  bool 
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::InsideValidRegion( const ContinuousIndexType& index ) const
+  {
+    bool inside = true;
+
+    if ( !m_ValidRegion.IsInside( index ) )
+      {
+       inside = false;
+      }
+
+    // JV verify all dimensions 
+    if ( inside)
+      {
+       typedef typename ContinuousIndexType::ValueType ValueType;
+       for( unsigned int j = 0; j < NInputDimensions; j++ )
+         {
+           if (m_SplineOrderOdd[j])
+             {
+               if ( index[j] >= static_cast<ValueType>( m_ValidRegionLast[j] ) )
+                 { 
+                   inside = false;
+                   break;
+                 }
+             }
+         }
+      }
+    return inside;
+  }
+
+
+  // Transform a point
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  typename ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::OutputPointType
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::TransformPoint(const InputPointType &inputPoint) const 
+  {
+  
+    InputPointType transformedPoint;
+    OutputPointType outputPoint;
+
+    // BulkTransform
+    if ( m_BulkTransform )
+      {
+       transformedPoint = m_BulkTransform->TransformPoint( inputPoint );
+      }
+    else
+      {
+       transformedPoint = inputPoint;
+      }
+    
+    // Deformable transform
+    if ( m_PaddedCoefficientImage )
+      {
+       // Check if inside mask
+       if(m_Mask &&  !(m_Mask->IsInside(inputPoint) ) )
+         {
+           // Outside: no (deformable) displacement
+           return transformedPoint;
+         }             
+       
+       // Check if inside valid region
+       bool inside = true;
+       ContinuousIndexType index;
+       this->TransformPointToContinuousIndex( inputPoint, index );
+       inside = this->InsideValidRegion( index );
+       if ( !inside )
+         {
+           // Outside: no (deformable) displacement
+           DD("outside valid region");
+           return transformedPoint;
+         }
+               
+       // Call the vector interpolator
+       itk::Vector<TCoordRep,SpaceDimension> displacement=m_VectorInterpolator->EvaluateAtContinuousIndex(index);
+       
+       // JV add for the spatial dimensions
+       outputPoint=transformedPoint;
+       for (unsigned int i=0; i<NInputDimensions-1; i++)
+         outputPoint[i] += displacement[i];
+
+      }
+
+    else
+      {
+       itkWarningMacro( << "B-spline coefficients have not been set" );
+       outputPoint = transformedPoint;
+      }
+    
+    return outputPoint;
+  }
+
+
+
+  //JV Deformably transform a point
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  typename ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::OutputPointType
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::DeformablyTransformPoint(const InputPointType &inputPoint) const 
+  {
+    OutputPointType outputPoint;
+    if ( m_PaddedCoefficientImage )
+      {
+
+       // Check if inside mask
+       if(m_Mask && !(m_Mask->IsInside(inputPoint) ) )
+         {
+           // Outside: no (deformable) displacement
+           return inputPoint;
+         }     
+       
+       // Check if inside
+       bool inside = true;
+       ContinuousIndexType index;
+       this->TransformPointToContinuousIndex( inputPoint, index );
+       inside = this->InsideValidRegion( index );
+
+       if ( !inside )
+         {
+           //outside: no (deformable) displacement
+           outputPoint = inputPoint;
+           return outputPoint;
+         }
+
+       // Call the vector interpolator
+       itk::Vector<TCoordRep,SpaceDimension> displacement=m_VectorInterpolator->EvaluateAtContinuousIndex(index);
+       
+       // JV add for the spatial dimensions
+       outputPoint=inputPoint;
+       for (unsigned int i=0; i<NInputDimensions-1; i++)
+         outputPoint[i] += displacement[i];
+      }
+
+    // No coefficients available
+    else
+      {
+       itkWarningMacro( << "B-spline coefficients have not been set" );
+       outputPoint = inputPoint;
+      }
+   
+    return outputPoint;
+  }
+  
+
+  // JV weights are identical as for transformpoint, could be done simultaneously in metric!!!!
+  // Compute the Jacobian in one position 
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  const 
+  typename ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::JacobianType & 
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetJacobian( const InputPointType & point ) const
+  {
+  
+    //========================================================
+    // Zero all components of jacobian
+    //========================================================
+    // JV not thread safe (m_LastJacobianIndex), instantiate N transforms
+    // NOTE: for efficiency, we only need to zero out the coefficients
+    // that got fill last time this method was called.
+    unsigned int j=0,b=0;
+      
+    //Set the previously-set to zero 
+    for ( j = 0; j < SpaceDimension; j++ )
+      {
+       m_FirstIterator[j].GoToBegin();
+       while ( !m_FirstIterator[j].IsAtEnd() )
+         {
+           m_FirstIterator[j].Set( m_ZeroVector );
+           ++(m_FirstIterator[j]);
+         }
+      }
+    
+    //Set the previously-set to zero 
+    for ( j = 0; j < SpaceDimension; j++ )
+      {
+       m_SecondIterator[j].GoToBegin();
+       while ( ! (m_SecondIterator[j]).IsAtEnd() )
+         {
+           m_SecondIterator[j].Set( m_ZeroVector );
+           ++(m_SecondIterator[j]);
+         }
+      }
+
+    //Set the previously-set to zero 
+    if (m_ThirdSize)
+      for ( j = 0; j < SpaceDimension; j++ )
+       {
+         m_ThirdIterator[j].GoToBegin();
+         while ( ! (m_ThirdIterator[j]).IsAtEnd() )
+           {
+             m_ThirdIterator[j].Set( m_ZeroVector );
+             ++(m_ThirdIterator[j]);
+           }
+       }
+
+    //Set the previously-set to zero 
+    if (m_BCSize)
+      for (b=0; b<m_BCSize;b++)
+       if ( !( m_FirstRegion.IsInside(m_BCRegions[b]) | m_SecondRegion.IsInside(m_BCRegions[b]) )  )
+         for ( j = 0; j < SpaceDimension; j++ ) 
+           {
+             m_BCIterators[j][b].GoToBegin();
+             while ( ! (m_BCIterators[j][b]).IsAtEnd() )
+               {
+                 m_BCIterators[j][b].Set( m_ZeroVector );
+                 ++(m_BCIterators[j][b]);
+               }
+           }
+       
+    //Set the previously-set to zero 
+    if (m_BC2Size)
+      for (b=0; b<m_BC2Size;b++)
+       if ( !( m_FirstRegion.IsInside(m_BC2Regions[b]) | m_SecondRegion.IsInside(m_BC2Regions[b]) )  )
+         for ( j = 0; j < SpaceDimension; j++ ) 
+           {
+             m_BC2Iterators[j][b].GoToBegin();
+             while ( ! (m_BC2Iterators[j][b]).IsAtEnd() )
+               {
+                 m_BC2Iterators[j][b].Set( m_ZeroVector );
+                 ++(m_BC2Iterators[j][b]);
+               }
+           }
+
+    //Set the previously-set to zero 
+    if (m_BC3Size)
+      for (b=0; b<m_BC3Size;b++)
+       if ( !( m_FirstRegion.IsInside(m_BC3Regions[b]) | m_SecondRegion.IsInside(m_BC3Regions[b]) )  )
+         for ( j = 0; j < SpaceDimension; j++ ) 
+           {
+             m_BC3Iterators[j][b].GoToBegin();
+             while ( ! (m_BC3Iterators[j][b]).IsAtEnd() )
+               {
+                 m_BC3Iterators[j][b].Set( m_ZeroVector );
+                 ++(m_BC3Iterators[j][b]);
+               }
+           }
+
+
+    //========================================================
+    // For each dimension, copy the weight to the support region
+    //========================================================
+
+    // Check if inside mask
+    if(m_Mask &&  !(m_Mask->IsInside(point) ) )
+      {
+       // Outside: no (deformable) displacement
+       return this->m_Jacobian;
+      }        
+
+    // Get index   
+    this->TransformPointToContinuousIndex( point, m_Index );
+
+    // NOTE: if the support region does not lie totally within the grid
+    // we assume zero displacement and return the input point
+    if ( !this->InsideValidRegion( m_Index ) )
+      {
+       return this->m_Jacobian;
+      }
+
+    // Compute interpolation weights
+    const WeightsDataType *weights=NULL;
+    m_VectorInterpolator->EvaluateWeightsAtContinuousIndex( m_Index, &weights, m_LastJacobianIndex);
+
+    // Get support
+    m_SupportRegion.SetIndex( m_LastJacobianIndex );
+    WrapRegion(m_SupportRegion, m_FirstRegion, m_SecondRegion, m_ThirdRegion, m_BCRegions, m_BCValues, m_BC2Regions, m_BC2Values, m_BC3Regions, m_BC3Values, m_InitialOffset);
+    m_ThirdSize=m_ThirdRegion.GetSize()[InputDimension-1]; 
+    m_BCSize=m_BCRegions.size();
+    m_BC2Size=m_BC2Regions.size();
+    m_BC3Size=m_BC3Regions.size();
+
+    // Reset the iterators
+    for ( j = 0; j < SpaceDimension ; j++ ) 
+      {
+       m_FirstIterator[j] = IteratorType( m_JacobianImage[j], m_FirstRegion);
+       m_SecondIterator[j] = IteratorType( m_JacobianImage[j], m_SecondRegion);
+       if(m_ThirdSize) m_ThirdIterator[j] = IteratorType( m_JacobianImage[j], m_ThirdRegion);
+
+       m_BCIterators[j].resize(m_BCSize);
+       for (b=0; b<m_BCSize;b++)
+         m_BCIterators[j][b]= IteratorType( m_JacobianImage[j], m_BCRegions[b]);
+       m_BC2Iterators[j].resize(m_BC2Size);
+       for (b=0; b<m_BC2Size;b++)
+         m_BC2Iterators[j][b]= IteratorType( m_JacobianImage[j], m_BC2Regions[b]);
+       m_BC3Iterators[j].resize(m_BC3Size);
+       for (b=0; b<m_BC3Size;b++)
+         m_BC3Iterators[j][b]= IteratorType( m_JacobianImage[j], m_BC3Regions[b]);
+      }
+
+    // Skip if on a fixed condition
+    if(m_InitialOffset)
+      {
+       if (m_BCSize)  weights+=m_InitialOffset*m_BCRegions[0].GetNumberOfPixels();
+       else std::cerr<<"InitialOffset without BCSize: Error!!!!!!!"<<std::endl;
+      }
+
+    //copy weight to jacobian image
+    for ( j = 0; j < SpaceDimension; j++ )
+      {
+       // For each dimension, copy the weight to the support region
+       while ( ! (m_FirstIterator[j]).IsAtEnd() )
+         {
+           m_ZeroVector[j]=*weights;
+           (m_FirstIterator[j]).Set( m_ZeroVector);
+           ++(m_FirstIterator[j]);
+           weights++;
+         }
+       
+       m_ZeroVector[j]=itk::NumericTraits<JacobianValueType>::Zero;
+       if (j != SpaceDimension-1)  weights-=m_FirstRegion.GetNumberOfPixels();
+      }
+            
+    // Skip BC1 and go to the second region
+    if (m_BCSize) weights+=m_BCRegions[0].GetNumberOfPixels();
+      
+    // For each dimension, copy the weight to the support region
+    //copy weight to jacobian image
+    for ( j = 0; j < SpaceDimension; j++ )
+      {
+       while ( ! (m_SecondIterator[j]).IsAtEnd() )
+         {
+           m_ZeroVector[j]=*weights;
+           (m_SecondIterator[j]).Set( m_ZeroVector);
+           ++(m_SecondIterator[j]);
+           weights++;
+         }
+       weights-=m_SecondRegion.GetNumberOfPixels();
+       m_ZeroVector[j]=itk::NumericTraits<JacobianValueType>::Zero;
+      }
+
+    // Now do BC1:
+    if (m_BCSize)
+      {        
+       //  Put pointer in correct position
+       weights-=m_BCRegions[0].GetNumberOfPixels();
+       
+       for ( j = 0; j < SpaceDimension; j++ )
+         {
+           for ( b=0; b < m_BCSize; b++ )
+             {
+               while ( ! (m_BCIterators[j][b]).IsAtEnd() )
+                 {
+                   //copy weight to jacobian image
+                   m_ZeroVector[j]=(*weights) * m_BCValues[b];
+                   (m_BCIterators[j][b]).Value()+= m_ZeroVector;
+                   ++(m_BCIterators[j][b]);
+                   weights++;
+                 }
+               weights-=m_BCRegions[b].GetNumberOfPixels();
+             }
+           m_ZeroVector[j]=itk::NumericTraits<JacobianValueType>::Zero;
+         }
+       weights+=m_BCRegions[m_BCSize-1].GetNumberOfPixels();
+      }
+        
+    // Add the BC2 to the weights
+    if (m_BC2Size)
+      {
+       // Move further in the weights pointer
+       weights+=m_SecondRegion.GetNumberOfPixels();
+
+       for ( j = 0; j < SpaceDimension; j++ )
+         {
+           for ( b=0; b < m_BC2Size; b++ )
+             {
+               while ( ! (m_BC2Iterators[j][b]).IsAtEnd() )
+                 {
+                   //copy weight to jacobian image
+                   m_ZeroVector[j]=(*weights) * m_BC2Values[b];
+                   (m_BC2Iterators[j][b]).Value()+= m_ZeroVector;
+                   ++(m_BC2Iterators[j][b]);
+                   weights++;
+                 }
+               weights-=m_BC2Regions[b].GetNumberOfPixels();
+             }
+           m_ZeroVector[j]=itk::NumericTraits<JacobianValueType>::Zero;
+         }
+       // Move further in the weights pointer
+       weights+=m_BC2Regions[m_BC2Size-1].GetNumberOfPixels();
+      }
+  
+    // Third Region
+    if(m_ThirdSize)
+      {
+       // For each dimension, copy the weight to the support region
+       //copy weight to jacobian image
+       for ( j = 0; j < SpaceDimension; j++ )
+         {
+           while ( ! (m_ThirdIterator[j]).IsAtEnd() )
+             {
+               m_ZeroVector[j]=*weights;
+               (m_ThirdIterator[j]).Value()+= m_ZeroVector;
+               ++(m_ThirdIterator[j]);
+               weights++;
+             }
+
+           // Move further in the weights pointer?
+           if (j != SpaceDimension-1) weights-=m_ThirdRegion.GetNumberOfPixels();
+           m_ZeroVector[j]=itk::NumericTraits<JacobianValueType>::Zero;
+         }
+      }
+
+    // Add the BC3 to the weights
+    if (m_BC3Size)
+      {
+       for ( j = 0; j < SpaceDimension; j++ )
+         {
+           for ( b=0; b < m_BC3Size; b++ )
+             {
+               while ( ! (m_BC3Iterators[j][b]).IsAtEnd() )
+                 {
+                   //copy weight to jacobian image
+                   m_ZeroVector[j]=(*weights) * m_BC3Values[b];
+                   (m_BC3Iterators[j][b]).Value()+= m_ZeroVector;
+                   ++(m_BC3Iterators[j][b]);
+                   weights++;
+                 }
+               weights-=m_BC3Regions[b].GetNumberOfPixels();
+             }
+           m_ZeroVector[j]=itk::NumericTraits<JacobianValueType>::Zero;
+         }
+      }
+
+    // Return the result
+    return this->m_Jacobian;
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void 
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::WrapRegion( const RegionType & m_SupportRegion, 
+               RegionType & m_FirstRegion, 
+               RegionType & m_SecondRegion,
+               RegionType & m_ThirdRegion,  
+               std::vector<RegionType>& m_BCRegions,std::vector<double>& m_BCValues, 
+               std::vector<RegionType>& m_BC2Regions,std::vector<double>& m_BC2Values,
+               std::vector<RegionType>& m_BC3Regions,std::vector<double>& m_BC3Values,
+               unsigned int& m_InitialOffset ) const
+  {
+
+    // Synchronize regions
+    m_InitialOffset=0;
+    m_FirstRegion=m_SupportRegion;
+    m_BCRegion=m_SupportRegion;
+    m_BCRegion.SetSize(InputDimension-1,1);
+    m_SecondRegion=m_SupportRegion;
+    m_ThirdRegion=m_SupportRegion;
+    m_ThirdRegion.SetSize(InputDimension-1,0);
+    m_BC3Regions.resize(0);
+
+
+    // BC depends on shape
+    switch(m_TransformShape)
+      {
+       /*  The shapes are
+           0: egg     4 CP  3 DOF
+           1: egg     5 CP  4 DOF 
+           2: rabbit  4 CP  3 DOF 
+           3: rabbit  5 CP  4 DOF
+           4: sputnik 4 CP  4 DOF
+           5: sputnik 5 CP  5 DOF
+           6: diamond 6 CP  5 DOF
+           7: diamond 7 CP  6 DOF
+       */
+  
+      case 0:
+       {         
+         // ----------------------------------------------------------------------
+         // The egg with 4 internal CP (starting from inhale)
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and
+         // Coeff      row  BC1 BC2  0  BC3  1   2  BC4
+         // PaddedCoeff  R:  0   1   2   3   4   5   6 
+         // BC1= R4
+         // BC2= R5
+         // BC3= -weights[2]/weights[0] ( R2+R4 ) 
+         // BC4= R2
+         // ---------------------------------------------------------------------
+         switch(m_SupportRegion.GetIndex(InputDimension-1)) 
+           {
+           case 0:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+               
+               // BC
+               m_BCRegions.resize(0);
+                    
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,0);
+               // BC
+               m_BC2Regions.resize(2);
+               m_BC2Values.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]= -m_WeightRatio[2][0];
+                                     
+               break;
+             }
+           case 1:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC
+               m_BCRegions.resize(0);
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC
+               m_BC2Regions.resize(2);
+               m_BC2Values.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]= -m_WeightRatio[2][0];
+
+               // Third Part
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+                     
+               break;
+             }
+           case 2:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -m_WeightRatio[2][0];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+
+               break;
+             }
+           case 3:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -m_WeightRatio[2][0];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC2
+               m_BC2Regions.resize(1);
+               m_BC2Values.resize(1);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=1;
+
+               break;
+             }
+                   
+           default:
+             {
+               DD("supportindex > 3 ???");
+               DD(m_SupportRegion.GetIndex(InputDimension-1));
+             }
+           } // end switch index
+               
+         break;
+       }
+
+      case 1:
+       {
+         // ----------------------------------------------------------------------
+         // The egg with 5 internal CP (starting from inhale)
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and
+         // Coeff      row  BC1 BC2  0  BC3  1   2   3  BC4
+         // PaddedCoeff  R:  0   1   2   3   4   5   6   7
+         // BC1= R5
+         // BC2= R6
+         // BC3= -weights[3]/weights[1] ( R2+R5 ) - R4 
+         // BC4= R2
+         // ---------------------------------------------------------------------
+         switch(m_SupportRegion.GetIndex(InputDimension-1)) 
+           {
+           case 0:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,2);
+               
+               // BC
+               m_BCRegions.resize(0);
+                    
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,0);
+               // BC
+               m_BC2Regions.resize(3);
+               m_BC2Values.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=-m_WeightRatio[3][1];
+                                     
+               break;
+             }
+           case 1:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,3);
+                     
+               // BC
+               m_BCRegions.resize(0);
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC
+               m_BC2Regions.resize(3);
+               m_BC2Values.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=-m_WeightRatio[3][1];
+
+               // Third Part
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+                     
+               break;
+             }
+           case 2:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+
+               break;
+             }
+           case 3:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,3);
+               m_SecondRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+       
+               break;
+             }
+           case 4:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,3);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC
+               m_BCRegions.resize(0);
+       
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+       
+               break;
+             }
+                   
+           default:
+             {
+               DD("supportindex > 3 ???");
+               DD(m_SupportRegion.GetIndex(InputDimension-1));
+             }
+           } // end switch index
+               
+         break;
+       }
+//       // ----------------------------------------------------------------------
+//       // The egg with 5 internal CP: 
+//       // Periodic, C2 smooth everywhere and constrained to zero at the reference
+//       // Coeff       row R5 BC1  0   1   2   3  BC2  R2  
+//       // PaddedCoeff R:  0   1   2   3   4   5   6   7    
+//       // BC1= -weights[2]/weights[0] ( R2+R5)
+//       // BC2= BC1  
+//       // ---------------------------------------------------------------------
+//       switch(m_SupportRegion.GetIndex(InputDimension-1))
+//         {
+//         case 0:
+//           {
+//             // Lower end 
+//             m_FirstRegion.SetSize(InputDimension-1,1);
+//             m_FirstRegion.SetIndex(InputDimension-1,3);
+                       
+//             // BC
+//             m_BCRegions.resize(2);
+//             m_BCValues.resize(2);
+//             m_BCRegion.SetIndex(InputDimension-1,0);
+//             m_BCRegions[0]=m_BCRegion;
+//             m_BCValues[0]=-m_WeightRatio[2][0];
+//             m_BCRegion.SetIndex(InputDimension-1,3);
+//             m_BCRegions[1]=m_BCRegion;
+//             m_BCValues[1]=-m_WeightRatio[2][0];
+             
+//             // Second part
+//             m_SecondRegion.SetSize(InputDimension-1,2);
+//             m_SecondRegion.SetIndex(InputDimension-1,0);
+
+//             // BC2
+//             m_BC2Regions.resize(0);
+
+//             break;
+//           }
+//         case 1:
+//           {
+//             // Lower end 
+//             m_FirstRegion.SetSize(InputDimension-1,0);
+                     
+//             // BC
+//             m_BCRegions.resize(2);
+//             m_BCValues.resize(2);
+//             m_BCRegion.SetIndex(InputDimension-1,0);
+//             m_BCRegions[0]=m_BCRegion;
+//             m_BCValues[0]=-m_WeightRatio[2][0];
+//             m_BCRegion.SetIndex(InputDimension-1,3);
+//             m_BCRegions[1]=m_BCRegion;
+//             m_BCValues[1]=-m_WeightRatio[2][0];
+             
+//             // Second part
+//             m_SecondRegion.SetSize(InputDimension-1,3);
+//             m_SecondRegion.SetIndex(InputDimension-1,0);
+
+//             // BC2
+//             m_BC2Regions.resize(0);
+
+//             break;
+//           }
+//         case 2:
+//           {
+//             // Lower end 
+//             m_FirstRegion.SetSize(InputDimension-1,4);
+//             m_FirstRegion.SetIndex(InputDimension-1,0);
+             
+//             // BC
+//             m_BCRegions.resize(0);
+                     
+//             // Second part
+//             m_SecondRegion.SetSize(InputDimension-1,0);
+       
+//             // BC2
+//             m_BC2Regions.resize(0);
+             
+//             break;
+//           }
+//         case 3:
+//           {
+//             // Lower end 
+//             m_FirstRegion.SetSize(InputDimension-1,3);
+//             m_FirstRegion.SetIndex(InputDimension-1,1);
+               
+//             // BC
+//             m_BCRegions.resize(2);
+//             m_BCValues.resize(2);
+//             m_BCRegion.SetIndex(InputDimension-1,0);
+//             m_BCRegions[0]=m_BCRegion;
+//             m_BCValues[0]=-m_WeightRatio[2][0];
+//             m_BCRegion.SetIndex(InputDimension-1,3);
+//             m_BCRegions[1]=m_BCRegion;
+//             m_BCValues[1]=-m_WeightRatio[2][0];
+               
+//             // Second part
+//             m_SecondRegion.SetSize(InputDimension-1,0);
+
+//             // BC2
+//             m_BC2Regions.resize(0);
+                
+//             break;
+//           }
+
+//         case 4:
+//           {
+//             // Lower end 
+//             m_FirstRegion.SetSize(InputDimension-1,2);
+//             m_FirstRegion.SetIndex(InputDimension-1,2);
+               
+//             // BC
+//             m_BCRegions.resize(2);
+//             m_BCValues.resize(2);
+//             m_BCRegion.SetIndex(InputDimension-1,0);
+//             m_BCRegions[0]=m_BCRegion;
+//             m_BCValues[0]=-m_WeightRatio[2][0];
+//             m_BCRegion.SetIndex(InputDimension-1,3);
+//             m_BCRegions[1]=m_BCRegion;
+//             m_BCValues[1]=-m_WeightRatio[2][0];
+
+//             // Second part
+//             m_SecondRegion.SetSize(InputDimension-1,1);
+//             m_SecondRegion.SetIndex(InputDimension-1,0);
+
+//             // BC2
+//             m_BC2Regions.resize(0);
+
+//             break;
+//           }
+
+//         default:
+//           {
+//             DD("supportindex > 4 ???");
+//             DD(m_SupportRegion.GetIndex(InputDimension-1));
+//             DD(m_TransformShape);
+//           }
+//         }// end swith index
+//       break;
+         
+//     } // end case 1 shape
+
+      case 2:
+       {
+         // ----------------------------------------------------------------------
+         // The rabbit with 4 internal CP
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and the extremes fixed with anit-symm bc
+         // Coeff      row  BC1  0   1  BC2  2  BC3 BC4 
+         // PaddedCoeff  R:  0   1   2   3   4   5   6 
+         // BC1= 2*R1-R0
+         // BC2= -weights[2]/weights[0] ( R2+R4 )
+         // BC3=  R1
+         // BC4= 2*R1-R4
+         // ---------------------------------------------------------------------
+         switch(m_SupportRegion.GetIndex(InputDimension-1)) 
+           {
+           case 0:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=2;
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+                    
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,0);
+               // BC
+               m_BC2Regions.resize(2);
+               m_BC2Values.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]= -m_WeightRatio[2][0];
+                                     
+               break;
+             }
+           case 1:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -m_WeightRatio[2][0];
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+                     
+               break;
+             }
+           case 2:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -m_WeightRatio[2][0];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(1);
+               m_BC2Values.resize(1);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=1;
+                                             
+               break;
+             }
+           case 3:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -m_WeightRatio[2][0];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(1);
+               m_BC2Values.resize(1);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=1;
+
+               // BC3
+               m_BC3Regions.resize(2);
+               m_BC3Values.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC3Regions[0]=m_BCRegion;
+               m_BC3Values[0]=2;
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC3Regions[1]=m_BCRegion;
+               m_BC3Values[1]= -1;
+
+               break;
+             }
+                   
+           default:
+             {
+               DD("supportindex > 3 ???");
+               DD(m_SupportRegion.GetIndex(InputDimension-1));
+             }
+           } // end switch index
+               
+         break;
+       } // end case 2 shape
+      case 3: 
+       {
+         // ----------------------------------------------------------------------
+         // The rabbit with 5 internal CP
+         // Periodic, constrained to zero at the reference at position 3.5 
+         // and the extremes fixed with anti-symmetrical BC
+         // Coeff      row  BC1  0   1  BC2  2   3  BC3 BC4
+         // PaddedCoeff  R:  0   1   2   3   4   5   6   7    
+         // BC1= 2*R1-R2
+         // BC2= -weights[3]/weights[1] ( R2+R5 ) - R4
+         // BC3= R1
+         // BC4= 2*R1-R5
+         // ---------------------------------------------------------------------
+         switch(m_SupportRegion.GetIndex(InputDimension-1)) 
+           {
+           case 0:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+                           
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=2.;
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1.;
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,0);
+       
+               // BC2
+               m_BC2Regions.resize(3);
+               m_BC2Values.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=-m_WeightRatio[3][1];      
+                     
+               break;
+             }
+           case 1:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+                     
+               break;
+             }
+           case 2:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];       
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+                     
+               break;
+             }
+           case 3:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];               
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(1);
+               m_BC2Values.resize(1);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=1.;
+                                     
+               break;
+             }
+                   
+           case 4:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BCRegions.resize(1);
+               m_BCValues.resize(1);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=1.;
+                             
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,0);
+                                     
+               // BC2
+               m_BC2Regions.resize(2);
+               m_BC2Values.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=2;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]=-1;
+                     
+               break;
+                     
+             }
+           default:
+             {
+               DD("supportindex > 4 ???");
+               DD(m_SupportRegion.GetIndex(InputDimension-1));
+             }
+           } // end switch index
+         
+         break;
+       } // end case 3 shape
+
+      case 4: 
+       {
+         // ----------------------------------------------------------------------
+         // The sputnik with 4 internal CP
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and one indepent extremes copied
+         // Coeff     row BC1  0   1  BC2  2  BC2  3
+         // PaddedCoeff R: 0   1   2   3   4   5   6      
+         // BC1= R6
+         // BC2= -weights[2]/weights[0] ( R2+R4 )
+         // BC3=  weights[2]/weights[0] ( R2-R4) + R1
+         // ---------------------------------------------------------------------
+         switch(m_SupportRegion.GetIndex(InputDimension-1)) 
+           {
+           case 0:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+
+               // BC
+               m_BCRegions.resize(1);
+               m_BCValues.resize(1);
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=1;
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,0);            
+               
+               // BC2
+               m_BC2Regions.resize(2);
+               m_BC2Values.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]= -m_WeightRatio[2][0];
+                     
+               break;
+             }
+           case 1:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -m_WeightRatio[2][0];
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+                     
+               break;
+             }
+           case 2:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -m_WeightRatio[2][0];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(3);
+               m_BC2Values.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=1;
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]=m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=-m_WeightRatio[2][0];      
+                                     
+               break;
+             }
+           case 3:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -m_WeightRatio[2][0];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(3);
+               m_BC2Values.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=1;
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]=m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=-m_WeightRatio[2][0];
+
+               // Third part
+               m_ThirdRegion.SetSize(InputDimension-1,1);
+               m_ThirdRegion.SetIndex(InputDimension-1,3);
+
+               break;
+             }
+                   
+           default:
+             {
+               DD("supportindex > 3 ???");
+               DD(m_SupportRegion.GetIndex(InputDimension-1));
+             }
+           } // end switch index
+               
+         break;
+       } // end case 4 shape
+       
+      case 5: 
+       {
+         // ----------------------------------------------------------------------
+         // The sputnik with 5 internal CP
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and one indepent extreme
+         // Coeff     row BC1  0   1  BC2  2   3  BC3  4
+         // PaddedCoeff R: 0   1   2   3   4   5   6   7   
+         // BC1= R2 + R5 - R7
+         // BC2= -weights[3]/weights[1] ( R2+R5 ) - R4
+         // BC3= R1 + 0.5 R2 - 0.5 R7
+         // ----------------------------------------------------------------------
+         switch(m_SupportRegion.GetIndex(InputDimension-1)) 
+           {
+           case 0:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=1.;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]=1.;
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-1.;
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,0);            
+               
+               // BC2
+               m_BC2Regions.resize(3);
+               m_BC2Values.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=-m_WeightRatio[3][1];
+                     
+               break;
+             }
+           case 1:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+                     
+               break;
+             }
+           case 2:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+                                             
+               break;
+             }
+           case 3:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(3);
+               m_BC2Values.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=1;
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]=0.5;
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=-0.5;
+       
+               break;
+             }
+           case 4:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,2);             
+      
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=1;
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]=0.5;
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-0.5;
+       
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,4);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+
+               break;
+             }
+           default:
+             {
+               DD("supportindex > 4 ???");
+               DD(m_SupportRegion.GetIndex(InputDimension-1));
+             }
+           } // end switch index
+               
+         break;
+       } // end case 5 shape
+
+
+
+     
+      case 6: 
+       {
+         // ----------------------------------------------------------------------
+         // The diamond with 4 internal CP:
+         // Periodic, constrained to zero at the reference at position 3
+         // Coeff      row 0   1   2  BC1  3  BC2  4
+         // PaddedCoeff  R:0   1   2   3   4   5   6    
+         // BC1= -weights[2]/weights[0] ( R2+R4 )
+         // BC2= weights[2]/weights[0]  ( R0+R2-R4-R6 ) + R1
+         // ---------------------------------------------------------------------
+         switch(m_SupportRegion.GetIndex(InputDimension-1)) 
+           {
+           case 0:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,3);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+               
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]=-m_WeightRatio[2][0];
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,0);
+
+               // BC2
+               m_BC2Regions.resize(0);
+               
+               break;
+             }
+           case 1:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+               
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]=-m_WeightRatio[2][0];  
+             
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,3);
+
+               // BC2
+               m_BC2Regions.resize(0);
+
+               break;
+             }
+           case 2:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,2);
+               
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]=-m_WeightRatio[2][0];               
+             
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,3);
+
+               // BC2
+               m_BC2Regions.resize(5);
+               m_BC2Values.resize(5);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]=1;
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=m_WeightRatio[2][0];       
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BC2Regions[3]=m_BCRegion;
+               m_BC2Values[3]=-m_WeightRatio[2][0];    
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BC2Regions[4]=m_BCRegion;
+               m_BC2Values[4]=-m_WeightRatio[2][0];
+               
+               break;
+             }
+           case 3:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+               
+               // BC
+               m_BCRegions.resize(2);
+               m_BCValues.resize(2);
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]=-m_WeightRatio[2][0];               
+             
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,3);
+
+               // BC2
+               m_BC2Regions.resize(5);
+               m_BC2Values.resize(5);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]=1;
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=m_WeightRatio[2][0];       
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BC2Regions[3]=m_BCRegion;
+               m_BC2Values[3]=-m_WeightRatio[2][0];    
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BC2Regions[4]=m_BCRegion;
+               m_BC2Values[4]=-m_WeightRatio[2][0];
+       
+               // Third part
+               m_ThirdRegion.SetSize(InputDimension-1,1);
+               m_ThirdRegion.SetIndex(InputDimension-1,4);
+               
+               break;
+             }
+             
+           default:
+             {
+               DD("supportindex > 3 ???");
+               DD(m_SupportRegion.GetIndex(InputDimension-1));
+             }
+           } // end switch index
+               
+         break;
+       } // end case 7 shape
+
+      case 7: 
+       {
+         // ----------------------------------------------------------------------
+         // The diamond with 5 internal CP: 
+         // periodic, constrained to zero at the reference at position 3.5
+         // Coeff      row 0   1   2  BC1  3   4  BC2  5
+         // PaddedCoeff  R:0   1   2   3   4   5   6   7    
+         // BC1= -weights[3]/weights[1] ( R2+R5 ) - R4
+         // BC2= weights[2]/weights[0] ( R0+R2-R5-R7 ) + R1
+         // ---------------------------------------------------------------------
+         switch(m_SupportRegion.GetIndex(InputDimension-1)) 
+           {
+           case 0:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,3);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+               
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];       
+             
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,0);
+
+               // BC2
+               m_BC2Regions.resize(0);
+               
+               break;
+             }
+           case 1:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+               
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];       
+             
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,3);
+
+               // BC2
+               m_BC2Regions.resize(0);
+
+               break;
+             }
+           case 2:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,2);
+               
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];               
+             
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,3);
+
+               // BC2
+               m_BC2Regions.resize(0);
+               
+               break;
+             }
+           case 3:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+               
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];               
+             
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,3);
+
+               // BC2
+               m_BC2Regions.resize(5);
+               m_BC2Values.resize(5);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]=1;
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=m_WeightRatio[2][0];       
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BC2Regions[3]=m_BCRegion;
+               m_BC2Values[3]=-m_WeightRatio[2][0];    
+               m_BCRegion.SetIndex(InputDimension-1,5);
+               m_BC2Regions[4]=m_BCRegion;
+               m_BC2Values[4]=-m_WeightRatio[2][0];    
+               
+               break;
+             }
+             
+           case 4:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,3);
+               
+               // BC
+               m_BCRegions.resize(5);
+               m_BCValues.resize(5);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=m_WeightRatio[2][0];
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]=1;
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=m_WeightRatio[2][0];        
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BCRegions[3]=m_BCRegion;
+               m_BCValues[3]=-m_WeightRatio[2][0];     
+               m_BCRegion.SetIndex(InputDimension-1,5);
+               m_BCRegions[4]=m_BCRegion;
+               m_BCValues[4]=-m_WeightRatio[2][0];     
+             
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,5);
+
+               // BC2
+               m_BC2Regions.resize(0);
+                       
+               break;
+             }
+
+           default:
+             {
+               DD("supportindex > 4 ???");
+               DD(m_SupportRegion.GetIndex(InputDimension-1));
+             }
+           } // end switch index
+               
+         break;
+       } // end case 7 shape
+
+      case 9:
+       {
+         // ----------------------------------------------------------------------
+         // The sputnik with 5 internal CP
+         // Periodic, constrained to zero at the reference 
+         // at position 3 and one indepent extreme
+         // Coeff     row BC1  0   1  BC2  2   3  BC3  4
+         // PaddedCoeff R: 0   1   2   3   4   5   6   7   
+         // BC1= -R2+R5-R7
+         // BC2= -weights[3]/weights[1] ( R2+R5 ) - R4
+         // BC3= R1
+         // ---------------------------------------------------------------------
+         switch(m_SupportRegion.GetIndex(InputDimension-1)) 
+           {
+           case 0:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]=1;
+               m_BCRegion.SetIndex(InputDimension-1,4);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-1;
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,0);            
+               
+               // BC2
+               m_BC2Regions.resize(3);
+               m_BC2Values.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BC2Regions[1]=m_BCRegion;
+               m_BC2Values[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BC2Regions[2]=m_BCRegion;
+               m_BC2Values[2]=-m_WeightRatio[3][1];
+                     
+               break;
+             }
+           case 1:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];
+                     
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+                     
+               break;
+             }
+           case 2:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,1);
+               m_FirstRegion.SetIndex(InputDimension-1,1);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,2);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+                                             
+               break;
+             }
+           case 3:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,0);
+                     
+               // BC
+               m_BCRegions.resize(3);
+               m_BCValues.resize(3);
+               m_BCRegion.SetIndex(InputDimension-1,1);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=-m_WeightRatio[3][1];
+               m_BCRegion.SetIndex(InputDimension-1,2);
+               m_BCRegions[1]=m_BCRegion;
+               m_BCValues[1]= -1;
+               m_BCRegion.SetIndex(InputDimension-1,3);
+               m_BCRegions[2]=m_BCRegion;
+               m_BCValues[2]=-m_WeightRatio[3][1];
+
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,2);
+                     
+               // BC
+               m_BC2Regions.resize(1);
+               m_BC2Values.resize(1);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BC2Regions[0]=m_BCRegion;
+               m_BC2Values[0]=1;
+       
+               break;
+             }
+           case 4:
+             {
+               // Lower end 
+               m_FirstRegion.SetSize(InputDimension-1,2);
+               m_FirstRegion.SetIndex(InputDimension-1,2);             
+      
+               // BC
+               m_BCRegions.resize(1);
+               m_BCValues.resize(1);
+               m_BCRegion.SetIndex(InputDimension-1,0);
+               m_BCRegions[0]=m_BCRegion;
+               m_BCValues[0]=1;
+               
+               // Second part
+               m_SecondRegion.SetSize(InputDimension-1,1);
+               m_SecondRegion.SetIndex(InputDimension-1,4);
+                     
+               // BC2
+               m_BC2Regions.resize(0);
+
+               break;
+             }
+           default:
+             {
+               DD("supportindex > 4 ???");
+               DD(m_SupportRegion.GetIndex(InputDimension-1));
+             }
+           } // end switch index
+               
+         break;
+       } // end case 9 shape
+       
+
+      default:
+       {
+         DD ("Other shapes currently not implemented");
+       }
+             
+      } // end switch shape
+  } // end wrap region
+       
+       
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  ShapedBLUTSpatioTemporalDeformableTransform<TCoordRep, NInputDimensions,NOutputDimensions>
+  ::TransformPointToContinuousIndex( const InputPointType & point, ContinuousIndexType & index ) const
+  {
+    unsigned int j;
+    
+    itk::Vector<double, OutputDimension> tvector;
+    
+    for ( j = 0; j < OutputDimension; j++ )
+      {
+       //JV find the index in the PADDED version
+       tvector[j] = point[j] - this->m_PaddedGridOrigin[j];
+      }
+    
+    itk::Vector<double, OutputDimension> cvector;
+    
+    cvector = m_PointToIndex * tvector;
+    
+    for ( j = 0; j < OutputDimension; j++ )
+      {
+       index[j] = static_cast< typename ContinuousIndexType::CoordRepType >( cvector[j] );
+      }
+  }
+  
+  
+} // namespace
+
+#endif
+
diff --git a/registration/clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.h b/registration/clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.h
new file mode 100755 (executable)
index 0000000..8c5d286
--- /dev/null
@@ -0,0 +1,183 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkShapedBLUTSpatioTemporalDeformableTransformInitializer_h
+#define __clitkShapedBLUTSpatioTemporalDeformableTransformInitializer_h
+#include "clitkResampleBSplineDeformableTransformImageFilter.h"
+
+#include "itkObject.h"
+#include "itkObjectFactory.h"
+#include "itkImageFileReader.h"
+#include <iostream>
+
+namespace clitk
+{
+
+
+template < class TTransform, class TImage >
+class ITK_EXPORT ShapedBLUTSpatioTemporalDeformableTransformInitializer : public itk::Object
+{
+public:
+  /** Standard class typedefs. */
+  typedef ShapedBLUTSpatioTemporalDeformableTransformInitializer     Self;
+  typedef itk::Object                               Superclass;
+  typedef itk::SmartPointer<Self>                   Pointer;
+  typedef itk::SmartPointer<const Self>             ConstPointer;
+
+  /** New macro for creation of through a Smart Pointer. */
+  itkNewMacro( Self );
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( ShapedBLUTSpatioTemporalDeformableTransformInitializer, Object );
+
+  // Typedefs
+  typedef TTransform                                TransformType;
+  typedef typename TransformType::Pointer           TransformPointer;
+  typedef typename TransformType::RegionType        RegionType;
+  typedef typename TransformType::OriginType        OriginType;
+  typedef typename TransformType::DirectionType        DirectionType;
+  typedef typename RegionType::SizeType             SizeType;
+  typedef typename TransformType::SpacingType       SpacingType;
+  itkStaticConstMacro(InputDimension, unsigned int, TransformType::InputDimension);
+  typedef   TImage                                  ImageType;
+  typedef typename ImageType::ConstPointer        ImagePointer;
+  typedef typename TransformType::CoefficientImageType CoefficientImageType;
+  typedef typename TransformType::ParametersType ParametersType;
+
+  // Set and Get
+  itkBooleanMacro(Verbose);
+  itkSetMacro( Verbose, bool);
+  itkGetConstReferenceMacro( Verbose, bool);
+  itkSetObjectMacro( Transform,   TransformType   );
+  itkGetConstObjectMacro( Transform,   TransformType   );
+  itkSetObjectMacro( Image,  ImageType  );
+  itkGetConstObjectMacro( Image,  ImageType  );
+
+  void SetSplineOrder(const unsigned int & splineOrder)
+  {
+    SizeType s;
+    s.Fill(splineOrder);
+    this->SetSplineOrders(s);
+  }
+  void SetSplineOrders(const SizeType & splineOrders)
+  {
+    m_SplineOrders=splineOrders;
+  }
+  void SetNumberOfControlPointsInsideTheImage(  SizeType & n  )
+  {
+    m_NumberOfControlPointsInsideTheImage=n;
+    m_NumberOfControlPointsIsGiven=true;
+    this->Modified();
+  }
+  void SetNumberOfControlPointsInsideTheImage(  int * n)
+  {
+    SizeType s;
+    for (unsigned int i=0;i<InputDimension;i++) 
+      s[i]=n[i];
+    this->SetNumberOfControlPointsInsideTheImage( s );
+  }
+  void SetNumberOfControlPointsInsideTheImage(  unsigned int & n )
+  {
+    SizeType s;
+    s.Fill( n );;
+    this->SetNumberOfControlPointsInsideTheImage( s );
+  }
+  void SetControlPointSpacing( SpacingType n )
+  {
+    m_ControlPointSpacing= n;
+    m_ControlPointSpacingIsGiven=true;
+    this->Modified();
+  }
+  void SetControlPointSpacing( double*& n )
+  {
+    SpacingType s( n );
+    this->SetControlPointSpacing(s);
+  }
+  void SetControlPointSpacing( double n )
+  {
+    SpacingType s;
+    s.Fill( n );
+    this->SetControlPointSpacing(s);
+  }
+  void SetSamplingFactors(  SizeType n  )
+  {
+    m_SamplingFactors=n;
+    m_SamplingFactorIsGiven=true;
+    this->Modified();
+  }
+  void SetSamplingFactors(  int *& n)
+  {
+    SizeType s;
+    for (unsigned int i=0;i<InputDimension;i++) 
+      s[i]=n[i];
+    this-> SetSamplingFactors( s );
+  }
+  void SetSamplingFactors( unsigned  int n )
+  {
+    SizeType s;
+    s.Fill( n );
+    this-> SetSamplingFactors( s );
+  }
+  virtual void InitializeTransform();
+  void SetInitialParameters(const typename CoefficientImageType::Pointer coefficientImage, ParametersType& params);
+  void SetInitialParameters(const std::string & s, ParametersType& params);
+//   void SetInitialPaddedParameters(const typename CoefficientImageType::Pointer coefficientImage, ParametersType& params);
+//   void SetInitialPaddedParameters(const std::string & s, ParametersType& params);
+
+  // For easy acces, declared public
+  std::vector<SizeType> m_NumberOfControlPointsInsideTheImageArray;
+  std::vector<SizeType> m_SamplingFactorsArray;
+  std::vector<SpacingType> m_ControlPointSpacingArray;
+
+  SpacingType   m_ControlPointSpacing;
+  SizeType   m_SamplingFactors;
+  SizeType   m_SplineOrders;
+  SpacingType   m_ChosenSpacing;
+  SizeType   m_NumberOfControlPointsInsideTheImage;
+  bool m_NumberOfControlPointsIsGiven;
+  bool m_ControlPointSpacingIsGiven;
+  bool m_SamplingFactorIsGiven;
+  bool m_TransformRegionIsGiven;
+  unsigned int m_TrajectoryShape;
+
+  typename TransformType::ParametersType* m_Parameters;
+
+protected:
+  ShapedBLUTSpatioTemporalDeformableTransformInitializer();
+  ~ShapedBLUTSpatioTemporalDeformableTransformInitializer(){};
+
+private:
+  ShapedBLUTSpatioTemporalDeformableTransformInitializer(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+  bool m_Verbose;
+  TransformPointer    m_Transform;
+  ImagePointer        m_Image;
+  bool m_BC1;
+  bool m_BC2;
+
+}; //class ShapedBLUTSpatioTemporalDeformableTransformInitializer
+
+
+}  // namespace clitk
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.txx"
+#endif
+
+#endif /* __clitkShapedBLUTSpatioTemporalDeformableTransformInitializer_h */
diff --git a/registration/clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.txx b/registration/clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.txx
new file mode 100755 (executable)
index 0000000..d78fb97
--- /dev/null
@@ -0,0 +1,503 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkShapedBLUTSpatioTemporalDeformableTransformInitializer_txx
+#define __clitkShapedBLUTSpatioTemporalDeformableTransformInitializer_txx
+#include "clitkShapedBLUTSpatioTemporalDeformableTransformInitializer.h"
+
+namespace clitk
+{
+
+
+  template < class TTransform, class TImage >
+  ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
+  ::ShapedBLUTSpatioTemporalDeformableTransformInitializer()
+  {
+    this->m_NumberOfControlPointsInsideTheImage.Fill( 5 );
+    this->m_ControlPointSpacing.Fill(64.);
+    m_ControlPointSpacing[InputDimension-1]=2;
+    this->m_ChosenSpacing.Fill(64.);
+    m_ChosenSpacing[InputDimension-1]=2;
+    m_ControlPointSpacing[InputDimension-1]=2;
+    m_NumberOfControlPointsIsGiven=false;
+    m_ControlPointSpacingIsGiven=false;
+    m_TransformRegionIsGiven=false;
+    m_SamplingFactorIsGiven=false;
+    m_SplineOrders.Fill(3);
+    m_BC1=true;
+    m_BC2=true;
+    m_TrajectoryShape=0;
+  }
+
+  template < class TTransform, class TImage >
+  void
+  ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
+  ::InitializeTransform()
+  {
+    // Sanity check:
+    // The image is required for the region and spacing
+    if( ! this->m_Image )
+      {
+       itkExceptionMacro( "Reference Image has not been set" );
+       return;
+      }
+    
+    // A pointer to the transform is required
+    if( ! this->m_Transform )
+      {
+       itkExceptionMacro( "Transform has not been set" );
+       return;
+      }
+
+    // If the image come from a filter, then update that filter.
+    if( this->m_Image->GetSource() )
+      {
+       this->m_Image->GetSource()->Update();
+      }
+
+
+    //--------------------------------------
+    // Spacing & Size on image
+    //--------------------------------------
+    SpacingType fixedImageSpacing = m_Image->GetSpacing();
+    SizeType fixedImageSize=m_Image->GetLargestPossibleRegion().GetSize();
+    typename RegionType::SizeType   gridBorderSize;
+    typename RegionType::SizeType   totalGridSize;
+
+    // Only spacing given: adjust if necessary
+    if (m_ControlPointSpacingIsGiven  && !m_NumberOfControlPointsIsGiven)
+      {
+       for(unsigned int r=0; r<InputDimension; r++) 
+         {
+           // JV
+           m_ChosenSpacing[r]= m_ControlPointSpacing[r];
+           m_ControlPointSpacing[r]= ( round(m_ChosenSpacing[r]/fixedImageSpacing[r]) *fixedImageSpacing[r] ) ;
+           m_NumberOfControlPointsInsideTheImage[r] = ceil( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] );
+           if ( (  ( ceil( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] ) )
+                == ( (double)fixedImageSize[r]*fixedImageSpacing[r]/ m_ControlPointSpacing[r] ) )
+                &&  (r!= InputDimension-1)  )
+             {
+               m_NumberOfControlPointsInsideTheImage[r] +=1;
+               DD("Adding control point");
+             }
+         }
+      }
+  
+    // Only number of CP given: adjust if necessary
+    // JV -1 ?
+    else if (!m_ControlPointSpacingIsGiven  && m_NumberOfControlPointsIsGiven)
+      {
+       for(unsigned int r=0; r<InputDimension; r++) 
+         {
+           m_ChosenSpacing[r]=fixedImageSpacing[r]*( (double)(fixedImageSize[r])  / 
+                                                     (double)(m_NumberOfControlPointsInsideTheImage[r]) );
+           m_ControlPointSpacing[r]= fixedImageSpacing[r]* ceil( (double)(fixedImageSize[r] - 1)  / 
+                                                                 (double)(m_NumberOfControlPointsInsideTheImage[r] - 1) );
+         }
+      }
+  
+    // Both or none of Spacing and number of CP given: no adjustment adjust, just warnings
+    else 
+      {
+       for(unsigned int r=0; r<InputDimension; r++) 
+         {
+           m_ChosenSpacing[r]= m_ControlPointSpacing[r];
+           if (m_NumberOfControlPointsInsideTheImage[r]*m_ControlPointSpacing[r]< fixedImageSize[r]*fixedImageSpacing[r]) 
+             {
+               std::cout<<"WARNING: Specified control point region ("<<m_NumberOfControlPointsInsideTheImage[r]*m_ControlPointSpacing[r]
+                        <<"mm) does not cover the fixed image region ("<< fixedImageSize[r]*fixedImageSpacing[r]
+                        <<"mm) for dimension "<<r<<"!" <<std::endl
+                        <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;
+             }
+           if (  fmod(m_ControlPointSpacing[r], fixedImageSpacing[r]) ) 
+             {
+               std::cout<<"WARNING: Specified control point spacing for dimension "<<r
+                        <<" does not allow exact representation of BLUT FFD!"<<std::endl
+                        <<"Spacing ratio is non-integer: "<<m_ControlPointSpacing[r]/ fixedImageSpacing[r]<<std::endl
+                        <<"Specify only --spacing or --control for automatic adjustment..."<<std::endl;  
+             }
+         }
+      }
+
+    //--------------------------------------
+    // LUT sampling factors
+    //--------------------------------------
+    for (unsigned int i=0; i< InputDimension; i++)
+      {
+       if (m_Verbose) std::cout<<"For dimension "<<i<<", the ideal sampling factor (if integer) is a multitude of "
+                               << m_ControlPointSpacing[i]/ fixedImageSpacing[i]<<"..."<<std::endl;
+       if ( !m_SamplingFactorIsGiven) m_SamplingFactors[i]= (int) ( m_ControlPointSpacing[i]/ fixedImageSpacing[i]);
+      }
+
+    //--------------------------------------
+    // Set the transform properties 
+    //--------------------------------------
+    RegionType gridRegion;
+    OriginType gridOrigin;
+    DirectionType gridDirection;
+
+    //--------------------------------------
+    // Border size 
+    //--------------------------------------
+    for(unsigned int r=0; r<InputDimension; r++) gridBorderSize[r]=m_SplineOrders[r]; // Border for spline order = 3 ( 1 lower, 2 upper )
+    totalGridSize = m_NumberOfControlPointsInsideTheImage + gridBorderSize;
+
+    //--------------------------------------
+    // Origin
+    //--------------------------------------
+    OriginType fixedImageOrigin;
+
+    // In case of non-zero index
+    m_Image->TransformIndexToPhysicalPoint(m_Image->GetLargestPossibleRegion().GetIndex(),fixedImageOrigin);
+    gridDirection = m_Image->GetDirection();      
+    itk::FixedArray<int, InputDimension> orderShift;
+    
+    // Spacing is 2.5 : manually modify the props
+    if( !(m_Transform->GetTransformShape()%2) )
+      {
+       m_ControlPointSpacing[InputDimension-1]=2.5;
+       m_SamplingFactors[InputDimension-1]=5;
+       totalGridSize[InputDimension-1]-=1;
+       gridRegion.SetSize(totalGridSize);
+      }
+
+
+    switch(m_Transform->GetTransformShape()){
+    
+      // The egg shape
+    case 0:
+    case 1:  
+      {
+       if (m_Verbose) std::cout<<"Using the egg shape..."<<std::endl;
+
+       //--------------------------------------
+       // Border size 
+       //--------------------------------------
+       // Boundary condition1: cyclic
+       if (m_BC1)
+         totalGridSize[InputDimension-1]-=3;
+       
+       // Boundary condition1: reference is on trajectory
+       if (m_BC2)
+         totalGridSize[InputDimension-1]-=1;
+       
+       gridRegion.SetSize(totalGridSize);
+               
+       //--------------------------------------
+       // Origin
+       //--------------------------------------
+       // Shift depends on order
+       for(unsigned int r=0; r<InputDimension; r++)
+         {
+           orderShift[r] = m_SplineOrders[r] / 2;
+           if (r==InputDimension-1)
+             {
+               // Boundary condition1: cyclic
+               if (m_BC1)
+                 orderShift[r]-=1;
+               
+               // Boundary condition1: reference is on trajectory
+               if (m_BC2)
+                 orderShift[r]-=1;
+             }
+           
+           gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
+         } 
+       break;
+      }
+
+      // The rabit: a diamond with fixed extreme values
+    case 2:
+    case 3:
+      {
+
+       if (m_Verbose) std::cout<<"Using the rabbit shape..."<<std::endl;
+       
+       //--------------------------------------
+       // Border size 
+       //--------------------------------------
+       // Boundary condition1: cyclic
+       if (m_BC1)
+         totalGridSize[InputDimension-1]-=1;
+       
+       // Boundary condition1: reference is on trajectory
+       if (m_BC2)
+         totalGridSize[InputDimension-1]-=1;
+
+       // Extreme values are constrained
+       totalGridSize[InputDimension-1]-=2;
+       
+       gridRegion.SetSize(totalGridSize);
+       
+       //--------------------------------------
+       // Origin
+       //--------------------------------------
+       // Shift depends on order
+       for(unsigned int r=0; r<InputDimension; r++)
+         {
+           orderShift[r] = m_SplineOrders[r] / 2;
+           if (r==InputDimension-1)
+             {
+               // Boundary condition1: cyclic
+               orderShift[r]=0;
+             }
+           gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
+         } 
+
+       break;
+      }
+
+      // The sputnik: a diamond with one indepent extreme value and 4DOF
+    case 4:
+    case 5:
+      {
+       if (m_Verbose) std::cout<<"Using the sputnik shape..."<<std::endl;
+
+       //--------------------------------------
+       // Border size 
+       //--------------------------------------
+       // Boundary condition1: cyclic
+       if (m_BC1)
+         totalGridSize[InputDimension-1]-=1;
+       
+       // Boundary condition1: reference is on trajectory
+       if (m_BC2)
+         totalGridSize[InputDimension-1]-=1;
+
+       // One extreme value is fixed
+       totalGridSize[InputDimension-1]-=1;
+       gridRegion.SetSize(totalGridSize);
+       
+       //--------------------------------------
+       // Origin
+       //--------------------------------------
+       // Shift depends on order
+       for(unsigned int r=0; r<InputDimension; r++)
+         {
+           orderShift[r] = m_SplineOrders[r] / 2;
+           if (r==InputDimension-1)
+             {
+               // Boundary condition1: cyclic
+               orderShift[r]=0;
+             }
+           gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
+         } 
+       break;
+      }
+
+      // The diamond
+    case 6:  
+    case 7:
+      {
+       if (m_Verbose) std::cout<<"Using the diamond shape..."<<std::endl;
+       
+       //--------------------------------------
+       // Border size 
+       //--------------------------------------
+       // Boundary condition1: cyclic
+       if (m_BC1)
+         totalGridSize[InputDimension-1]-=1;
+       
+       // Boundary condition1: reference is on trajectory
+       if (m_BC2)
+         totalGridSize[InputDimension-1]-=1;
+       
+       gridRegion.SetSize(totalGridSize);
+       
+       //--------------------------------------
+       // Origin
+       //--------------------------------------
+       // Shift depends on order
+       for(unsigned int r=0; r<InputDimension; r++)
+         {
+           orderShift[r] = m_SplineOrders[r] / 2;
+           gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
+         } 
+
+       break;
+
+      } //end case 7
+
+   // The sputnik: a diamond with one indepent extreme value and 4DOF
+    case 8:
+    case 9:
+      {
+       if (m_Verbose) std::cout<<"Using the sputnik shape..."<<std::endl;
+
+       //--------------------------------------
+       // Border size 
+       //--------------------------------------
+       // Boundary condition1: cyclic
+       if (m_BC1)
+         totalGridSize[InputDimension-1]-=1;
+       
+       // Boundary condition1: reference is on trajectory
+       if (m_BC2)
+         totalGridSize[InputDimension-1]-=1;
+
+       // One extreme value is fixed
+       totalGridSize[InputDimension-1]-=1;
+       gridRegion.SetSize(totalGridSize);
+       
+       //--------------------------------------
+       // Origin
+       //--------------------------------------
+       // Shift depends on order
+       for(unsigned int r=0; r<InputDimension; r++)
+         {
+           orderShift[r] = m_SplineOrders[r] / 2;
+           if (r==InputDimension-1)
+             {
+               // Boundary condition1: cyclic
+               orderShift[r]=0;
+             }
+           gridOrigin[r] = fixedImageOrigin[r]- (double) orderShift[r]* m_ControlPointSpacing[r];
+         } 
+       break;
+      }
+  
+    default:
+      {
+       DD("Shape not available");
+      }
+
+    }
+
+
+
+    if (m_Verbose) std::cout<<"The chosen control point spacing "<<m_ChosenSpacing<<"..."<<std::endl;
+    if (m_Verbose) std::cout<<"The control points spacing was adapted to "<<m_ControlPointSpacing<<"..."<<std::endl; 
+    if (m_Verbose) std::cout<<"The number of (internal) control points is "<<m_NumberOfControlPointsInsideTheImage<<"..."<<std::endl;
+    if (m_Verbose) std::cout<<"Setting sampling factors to "<<m_SamplingFactors<<"..."<<std::endl; 
+    if (m_Verbose) std::cout<<"The total control point grid size was set to "<<totalGridSize<<"..."<<std::endl;
+    if (m_Verbose) std::cout<<"The control point grid origin was set to "<<gridOrigin<<"..."<<std::endl;
+    
+    //--------------------------------------
+    // Set
+    //--------------------------------------
+    this->m_Transform->SetSplineOrders(m_SplineOrders);
+    this->m_Transform->SetGridSpacing( m_ControlPointSpacing );
+    this->m_Transform->SetGridOrigin( gridOrigin );
+    this->m_Transform->SetGridDirection( gridDirection );
+    this->m_Transform->SetGridRegion( gridRegion );
+    this->m_Transform->SetLUTSamplingFactors(m_SamplingFactors);
+
+  }
+
+  template < class TTransform, class TImage >
+  void
+  ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
+  ::SetInitialParameters( const std::string& s, ParametersType& params) 
+  {
+    //---------------------------------------
+    // Read Initial parameters
+    //---------------------------------------
+    typedef itk::ImageFileReader<CoefficientImageType> CoefficientReaderType;
+    typename CoefficientReaderType::Pointer coeffReader=CoefficientReaderType::New();
+    coeffReader->SetFileName(s);
+    if(m_Verbose) std::cout<<"Reading initial coefficients from file: "<<s<<"..."<<std::endl;
+    coeffReader->Update();
+    typename CoefficientImageType::Pointer coefficientImage=coeffReader->GetOutput();
+    this->SetInitialParameters(coefficientImage, params);
+  }
+  
+  template < class TTransform, class TImage >
+  void
+  ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
+  ::SetInitialParameters(const typename CoefficientImageType::Pointer coefficientImage, ParametersType& params) 
+  {
+    // Keep a reference 
+    m_Parameters=&params;
+
+    // Resample
+    typedef ResampleBSplineDeformableTransformImageFilter<CoefficientImageType,CoefficientImageType> ResamplerType;
+    typename ResamplerType::Pointer resampler=ResamplerType::New();
+    resampler->SetVerbose(m_Verbose);
+    resampler->SetInput(coefficientImage);     
+    resampler->SetOutputParametersFromImage(m_Transform->GetCoefficientImage()); 
+    if(m_Verbose) std::cout<<"Resampling initial coefficients..."<<std::endl;
+    resampler->Update();
+
+    // Copy parameters into the existing array, I know its crappy
+    typedef itk::ImageRegionConstIterator<CoefficientImageType> Iterator;
+    Iterator it (resampler->GetOutput(), resampler->GetOutput()->GetLargestPossibleRegion() );
+    it.GoToBegin();
+    unsigned int i=0;
+    while(! it.IsAtEnd())
+      {
+       for (unsigned int j=0; j<InputDimension-1;j++)
+         params[i+j]=it.Get()[j];
+
+       ++it;
+       i+=InputDimension-1;
+      }
+
+    // JV pass the reference to the array !!
+    // JV Update the padded version !!
+    this->m_Transform->SetParameters(params);
+  }
+
+
+  //   template < class TTransform, class TImage >
+  //   void
+  //   ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
+  //   ::SetInitialPaddedParameters( const std::string& s, ParametersType& params) 
+  //   {
+  //     //---------------------------------------
+  //     // Read Initial parameters
+  //     //---------------------------------------
+  //     typedef itk::ImageFileReader<CoefficientImageType> CoefficientReaderType;
+  //     typename CoefficientReaderType::Pointer coeffReader=CoefficientReaderType::New();
+  //     coeffReader->SetFileName(s);
+  //     if(m_Verbose) std::cout<<"Reading initial padded coefficients from file: "<<s<<"..."<<std::endl;
+  //     coeffReader->Update();
+  //     typename CoefficientImageType::Pointer coefficientImage=coeffReader->GetOutput();
+  //     this->SetInitialPaddedParameters(coefficientImage, params);
+  //   }
+  
+  //   template < class TTransform, class TImage >
+  //   void
+  //   ShapedBLUTSpatioTemporalDeformableTransformInitializer<TTransform, TImage >
+  //   ::SetInitialPaddedParameters(const typename CoefficientImageType::Pointer coefficientImage, ParametersType& params) 
+  //   {
+  //     // Resample
+  //     typedef ResampleBSplineSpatioTemporalDeformableTransformImageFilter<CoefficientImageType,CoefficientImageType> ResamplerType;
+  //     typename ResamplerType::Pointer resampler=ResamplerType::New();
+  //     resampler->SetInput(coefficientImage);        
+  //     resampler->SetOutputParametersFromImage(m_Transform->GetCoefficientImage()); 
+  //     if(m_Verbose) std::cout<<"Resampling initial padded coefficients..."<<std::endl;
+  //     resampler->Update();
+    
+  //     // Copy parameters into the existing array, I know its crappy
+  //     typedef itk::ImageRegionConstIterator<CoefficientImageType> Iterator;
+  //     Iterator it (resampler->GetOutput(), resampler->GetOutput()->GetLargestPossibleRegion() );
+  //     it.GoToBegin();
+  //     unsigned int i=0;
+  //     while(! it.IsAtEnd())
+  //       {
+  //   for (unsigned int j=0; j<InputDimension;j++)
+  //     params[i+j]=it.Get()[j];
+
+  //   ++it;
+  //   i+=InputDimension;
+  //       }
+  //   }
+
+  
+}  // namespace itk
+
+#endif
diff --git a/registration/clitkSpatioTemporalMultiResolutionImageRegistrationMethod.h b/registration/clitkSpatioTemporalMultiResolutionImageRegistrationMethod.h
new file mode 100644 (file)
index 0000000..4a019bb
--- /dev/null
@@ -0,0 +1,247 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkSpatioTemporalMultiResolutionImageRegistrationMethod_h
+#define __clitkSpatioTemporalMultiResolutionImageRegistrationMethod_h
+#include "clitkSpatioTemporalMultiResolutionPyramidImageFilter.h"
+
+#include "itkProcessObject.h"
+#include "itkImageToImageMetric.h"
+#include "itkSingleValuedNonLinearOptimizer.h"
+#include "itkNumericTraits.h"
+#include "itkDataObjectDecorator.h"
+
+namespace clitk
+{
+
+template <typename TFixedImage, typename TMovingImage>
+class ITK_EXPORT SpatioTemporalMultiResolutionImageRegistrationMethod : public itk::ProcessObject 
+{
+public:
+  /** Standard class typedefs. */
+  typedef SpatioTemporalMultiResolutionImageRegistrationMethod  Self;
+  typedef itk::ProcessObject                      Superclass;
+  typedef SmartPointer<Self>                      Pointer;
+  typedef SmartPointer<const Self>                ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+  
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(SpatioTemporalMultiResolutionImageRegistrationMethod, ProcessObject);
+
+  /**  Type of the Fixed image. */
+  typedef          TFixedImage                     FixedImageType;
+  typedef typename FixedImageType::ConstPointer    FixedImageConstPointer;
+  typedef typename FixedImageType::RegionType      FixedImageRegionType;
+
+  /**  Type of the Moving image. */
+  typedef          TMovingImage                    MovingImageType;
+  typedef typename MovingImageType::ConstPointer   MovingImageConstPointer;
+
+  /**  Type of the metric. */
+  typedef itk::ImageToImageMetric< FixedImageType,
+                              MovingImageType >    MetricType;
+  typedef typename MetricType::Pointer             MetricPointer;
+
+  /**  Type of the Transform . */
+  typedef typename MetricType::TransformType       TransformType;
+  typedef typename TransformType::Pointer          TransformPointer;
+
+  /** Type for the output: Using Decorator pattern for enabling
+   *  the Transform to be passed in the data pipeline */
+  typedef itk::DataObjectDecorator< TransformType >  TransformOutputType;
+  typedef typename TransformOutputType::Pointer      TransformOutputPointer;
+  typedef typename TransformOutputType::ConstPointer TransformOutputConstPointer;
+  
+  /**  Type of the Interpolator. */
+  typedef typename MetricType::InterpolatorType    InterpolatorType;
+  typedef typename InterpolatorType::Pointer       InterpolatorPointer;
+
+  /**  Type of the optimizer. */
+  typedef itk::SingleValuedNonLinearOptimizer           OptimizerType;
+
+  //JV replace with clitk Spatio Temporal Type
+  /** Type of the Fixed image multiresolution pyramid. */
+  typedef SpatioTemporalMultiResolutionPyramidImageFilter< FixedImageType,
+                                             FixedImageType >
+                                                   FixedImagePyramidType;
+  typedef typename FixedImagePyramidType::Pointer  FixedImagePyramidPointer;
+
+  /** Type of pyramid schedule type */
+  typedef typename FixedImagePyramidType::ScheduleType ScheduleType;
+
+  //JV replace with clitk Spatio Temporal Type
+  /** Type of the moving image multiresolution pyramid. */
+  typedef SpatioTemporalMultiResolutionPyramidImageFilter< MovingImageType,
+                                             MovingImageType >
+                                                   MovingImagePyramidType;
+  typedef typename MovingImagePyramidType::Pointer MovingImagePyramidPointer;
+
+  /** Type of the Transformation parameters This is the same type used to
+   *  represent the search space of the optimization algorithm */
+  typedef  typename MetricType::TransformParametersType    ParametersType;
+
+  /** Smart Pointer type to a DataObject. */
+  typedef typename itk::DataObject::Pointer DataObjectPointer;
+
+  /** Method that initiates the registration. */
+  void StartRegistration();
+
+  /** Method to stop the registration. */
+  void StopRegistration();
+
+  /** Set/Get the Fixed image. */
+  itkSetConstObjectMacro( FixedImage, FixedImageType );
+  itkGetConstObjectMacro( FixedImage, FixedImageType ); 
+
+  /** Set/Get the Moving image. */
+  itkSetConstObjectMacro( MovingImage, MovingImageType );
+  itkGetConstObjectMacro( MovingImage, MovingImageType );
+
+  /** Set/Get the Optimizer. */
+  itkSetObjectMacro( Optimizer,  OptimizerType );
+  itkGetObjectMacro( Optimizer,  OptimizerType );
+
+  /** Set/Get the Metric. */
+  itkSetObjectMacro( Metric, MetricType );
+  itkGetObjectMacro( Metric, MetricType );
+
+  /** Set/Get the Metric. */
+  itkSetMacro( FixedImageRegion, FixedImageRegionType );
+  itkGetConstReferenceMacro( FixedImageRegion, FixedImageRegionType );
+
+  /** Set/Get the Transfrom. */
+  itkSetObjectMacro( Transform, TransformType );
+  itkGetObjectMacro( Transform, TransformType );
+
+  /** Set/Get the Interpolator. */
+  itkSetObjectMacro( Interpolator, InterpolatorType );
+  itkGetObjectMacro( Interpolator, InterpolatorType );
+
+  /** Set/Get the Fixed image pyramid. */
+  itkSetObjectMacro( FixedImagePyramid, FixedImagePyramidType );
+  itkGetObjectMacro( FixedImagePyramid, FixedImagePyramidType ); 
+
+  /** Set/Get the Moving image pyramid. */
+  itkSetObjectMacro( MovingImagePyramid, MovingImagePyramidType );
+  itkGetObjectMacro( MovingImagePyramid, MovingImagePyramidType );
+
+  /** Set/Get the schedules . */
+  void SetSchedules( const ScheduleType & fixedSchedule,
+                    const ScheduleType & movingSchedule );
+  itkGetConstMacro( FixedImagePyramidSchedule, ScheduleType ); 
+  itkGetConstMacro( MovingImagePyramidSchedule, ScheduleType ); 
+
+  /** Set/Get the number of multi-resolution levels. */
+  void SetNumberOfLevels( unsigned long numberOfLevels );
+  itkGetMacro( NumberOfLevels, unsigned long );
+
+  /** Get the current resolution level being processed. */
+  itkGetMacro( CurrentLevel, unsigned long );
+
+  /** Set/Get the initial transformation parameters. */
+  itkSetMacro( InitialTransformParameters, ParametersType );
+  itkGetConstReferenceMacro( InitialTransformParameters, ParametersType );
+
+  /** Set/Get the initial transformation parameters of the next resolution
+   level to be processed. The default is the last set of parameters of
+   the last resolution level. */
+  itkSetMacro( InitialTransformParametersOfNextLevel, ParametersType );
+  itkGetConstReferenceMacro( InitialTransformParametersOfNextLevel, ParametersType );
+
+  /** Get the last transformation parameters visited by 
+   * the optimizer. */
+  itkGetConstReferenceMacro( LastTransformParameters, ParametersType );  
+
+  /** Returns the transform resulting from the registration process  */
+  const TransformOutputType * GetOutput() const;
+
+  /** Make a DataObject of the correct type to be used as the specified
+   * output. */
+  virtual DataObjectPointer MakeOutput(unsigned int idx);
+
+  /** Method to return the latest modified time of this object or
+   * any of its cached ivars */
+  unsigned long GetMTime() const;  
+  
+protected:
+  SpatioTemporalMultiResolutionImageRegistrationMethod();
+  virtual ~SpatioTemporalMultiResolutionImageRegistrationMethod() {};
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** Method invoked by the pipeline in order to trigger the computation of 
+   * the registration. */
+  void  GenerateData ();
+
+  /** Initialize by setting the interconnects between the components.
+      This method is executed at every level of the pyramid with the
+      values corresponding to this resolution
+   */
+  void Initialize() throw (ExceptionObject);
+
+  /** Compute the size of the fixed region for each level of the pyramid. */
+  void PreparePyramids( void );
+
+  /** Set the current level to be processed */  
+  itkSetMacro( CurrentLevel, unsigned long );
+
+private:
+  SpatioTemporalMultiResolutionImageRegistrationMethod(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+  MetricPointer                    m_Metric;
+  OptimizerType::Pointer           m_Optimizer;
+
+  MovingImageConstPointer          m_MovingImage;
+  FixedImageConstPointer           m_FixedImage;
+
+  TransformPointer                 m_Transform;
+  InterpolatorPointer              m_Interpolator;
+
+  MovingImagePyramidPointer        m_MovingImagePyramid;
+  FixedImagePyramidPointer         m_FixedImagePyramid;
+
+  ParametersType                   m_InitialTransformParameters;
+  ParametersType                   m_InitialTransformParametersOfNextLevel;
+  ParametersType                   m_LastTransformParameters;
+
+  FixedImageRegionType               m_FixedImageRegion;
+  std::vector<FixedImageRegionType>  m_FixedImageRegionPyramid;
+
+  unsigned long                    m_NumberOfLevels;
+  unsigned long                    m_CurrentLevel;
+
+  bool                             m_Stop;
+
+  ScheduleType                     m_FixedImagePyramidSchedule;
+  ScheduleType                     m_MovingImagePyramidSchedule;
+
+  bool                             m_ScheduleSpecified;
+  bool                             m_NumberOfLevelsSpecified;
+  
+};
+
+
+} // end namespace clitk
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkSpatioTemporalMultiResolutionImageRegistrationMethod.txx"
+#endif
+
+#endif
diff --git a/registration/clitkSpatioTemporalMultiResolutionImageRegistrationMethod.txx b/registration/clitkSpatioTemporalMultiResolutionImageRegistrationMethod.txx
new file mode 100644 (file)
index 0000000..d93e3b3
--- /dev/null
@@ -0,0 +1,528 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkSpatioTemporalMultiResolutionImageRegistrationMethod_txx
+#define __clitkSpatioTemporalMultiResolutionImageRegistrationMethod_txx
+#include "clitkSpatioTemporalMultiResolutionImageRegistrationMethod.h"
+#include "clitkRecursiveSpatioTemporalMultiResolutionPyramidImageFilter.h"
+
+namespace clitk
+{
+
+/**
+ * Constructor
+ */
+template < typename TFixedImage, typename TMovingImage >
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::SpatioTemporalMultiResolutionImageRegistrationMethod()
+{
+  this->SetNumberOfRequiredOutputs( 1 );  // for the Transform
+
+  m_FixedImage   = 0; // has to be provided by the user.
+  m_MovingImage  = 0; // has to be provided by the user.
+  m_Transform    = 0; // has to be provided by the user.
+  m_Interpolator = 0; // has to be provided by the user.
+  m_Metric       = 0; // has to be provided by the user.
+  m_Optimizer    = 0; // has to be provided by the user.
+
+  // Use SpatioTemporalMultiResolutionPyramidImageFilter as the default
+  // image pyramids.
+  m_FixedImagePyramid  = FixedImagePyramidType::New(); 
+  m_MovingImagePyramid = MovingImagePyramidType::New();
+
+  m_NumberOfLevels = 1;
+  m_CurrentLevel = 0;
+
+  m_Stop = false;
+
+  m_ScheduleSpecified = false;
+  m_NumberOfLevelsSpecified = false;
+
+  m_InitialTransformParameters = ParametersType(1);
+  m_InitialTransformParametersOfNextLevel = ParametersType(1);
+  m_LastTransformParameters = ParametersType(1);
+
+  m_InitialTransformParameters.Fill( 0.0f );
+  m_InitialTransformParametersOfNextLevel.Fill( 0.0f );
+  m_LastTransformParameters.Fill( 0.0f );
+
+
+  TransformOutputPointer transformDecorator = 
+                 static_cast< TransformOutputType * >( 
+                                  this->MakeOutput(0).GetPointer() );
+
+  this->ProcessObject::SetNthOutput( 0, transformDecorator.GetPointer() );
+}
+
+
+/*
+ * Initialize by setting the interconnects between components. 
+ */
+template < typename TFixedImage, typename TMovingImage >
+void
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::Initialize() throw (ExceptionObject)
+{
+
+  // Sanity checks
+  if ( !m_Metric )
+    {
+    itkExceptionMacro(<<"Metric is not present" );
+    }
+
+  if ( !m_Optimizer )
+    {
+    itkExceptionMacro(<<"Optimizer is not present" );
+    }
+
+  if( !m_Transform )
+    {
+    itkExceptionMacro(<<"Transform is not present");
+    }
+
+  if( !m_Interpolator )
+    {
+    itkExceptionMacro(<<"Interpolator is not present");
+    }
+
+  // Setup the metric
+  m_Metric->SetMovingImage( m_MovingImagePyramid->GetOutput(m_CurrentLevel) );
+  m_Metric->SetFixedImage( m_FixedImagePyramid->GetOutput(m_CurrentLevel) );
+  m_Metric->SetTransform( m_Transform );
+  m_Metric->SetInterpolator( m_Interpolator );
+  m_Metric->SetFixedImageRegion( m_FixedImageRegionPyramid[ m_CurrentLevel ] );
+  m_Metric->Initialize();
+
+  // Setup the optimizer
+  m_Optimizer->SetCostFunction( m_Metric );
+  m_Optimizer->SetInitialPosition( m_InitialTransformParametersOfNextLevel );
+
+  //
+  // Connect the transform to the Decorator.
+  //
+  TransformOutputType * transformOutput =  
+     static_cast< TransformOutputType * >( this->ProcessObject::GetOutput(0) );
+
+  transformOutput->Set( m_Transform.GetPointer() );
+
+}
+
+
+/*
+ * Stop the Registration Process
+ */
+template < typename TFixedImage, typename TMovingImage >
+void
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::StopRegistration( void )
+{
+  m_Stop = true;
+}
+
+/**
+ * Set the schedules for the fixed and moving image pyramid
+ */
+template < typename TFixedImage, typename TMovingImage >
+void
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::SetSchedules( const ScheduleType & fixedImagePyramidSchedule,
+               const ScheduleType & movingImagePyramidSchedule )
+{
+  if( m_NumberOfLevelsSpecified )
+    {
+    itkExceptionMacro( "SetSchedules should not be used " 
+           << "if numberOfLevelves are specified using SetNumberOfLevels" );
+    }
+  m_FixedImagePyramidSchedule = fixedImagePyramidSchedule;
+  m_MovingImagePyramidSchedule = movingImagePyramidSchedule;
+  m_ScheduleSpecified = true;
+
+  //Set the number of levels based on the pyramid schedule specified
+  if ( m_FixedImagePyramidSchedule.rows() != 
+        m_MovingImagePyramidSchedule.rows())
+    {
+    itkExceptionMacro("The specified schedules contain unequal number of levels");
+    }
+  else
+    {
+    m_NumberOfLevels = m_FixedImagePyramidSchedule.rows();
+    }
+
+  this->Modified();
+}
+
+/**
+ * Set the number of levels  
+ */
+template < typename TFixedImage, typename TMovingImage >
+void
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::SetNumberOfLevels( unsigned long numberOfLevels )
+{
+  if( m_ScheduleSpecified )
+    {
+    itkExceptionMacro( "SetNumberOfLevels should not be used " 
+      << "if schedules have been specified using SetSchedules method " );
+    }
+
+  m_NumberOfLevels = numberOfLevels;
+  m_NumberOfLevelsSpecified = true;
+  this->Modified();
+}
+
+/**
+ * Stop the Registration Process
+ */
+template < typename TFixedImage, typename TMovingImage >
+void
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::PreparePyramids( void )
+{
+
+  if( !m_Transform )
+    {
+    itkExceptionMacro(<<"Transform is not present");
+    }
+
+  m_InitialTransformParametersOfNextLevel = m_InitialTransformParameters;
+
+  if ( m_InitialTransformParametersOfNextLevel.Size() != 
+       m_Transform->GetNumberOfParameters() )
+    {
+    itkExceptionMacro(<<"Size mismatch between initial parameter and transform"); 
+    }
+
+  // Sanity checks
+  if( !m_FixedImage )
+    {
+    itkExceptionMacro(<<"FixedImage is not present");
+    }
+
+  if( !m_MovingImage )
+    {
+    itkExceptionMacro(<<"MovingImage is not present");
+    }
+
+  if( !m_FixedImagePyramid )
+    {
+    itkExceptionMacro(<<"Fixed image pyramid is not present");
+    }
+
+  if( !m_MovingImagePyramid )
+    {
+    itkExceptionMacro(<<"Moving image pyramid is not present");
+    }
+
+  // Setup the fixed and moving image pyramid
+  if( m_NumberOfLevelsSpecified )
+    {
+    m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+    m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+    }
+
+  if( m_ScheduleSpecified )
+    {
+    m_FixedImagePyramid->SetNumberOfLevels( m_FixedImagePyramidSchedule.rows());
+    m_FixedImagePyramid->SetSchedule( m_FixedImagePyramidSchedule );
+
+    m_MovingImagePyramid->SetNumberOfLevels( m_MovingImagePyramidSchedule.rows());
+    m_MovingImagePyramid->SetSchedule( m_MovingImagePyramidSchedule );
+    }
+
+  m_FixedImagePyramid->SetInput( m_FixedImage );
+  m_FixedImagePyramid->UpdateLargestPossibleRegion();
+
+  // Setup the moving image pyramid
+  m_MovingImagePyramid->SetInput( m_MovingImage );
+  m_MovingImagePyramid->UpdateLargestPossibleRegion();
+
+  typedef typename FixedImageRegionType::SizeType         SizeType;
+  typedef typename FixedImageRegionType::IndexType        IndexType;
+
+  ScheduleType schedule = m_FixedImagePyramid->GetSchedule();
+  std::cout << "FixedImage schedule: " << schedule << std::endl;
+
+  ScheduleType movingschedule = m_MovingImagePyramid->GetSchedule();
+  std::cout << "MovingImage schedule: " << movingschedule << std::endl;
+
+  SizeType  inputSize  = m_FixedImageRegion.GetSize();
+  IndexType inputStart = m_FixedImageRegion.GetIndex();
+
+  const unsigned long numberOfLevels = 
+          m_FixedImagePyramid->GetNumberOfLevels(); 
+
+  m_FixedImageRegionPyramid.reserve( numberOfLevels );
+  m_FixedImageRegionPyramid.resize( numberOfLevels );
+
+  // Compute the FixedImageRegion corresponding to each level of the 
+  // pyramid. This uses the same algorithm of the ShrinkImageFilter 
+  // since the regions should be compatible. 
+  for ( unsigned int level=0; level < numberOfLevels; level++ )
+    {
+    SizeType  size;
+    IndexType start;
+    for ( unsigned int dim = 0; dim < TFixedImage::ImageDimension; dim++)
+      {
+      const float scaleFactor = static_cast<float>( schedule[ level ][ dim ] );
+
+      size[ dim ] = static_cast<typename SizeType::SizeValueType>(
+        vcl_floor(static_cast<float>( inputSize[ dim ] ) / scaleFactor ) );
+      if( size[ dim ] < 1 )
+        {
+        size[ dim ] = 1;
+        }
+      
+      start[ dim ] = static_cast<typename IndexType::IndexValueType>(
+        vcl_ceil(static_cast<float>( inputStart[ dim ] ) / scaleFactor ) ); 
+      }
+    m_FixedImageRegionPyramid[ level ].SetSize( size );
+    m_FixedImageRegionPyramid[ level ].SetIndex( start );
+    }
+
+}
+
+/*
+ * Starts the Registration Process
+ */
+template < typename TFixedImage, typename TMovingImage >
+void
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::StartRegistration( void )
+{ 
+
+  // StartRegistration is an old API from before
+  // this egistrationMethod was a subclass of ProcessObject.
+  // Historically, one could call StartRegistration() instead of
+  // calling Update().  However, when called directly by the user, the
+  // inputs to the RegistrationMethod may not be up to date.  This
+  // may cause an unexpected behavior.
+  //
+  // Since we cannot eliminate StartRegistration for backward
+  // compability reasons, we check whether StartRegistration was
+  // called directly or whether Update() (which in turn called 
+  // StartRegistration()).
+  if (!m_Updating)
+    {
+    this->Update();
+    }
+  else
+    {
+    m_Stop = false;
+    
+    this->PreparePyramids();
+    
+    for ( m_CurrentLevel = 0; m_CurrentLevel < m_NumberOfLevels;
+          m_CurrentLevel++ )
+      {
+      
+      // Invoke an iteration event.
+      // This allows a UI to reset any of the components between
+      // resolution level.
+      this->InvokeEvent( IterationEvent() );
+      
+      // Check if there has been a stop request
+      if ( m_Stop ) 
+        {
+        break;
+        }
+      
+      try
+        {
+        // initialize the interconnects between components
+        this->Initialize();
+        }
+      catch( ExceptionObject& err )
+        {
+        m_LastTransformParameters = ParametersType(1);
+        m_LastTransformParameters.Fill( 0.0f );
+        
+        // pass exception to caller
+        throw err;
+        }
+      
+      try
+        {
+        // do the optimization
+        m_Optimizer->StartOptimization();
+        }
+      catch( ExceptionObject& err )
+        {
+        // An error has occurred in the optimization.
+        // Update the parameters
+        m_LastTransformParameters = m_Optimizer->GetCurrentPosition();
+        
+        // Pass exception to caller
+        throw err;
+        }
+      
+      // get the results
+      m_LastTransformParameters = m_Optimizer->GetCurrentPosition();
+      m_Transform->SetParameters( m_LastTransformParameters );
+      
+      // setup the initial parameters for next level
+      if ( m_CurrentLevel < m_NumberOfLevels - 1 )
+        {
+        m_InitialTransformParametersOfNextLevel =
+          m_LastTransformParameters;
+        }
+      }
+    }
+
+}
+
+
+/*
+ * PrintSelf
+ */
+template < typename TFixedImage, typename TMovingImage >
+void
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf( os, indent );
+  os << indent << "Metric: " << m_Metric.GetPointer() << std::endl;
+  os << indent << "Optimizer: " << m_Optimizer.GetPointer() << std::endl;
+  os << indent << "Transform: " << m_Transform.GetPointer() << std::endl;
+  os << indent << "Interpolator: " << m_Interpolator.GetPointer() << std::endl;
+  os << indent << "FixedImage: " << m_FixedImage.GetPointer() << std::endl;
+  os << indent << "MovingImage: " << m_MovingImage.GetPointer() << std::endl;
+  os << indent << "FixedImagePyramid: ";
+  os << m_FixedImagePyramid.GetPointer() << std::endl;
+  os << indent << "MovingImagePyramid: ";
+  os << m_MovingImagePyramid.GetPointer() << std::endl;
+
+  os << indent << "NumberOfLevels: ";
+  os << m_NumberOfLevels << std::endl;
+
+  os << indent << "CurrentLevel: ";
+  os << m_CurrentLevel << std::endl;  
+
+  os << indent << "InitialTransformParameters: ";
+  os << m_InitialTransformParameters << std::endl;
+  os << indent << "InitialTransformParametersOfNextLevel: ";
+  os << m_InitialTransformParametersOfNextLevel << std::endl;
+  os << indent << "LastTransformParameters: ";
+  os << m_LastTransformParameters << std::endl;
+  os << indent << "FixedImageRegion: ";
+  os << m_FixedImageRegion << std::endl;
+  for(unsigned int level=0; level< m_FixedImageRegionPyramid.size(); level++)
+    {
+    os << indent << "FixedImageRegion at level " << level << ": ";
+    os << m_FixedImageRegionPyramid[level] << std::endl;
+    }
+  os << indent << "FixedImagePyramidSchedule : " << std::endl;
+  os << m_FixedImagePyramidSchedule << std::endl;
+  os << indent << "MovingImagePyramidSchedule : " << std::endl;
+  os << m_MovingImagePyramidSchedule << std::endl;
+
+}
+
+
+/*
+ * Generate Data
+ */
+template < typename TFixedImage, typename TMovingImage >
+void
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::GenerateData()
+{
+  this->StartRegistration();
+}
+
+template < typename TFixedImage, typename TMovingImage >
+unsigned long
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::GetMTime() const
+{
+  unsigned long mtime = Superclass::GetMTime();
+  unsigned long m;
+
+
+  // Some of the following should be removed once ivars are put in the
+  // input and output lists
+  
+  if (m_Transform)
+    {
+    m = m_Transform->GetMTime();
+    mtime = (m > mtime ? m : mtime);
+    }
+
+  if (m_Interpolator)
+    {
+    m = m_Interpolator->GetMTime();
+    mtime = (m > mtime ? m : mtime);
+    }
+
+  if (m_Metric)
+    {
+    m = m_Metric->GetMTime();
+    mtime = (m > mtime ? m : mtime);
+    }
+
+  if (m_Optimizer)
+    {
+    m = m_Optimizer->GetMTime();
+    mtime = (m > mtime ? m : mtime);
+    }
+
+  if (m_FixedImage)
+    {
+    m = m_FixedImage->GetMTime();
+    mtime = (m > mtime ? m : mtime);
+    }
+
+  if (m_MovingImage)
+    {
+    m = m_MovingImage->GetMTime();
+    mtime = (m > mtime ? m : mtime);
+    }
+
+  return mtime;
+  
+}
+
+/*
+ *  Get Output
+ */
+template < typename TFixedImage, typename TMovingImage >
+const typename SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>::TransformOutputType *
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::GetOutput() const
+{
+  return static_cast< const TransformOutputType * >( this->ProcessObject::GetOutput(0) );
+}
+
+template < typename TFixedImage, typename TMovingImage >
+DataObject::Pointer
+SpatioTemporalMultiResolutionImageRegistrationMethod<TFixedImage,TMovingImage>
+::MakeOutput(unsigned int output)
+{
+  switch (output)
+    {
+    case 0:
+      return static_cast<DataObject*>(TransformOutputType::New().GetPointer());
+      break;
+    default:
+      itkExceptionMacro("MakeOutput request for an output number larger than the expected number of outputs");
+      return 0;
+    }
+}
+
+} // end namespace clitk
+
+
+#endif
diff --git a/registration/clitkSpatioTemporalMultiResolutionPyramidImageFilter.h b/registration/clitkSpatioTemporalMultiResolutionPyramidImageFilter.h
new file mode 100644 (file)
index 0000000..ca4a001
--- /dev/null
@@ -0,0 +1,162 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkSpatioTemporalMultiResolutionPyramidImageFilter_h
+#define __clitkSpatioTemporalMultiResolutionPyramidImageFilter_h
+#include "itkImageToImageFilter.h"
+#include "itkArray2D.h"
+
+namespace clitk
+{
+
+template <  class TInputImage,  class TOutputImage  >
+class ITK_EXPORT SpatioTemporalMultiResolutionPyramidImageFilter : 
+    public itk::ImageToImageFilter< TInputImage, TOutputImage >
+{
+
+public:
+  /** Standard class typedefs. */
+  typedef SpatioTemporalMultiResolutionPyramidImageFilter             Self;
+  typedef itk::ImageToImageFilter<TInputImage,TOutputImage>  Superclass;
+  typedef itk::SmartPointer<Self>                            Pointer;
+  typedef itk::SmartPointer<const Self>                      ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(SpatioTemporalMultiResolutionPyramidImageFilter, ImageToImageFilter);
+
+  /** ScheduleType typedef support. */
+  typedef itk::Array2D<unsigned int>  ScheduleType;
+
+  /** ImageDimension enumeration. */
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      TInputImage::ImageDimension);
+  itkStaticConstMacro(OutputImageDimension, unsigned int,
+                      TOutputImage::ImageDimension);
+
+  /** Inherit types from Superclass. */
+  typedef typename Superclass::InputImageType         InputImageType;
+  typedef typename Superclass::OutputImageType        OutputImageType;
+  typedef typename Superclass::InputImagePointer      InputImagePointer;
+  typedef typename Superclass::OutputImagePointer     OutputImagePointer;
+  typedef typename Superclass::InputImageConstPointer InputImageConstPointer;
+
+  /** Set the number of multi-resolution levels. The matrix containing the
+   * schedule will be resized accordingly.  The schedule is populated with
+   * default values.  At the coarset (0) level, the shrink factors are set
+   * 2^(nlevel - 1) for all dimension. These shrink factors are halved for
+   * subsequent levels.  The number of levels is clamped to a minimum value
+   * of 1.  All shrink factors are also clamped to a minimum value of 1. */
+  virtual void SetNumberOfLevels(unsigned int num);
+
+  /** Get the number of multi-resolution levels. */
+  itkGetConstMacro(NumberOfLevels, unsigned int);
+
+  /** Set a multi-resolution schedule.  The input schedule must have only
+   * ImageDimension number of columns and NumberOfLevels number of rows.  For
+   * each dimension, the shrink factor must be non-increasing with respect to
+   * subsequent levels. This function will clamp shrink factors to satisify
+   * this condition.  All shrink factors less than one will also be clamped
+   * to the value of 1. */
+  virtual void SetSchedule( const ScheduleType& schedule );
+
+  /** Get the multi-resolution schedule. */
+  itkGetConstReferenceMacro(Schedule, ScheduleType);
+
+  /** Set the starting shrink factor for the coarset (0) resolution
+   * level. The schedule is then populated with defaults values obtained by
+   * halving the factors at the previous level.  All shrink factors are
+   * clamped to a minimum value of 1. */
+  virtual void SetStartingShrinkFactors( unsigned int factor );
+  virtual void SetStartingShrinkFactors( unsigned int* factors );
+
+  /** Get the starting shrink factors */
+  const unsigned int * GetStartingShrinkFactors() const;
+
+  /** Test if the schedule is downward divisible. This method returns true if
+   * at every level, the shrink factors are divisble by the shrink factors at
+   * the next level. */
+  static bool IsScheduleDownwardDivisible( const ScheduleType& schedule );
+
+  /** MultiResolutionPyramidImageFilter produces images which are of
+   * different resolution and different pixel spacing than its input image.
+   * As such, MultiResolutionPyramidImageFilter needs to provide an
+   * implementation for GenerateOutputInformation() in order to inform the
+   * pipeline execution model.  The original documentation of this method is
+   * below.  \sa ProcessObject::GenerateOutputInformaton() */
+  virtual void GenerateOutputInformation();
+
+  /** Given one output whose requested region has been set, this method sets
+   * the requested region for the remaining output images.  The original
+   * documentation of this method is below.  \sa
+   * ProcessObject::GenerateOutputRequestedRegion(); */
+  virtual void GenerateOutputRequestedRegion(itk::DataObject *output);
+
+  /** MultiResolutionPyramidImageFilter requires a larger input requested
+   * region than the output requested regions to accomdate the shrinkage and
+   * smoothing operations. As such, MultiResolutionPyramidImageFilter needs
+   * to provide an implementation for GenerateInputRequestedRegion().  The
+   * original documentation of this method is below.  \sa
+   * ProcessObject::GenerateInputRequestedRegion() */
+  virtual void GenerateInputRequestedRegion();
+
+  itkSetMacro(MaximumError,double);
+  itkGetConstReferenceMacro(MaximumError,double);
+
+  itkSetMacro(UseShrinkImageFilter,bool);
+  itkGetConstMacro(UseShrinkImageFilter,bool);
+  itkBooleanMacro(UseShrinkImageFilter);
+  
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+  /** Begin concept checking */
+  itkConceptMacro(SameDimensionCheck,
+    (itk::Concept::SameDimension<ImageDimension, OutputImageDimension>));
+  itkConceptMacro(OutputHasNumericTraitsCheck,
+    (itk::Concept::HasNumericTraits<typename TOutputImage::PixelType>));
+  /** End concept checking */
+#endif
+
+protected:
+  SpatioTemporalMultiResolutionPyramidImageFilter();
+  ~SpatioTemporalMultiResolutionPyramidImageFilter() {};
+  void PrintSelf(std::ostream&os, itk::Indent indent) const;
+
+  /** Generate the output data. */
+  void GenerateData();
+
+  double          m_MaximumError; 
+  unsigned int    m_NumberOfLevels;
+  ScheduleType    m_Schedule;
+  bool            m_UseShrinkImageFilter;
+
+private:
+  SpatioTemporalMultiResolutionPyramidImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+};
+
+
+} // namespace clitk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkSpatioTemporalMultiResolutionPyramidImageFilter.txx"
+#endif
+
+#endif
diff --git a/registration/clitkSpatioTemporalMultiResolutionPyramidImageFilter.txx b/registration/clitkSpatioTemporalMultiResolutionPyramidImageFilter.txx
new file mode 100644 (file)
index 0000000..55e599c
--- /dev/null
@@ -0,0 +1,629 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkSpatioTemporalMultiResolutionPyramidImageFilter_txx
+#define __clitkSpatioTemporalMultiResolutionPyramidImageFilter_txx
+#include "clitkSpatioTemporalMultiResolutionPyramidImageFilter.h"
+#include "itkGaussianOperator.h"
+#include "itkCastImageFilter.h"
+#include "itkDiscreteGaussianImageFilter.h"
+#include "itkExceptionObject.h"
+#include "itkResampleImageFilter.h"
+#include "itkShrinkImageFilter.h"
+#include "itkIdentityTransform.h"
+
+#include "vnl/vnl_math.h"
+
+namespace clitk
+{
+
+/**
+ * Constructor
+ */
+template <class TInputImage, class TOutputImage>
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::SpatioTemporalMultiResolutionPyramidImageFilter()
+{
+  m_NumberOfLevels = 0;
+  this->SetNumberOfLevels( 2 );
+  m_MaximumError = 0.1;
+  m_UseShrinkImageFilter = false;
+}
+
+
+/**
+ * Set the number of computation levels
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::SetNumberOfLevels(
+  unsigned int num )
+{
+  if( m_NumberOfLevels == num )
+    {
+    return;
+    }
+
+  this->Modified();
+
+  // clamp value to be at least one
+  m_NumberOfLevels = num;
+  if( m_NumberOfLevels < 1 ) m_NumberOfLevels = 1;
+
+  // resize the schedules
+  ScheduleType temp( m_NumberOfLevels, ImageDimension );
+  temp.Fill( 0 );
+  m_Schedule = temp;
+
+  // determine initial shrink factor
+  unsigned int startfactor = 1;
+  startfactor = startfactor << ( m_NumberOfLevels - 1 );
+
+  // set the starting shrink factors
+  this->SetStartingShrinkFactors( startfactor );
+
+  // set the required number of outputs
+  this->SetNumberOfRequiredOutputs( m_NumberOfLevels );
+
+  unsigned int numOutputs = static_cast<unsigned int>( this->GetNumberOfOutputs() );
+  unsigned int idx;
+  if( numOutputs < m_NumberOfLevels )
+    {
+    // add extra outputs
+    for( idx = numOutputs; idx < m_NumberOfLevels; idx++ )
+      {
+      typename itk::DataObject::Pointer output =
+        this->MakeOutput( idx );
+      this->SetNthOutput( idx, output.GetPointer() );
+      }
+
+    }
+  else if( numOutputs > m_NumberOfLevels )
+    {
+    // remove extra outputs
+    for( idx = m_NumberOfLevels; idx < numOutputs; idx++ )
+      {
+      typename itk::DataObject::Pointer output =
+        this->GetOutputs()[idx];
+      this->RemoveOutput( output );
+      }
+    }
+
+}
+
+
+/*
+ * Set the starting shrink factors
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::SetStartingShrinkFactors(
+  unsigned int factor )
+{
+
+  unsigned int array[ImageDimension];
+  //JV temporal dimension always 1
+  for( unsigned int dim = 0; dim < ImageDimension-1; ++dim )
+    {
+    array[dim] = factor;
+    }
+  array[ImageDimension-1]=1;
+
+  this->SetStartingShrinkFactors( array );
+
+}
+
+
+/**
+ * Set the starting shrink factors
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::SetStartingShrinkFactors(
+  unsigned int * factors )
+{
+
+  for( unsigned int dim = 0; dim < ImageDimension-1; ++dim )
+    {
+    m_Schedule[0][dim] = factors[dim];
+    if( m_Schedule[0][dim] == 0 )
+      {
+      m_Schedule[0][dim] = 1;
+      }
+    }
+  //JV temporal dimension always 1
+  m_Schedule[0][ImageDimension-1]=1;
+
+  for( unsigned int level = 1; level < m_NumberOfLevels; ++level )
+    {
+      //JV temporal dimension always 1
+      for( unsigned int dim = 0; dim < ImageDimension-1; ++dim )
+          {
+         m_Schedule[level][dim] = m_Schedule[level-1][dim] / 2;
+         if( m_Schedule[level][dim] == 0 )
+           {
+             m_Schedule[level][dim] = 1;
+           }
+       }
+      m_Schedule[level][ImageDimension-1]=1;
+    }
+
+  this->Modified();
+
+}
+
+
+/*
+ * Get the starting shrink factors
+ */
+template <class TInputImage, class TOutputImage>
+const unsigned int *
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::GetStartingShrinkFactors() const
+{
+  return ( m_Schedule.data_block() );
+}
+
+
+/*
+ * Set the multi-resolution schedule
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::SetSchedule(
+  const ScheduleType& schedule )
+{
+
+  if( schedule.rows() != m_NumberOfLevels ||
+      schedule.columns() != ImageDimension )
+    {
+    itkDebugMacro(<< "Schedule has wrong dimensions" );
+    return;
+    }
+
+  if( schedule == m_Schedule )
+    {
+    return;
+    }
+
+  this->Modified();
+  unsigned int level, dim;
+  for( level = 0; level < m_NumberOfLevels; level++ )
+    {
+      //JV temporal dimension always 1
+      for( dim = 0; dim < ImageDimension-1; dim++ )
+       {
+         
+         m_Schedule[level][dim] = schedule[level][dim];
+
+         // set schedule to max( 1, min(schedule[level],
+         //  schedule[level-1] );
+         if( level > 0 )
+           {
+             m_Schedule[level][dim] = vnl_math_min( m_Schedule[level][dim], m_Schedule[level-1][dim] );
+           }
+         
+         if( m_Schedule[level][dim] < 1 )
+           {
+             m_Schedule[level][dim] = 1;
+           }
+       }
+      m_Schedule[level][ImageDimension-1]=1;
+    }
+}
+
+
+/*
+ * Is the schedule downward divisible ?
+ */
+template <class TInputImage, class TOutputImage>
+bool
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::IsScheduleDownwardDivisible( const ScheduleType& schedule )
+{
+
+  unsigned int ilevel, idim;
+  for( ilevel = 0; ilevel < schedule.rows() - 1; ilevel++ )
+    {
+    for( idim = 0; idim < schedule.columns(); idim++ )
+      {
+      if( schedule[ilevel][idim] == 0 )
+        {
+        return false;
+        }
+      if( ( schedule[ilevel][idim] % schedule[ilevel+1][idim] ) > 0 )
+        {
+        return false;
+        }
+      }
+    }
+
+  return true;
+}
+
+/*
+ * GenerateData for non downward divisible schedules
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::GenerateData()
+{
+  // Get the input and output pointers
+  InputImageConstPointer  inputPtr = this->GetInput();
+
+  // Create caster, smoother and resampleShrinker filters
+  typedef itk::CastImageFilter<TInputImage, TOutputImage>              CasterType;
+  typedef itk::DiscreteGaussianImageFilter<TOutputImage, TOutputImage> SmootherType;
+
+  typedef itk::ImageToImageFilter<TOutputImage,TOutputImage>           ImageToImageType;
+  typedef itk::ResampleImageFilter<TOutputImage,TOutputImage>          ResampleShrinkerType;
+  typedef itk::ShrinkImageFilter<TOutputImage,TOutputImage>            ShrinkerType;
+
+  typename CasterType::Pointer caster = CasterType::New();
+  typename SmootherType::Pointer smoother = SmootherType::New();
+
+  typename ImageToImageType::Pointer shrinkerFilter;
+  //
+  // only one of these pointers is going to be valid, depending on the
+  // value of UseShrinkImageFilter flag
+  typename ResampleShrinkerType::Pointer resampleShrinker;
+  typename ShrinkerType::Pointer shrinker;
+
+  if(this->GetUseShrinkImageFilter())
+    {
+    shrinker = ShrinkerType::New();
+    shrinkerFilter = shrinker.GetPointer();
+    }
+  else
+    {
+    resampleShrinker = ResampleShrinkerType::New();
+    typedef itk::LinearInterpolateImageFunction< OutputImageType, double >
+      LinearInterpolatorType;
+    typename LinearInterpolatorType::Pointer interpolator = 
+      LinearInterpolatorType::New();
+    resampleShrinker->SetInterpolator( interpolator );
+    resampleShrinker->SetDefaultPixelValue( 0 );
+    shrinkerFilter = resampleShrinker.GetPointer();
+    }
+  // Setup the filters
+  caster->SetInput( inputPtr );
+
+  smoother->SetUseImageSpacing( false );
+  smoother->SetInput( caster->GetOutput() );
+  smoother->SetMaximumError( m_MaximumError );
+
+  shrinkerFilter->SetInput( smoother->GetOutput() );
+
+  unsigned int ilevel, idim;
+  unsigned int factors[ImageDimension];
+  double       variance[ImageDimension];
+
+  for( ilevel = 0; ilevel < m_NumberOfLevels; ilevel++ )
+    {
+    this->UpdateProgress( static_cast<float>( ilevel ) /
+                          static_cast<float>( m_NumberOfLevels ) );
+
+    // Allocate memory for each output
+    OutputImagePointer outputPtr = this->GetOutput( ilevel );
+    outputPtr->SetBufferedRegion( outputPtr->GetRequestedRegion() );
+    outputPtr->Allocate();
+
+    // compute shrink factors and variances
+    for( idim = 0; idim < ImageDimension; idim++ )
+      {
+      factors[idim] = m_Schedule[ilevel][idim];
+      variance[idim] = vnl_math_sqr( 0.5 *
+                                     static_cast<float>( factors[idim] ) );
+      }
+
+    if(!this->GetUseShrinkImageFilter())
+      {
+      typedef itk::IdentityTransform<double,OutputImageType::ImageDimension> 
+        IdentityTransformType;
+      typename IdentityTransformType::Pointer identityTransform =
+        IdentityTransformType::New();
+      resampleShrinker->SetOutputParametersFromImage( outputPtr );
+      resampleShrinker->SetTransform(identityTransform);
+      }
+    else
+      {
+      shrinker->SetShrinkFactors(factors);
+      }
+    // use mini-pipeline to compute output
+    smoother->SetVariance( variance );
+
+    shrinkerFilter->GraftOutput( outputPtr );
+
+    // force to always update in case shrink factors are the same
+    shrinkerFilter->Modified();
+    shrinkerFilter->UpdateLargestPossibleRegion();
+    this->GraftNthOutput( ilevel, shrinkerFilter->GetOutput() );
+    }
+}
+
+/**
+ * PrintSelf method
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os,indent);
+
+  os << indent << "MaximumError: " << m_MaximumError << std::endl;
+  os << indent << "No. levels: " << m_NumberOfLevels << std::endl;
+  os << indent << "Schedule: " << std::endl;
+  os << m_Schedule << std::endl;
+  os << "Use ShrinkImageFilter= " << m_UseShrinkImageFilter << std::endl;
+}
+
+
+/*
+ * GenerateOutputInformation
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::GenerateOutputInformation()
+{
+
+  // call the superclass's implementation of this method
+  Superclass::GenerateOutputInformation();
+
+  // get pointers to the input and output
+  InputImageConstPointer inputPtr = this->GetInput();
+
+  if ( !inputPtr  )
+    {
+    itkExceptionMacro( << "Input has not been set" );
+    }
+
+  const typename InputImageType::PointType&
+    inputOrigin = inputPtr->GetOrigin();
+  const typename InputImageType::SpacingType&
+    inputSpacing = inputPtr->GetSpacing();
+  const typename InputImageType::DirectionType&
+    inputDirection = inputPtr->GetDirection();
+  const typename InputImageType::SizeType& inputSize =
+    inputPtr->GetLargestPossibleRegion().GetSize();
+  const typename InputImageType::IndexType& inputStartIndex =
+    inputPtr->GetLargestPossibleRegion().GetIndex();
+
+  typedef typename OutputImageType::SizeType  SizeType;
+  typedef typename SizeType::SizeValueType    SizeValueType;
+  typedef typename OutputImageType::IndexType IndexType;
+  typedef typename IndexType::IndexValueType  IndexValueType;
+
+  OutputImagePointer outputPtr;
+  typename OutputImageType::PointType   outputOrigin;
+  typename OutputImageType::SpacingType outputSpacing;
+  SizeType    outputSize;
+  IndexType   outputStartIndex;
+
+  // we need to compute the output spacing, the output image size,
+  // and the output image start index
+  for(unsigned int ilevel = 0; ilevel < m_NumberOfLevels; ilevel++ )
+    {
+    outputPtr = this->GetOutput( ilevel );
+    if( !outputPtr ) { continue; }
+
+    for(unsigned int idim = 0; idim < OutputImageType::ImageDimension; idim++ )
+      {
+      const double shrinkFactor = static_cast<double>( m_Schedule[ilevel][idim] );
+      outputSpacing[idim] = inputSpacing[idim] * shrinkFactor;
+
+      outputSize[idim] = static_cast<SizeValueType>(
+        vcl_floor(static_cast<double>(inputSize[idim]) / shrinkFactor ) );
+      if( outputSize[idim] < 1 ) { outputSize[idim] = 1; }
+
+      outputStartIndex[idim] = static_cast<IndexValueType>(
+        vcl_ceil(static_cast<double>(inputStartIndex[idim]) / shrinkFactor ) );
+      }
+    //Now compute the new shifted origin for the updated levels;
+    const typename OutputImageType::PointType::VectorType outputOriginOffset
+         =(inputDirection*(outputSpacing-inputSpacing))*0.5;
+    for(unsigned int idim = 0; idim < OutputImageType::ImageDimension; idim++ )
+      {
+        outputOrigin[idim]=inputOrigin[idim]+outputOriginOffset[idim];
+      }
+
+    typename OutputImageType::RegionType outputLargestPossibleRegion;
+    outputLargestPossibleRegion.SetSize( outputSize );
+    outputLargestPossibleRegion.SetIndex( outputStartIndex );
+
+    outputPtr->SetLargestPossibleRegion( outputLargestPossibleRegion );
+    outputPtr->SetOrigin ( outputOrigin );
+    outputPtr->SetSpacing( outputSpacing );
+    outputPtr->SetDirection( inputDirection );//Output Direction should be same as input.
+    }
+}
+
+
+/*
+ * GenerateOutputRequestedRegion
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::GenerateOutputRequestedRegion(itk::DataObject * refOutput )
+{
+  // call the superclass's implementation of this method
+  Superclass::GenerateOutputRequestedRegion( refOutput );
+
+  // find the index for this output
+  unsigned int refLevel = refOutput->GetSourceOutputIndex();
+
+  // compute baseIndex and baseSize
+  typedef typename OutputImageType::SizeType    SizeType;
+  typedef typename SizeType::SizeValueType      SizeValueType;
+  typedef typename OutputImageType::IndexType   IndexType;
+  typedef typename IndexType::IndexValueType    IndexValueType;
+  typedef typename OutputImageType::RegionType  RegionType;
+
+  TOutputImage * ptr = static_cast<TOutputImage*>( refOutput );
+  if( !ptr )
+    {
+    itkExceptionMacro( << "Could not cast refOutput to TOutputImage*." );
+    }
+
+  unsigned int ilevel, idim;
+
+  if ( ptr->GetRequestedRegion() == ptr->GetLargestPossibleRegion() )
+    {
+    // set the requested regions for the other outputs to their
+    // requested region
+
+    for( ilevel = 0; ilevel < m_NumberOfLevels; ilevel++ )
+      {
+      if( ilevel == refLevel ) { continue; }
+      if( !this->GetOutput(ilevel) ) { continue; }
+      this->GetOutput(ilevel)->SetRequestedRegionToLargestPossibleRegion();
+      }
+    }
+  else
+    {
+    // compute requested regions for the other outputs based on
+    // the requested region of the reference output
+    IndexType outputIndex;
+    SizeType  outputSize;
+    RegionType outputRegion;
+    IndexType  baseIndex = ptr->GetRequestedRegion().GetIndex();
+    SizeType   baseSize  = ptr->GetRequestedRegion().GetSize();
+
+    for( idim = 0; idim < TOutputImage::ImageDimension; idim++ )
+      {
+      unsigned int factor = m_Schedule[refLevel][idim];
+      baseIndex[idim] *= static_cast<IndexValueType>( factor );
+      baseSize[idim] *= static_cast<SizeValueType>( factor );
+      }
+
+    for( ilevel = 0; ilevel < m_NumberOfLevels; ilevel++ )
+      {
+      if( ilevel == refLevel ) { continue; }
+      if( !this->GetOutput(ilevel) ) { continue; }
+
+      for( idim = 0; idim < TOutputImage::ImageDimension; idim++ )
+        {
+
+        double factor = static_cast<double>( m_Schedule[ilevel][idim] );
+
+        outputSize[idim] = static_cast<SizeValueType>(
+          vcl_floor(static_cast<double>(baseSize[idim]) / factor ) );
+        if( outputSize[idim] < 1 ) { outputSize[idim] = 1; }
+
+        outputIndex[idim] = static_cast<IndexValueType>(
+          vcl_ceil(static_cast<double>(baseIndex[idim]) / factor ) );
+
+        }
+
+      outputRegion.SetIndex( outputIndex );
+      outputRegion.SetSize( outputSize );
+
+      // make sure the region is within the largest possible region
+      outputRegion.Crop( this->GetOutput( ilevel )->
+                         GetLargestPossibleRegion() );
+      // set the requested region
+      this->GetOutput( ilevel )->SetRequestedRegion( outputRegion );
+      }
+
+    }
+}
+
+
+/**
+ * GenerateInputRequestedRegion
+ */
+template <class TInputImage, class TOutputImage>
+void
+SpatioTemporalMultiResolutionPyramidImageFilter<TInputImage, TOutputImage>
+::GenerateInputRequestedRegion()
+{
+  // call the superclass' implementation of this method
+  Superclass::GenerateInputRequestedRegion();
+
+  // get pointers to the input and output
+  InputImagePointer  inputPtr =
+    const_cast< InputImageType * >( this->GetInput() );
+  if ( !inputPtr )
+    {
+    itkExceptionMacro( << "Input has not been set." );
+    }
+
+  // compute baseIndex and baseSize
+  typedef typename OutputImageType::SizeType    SizeType;
+  typedef typename SizeType::SizeValueType      SizeValueType;
+  typedef typename OutputImageType::IndexType   IndexType;
+  typedef typename IndexType::IndexValueType    IndexValueType;
+  typedef typename OutputImageType::RegionType  RegionType;
+
+  unsigned int refLevel = m_NumberOfLevels - 1;
+  SizeType baseSize = this->GetOutput(refLevel)->GetRequestedRegion().GetSize();
+  IndexType baseIndex = this->GetOutput(refLevel)->GetRequestedRegion().GetIndex();
+  RegionType baseRegion;
+
+  unsigned int idim;
+  for( idim = 0; idim < ImageDimension; idim++ )
+    {
+    unsigned int factor = m_Schedule[refLevel][idim];
+    baseIndex[idim] *= static_cast<IndexValueType>( factor );
+    baseSize[idim] *= static_cast<SizeValueType>( factor );
+    }
+  baseRegion.SetIndex( baseIndex );
+  baseRegion.SetSize( baseSize );
+
+  // compute requirements for the smoothing part
+  typedef typename TOutputImage::PixelType                 OutputPixelType;
+  typedef typename itk::GaussianOperator<OutputPixelType,ImageDimension> OperatorType;
+
+  OperatorType *oper = new OperatorType;
+
+  typename TInputImage::SizeType radius;
+
+  RegionType inputRequestedRegion = baseRegion;
+  refLevel = 0;
+
+  for( idim = 0; idim < TInputImage::ImageDimension; idim++ )
+    {
+    oper->SetDirection(idim);
+    oper->SetVariance( vnl_math_sqr( 0.5 * static_cast<float>(
+                                       m_Schedule[refLevel][idim] ) ) );
+    oper->SetMaximumError( m_MaximumError );
+    oper->CreateDirectional();
+    radius[idim] = oper->GetRadius()[idim];
+    }
+  delete oper;
+
+  inputRequestedRegion.PadByRadius( radius );
+
+  // make sure the requested region is within the largest possible
+  inputRequestedRegion.Crop( inputPtr->GetLargestPossibleRegion() );
+
+  // set the input requested region
+  inputPtr->SetRequestedRegion( inputRequestedRegion );
+
+}
+
+
+} // namespace clitk
+
+#endif
diff --git a/registration/clitkTransformToDeformationFieldSource.h b/registration/clitkTransformToDeformationFieldSource.h
new file mode 100644 (file)
index 0000000..2e0a101
--- /dev/null
@@ -0,0 +1,223 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkTransformToDeformationFieldSource_h
+#define __clitkTransformToDeformationFieldSource_h
+#include "itkTransform.h"
+#include "itkImageSource.h"
+
+namespace clitk
+{
+
+/** \class TransformToDeformationFieldSource
+ * \brief Generate a deformation field from a coordinate transform
+ *
+ * This class was inspired on an the itkDeformationFieldImageFilter class.
+ *
+ * Output information (spacing, size and direction) for the output
+ * image should be set. This information has the normal defaults of
+ * unit spacing, zero origin and identity direction. Optionally, the
+ * output information can be obtained from a reference image. If the
+ * reference image is provided and UseReferenceImage is On, then the
+ * spacing, origin and direction of the reference image will be used.
+ *
+ * Since this filter produces an image which is a different size than
+ * its input, it needs to override several of the methods defined
+ * in ProcessObject in order to properly manage the pipeline execution model.
+ * In particular, this filter overrides
+ * ProcessObject::GenerateInputRequestedRegion() and
+ * ProcessObject::GenerateOutputInformation().
+ *
+ * This filter is implemented as a multithreaded filter.  It provides a 
+ * ThreadedGenerateData() method for its implementation.
+ *
+ * \author Marius Staring, Leiden University Medical Center, The Netherlands.
+ *
+ * This class was taken from the Insight Journal paper:
+ * http://hdl.handle.net/1926/1387
+ *
+ * 
+ * \ingroup GeometricTransforms
+ */
+template <class TOutputImage,
+         class TTransformPrecisionType=double>
+class ITK_EXPORT TransformToDeformationFieldSource:
+    public itk::ImageSource<TOutputImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef TransformToDeformationFieldSource       Self;
+  typedef itk::ImageSource<TOutputImage>               Superclass;
+  typedef itk::SmartPointer<Self>                      Pointer;
+  typedef itk::SmartPointer<const Self>                ConstPointer;
+
+  typedef TOutputImage                            OutputImageType;
+  typedef typename OutputImageType::Pointer       OutputImagePointer;
+  typedef typename OutputImageType::ConstPointer  OutputImageConstPointer;
+  typedef typename OutputImageType::RegionType    OutputImageRegionType;
+  /** Method for creation through the object factory. */
+  itkNewMacro( Self );
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( TransformToDeformationFieldSource, ImageSource );
+
+  /** Number of dimensions. */
+  itkStaticConstMacro( ImageDimension, unsigned int,
+    TOutputImage::ImageDimension );
+
+  /** Typedefs for transform. */
+  typedef itk::Transform<TTransformPrecisionType, 
+    itkGetStaticConstMacro( ImageDimension ), 
+    itkGetStaticConstMacro( ImageDimension )>     TransformType;
+  typedef typename TransformType::ConstPointer    TransformPointerType;
+
+  /** Typedefs for output image. */
+  typedef typename OutputImageType::PixelType     PixelType;
+  // JV
+  itkStaticConstMacro(SpaceDimension, unsigned int,PixelType::Dimension);
+  typedef typename PixelType::ValueType           PixelValueType;
+  typedef typename OutputImageType::RegionType    RegionType;
+  typedef typename RegionType::SizeType           SizeType;
+  typedef typename OutputImageType::IndexType     IndexType;
+  typedef typename OutputImageType::PointType     PointType;
+  typedef typename OutputImageType::SpacingType   SpacingType;
+  typedef typename OutputImageType::PointType     OriginType;
+  typedef typename OutputImageType::DirectionType DirectionType;
+
+  /** Typedefs for base image. */
+  typedef itk::ImageBase< itkGetStaticConstMacro( ImageDimension ) > ImageBaseType;
+  
+  /** Set the coordinate transformation.
+   * Set the coordinate transform to use for resampling.  Note that this must
+   * be in physical coordinates and it is the output-to-input transform, NOT
+   * the input-to-output transform that you might naively expect.  By default
+   * the filter uses an Identity transform. You must provide a different
+   * transform here, before attempting to run the filter, if you do not want to
+   * use the default Identity transform. */
+  itkSetConstObjectMacro( Transform, TransformType ); 
+
+  /** Get a pointer to the coordinate transform. */
+  itkGetConstObjectMacro( Transform, TransformType );
+
+  /** Set the size of the output image. */
+  virtual void SetOutputSize( const SizeType & size );
+
+  /** Get the size of the output image. */
+  virtual const SizeType & GetOutputSize();
+
+  /** Set the start index of the output largest possible region. 
+  * The default is an index of all zeros. */
+  virtual void SetOutputIndex( const IndexType & index );
+
+  /** Get the start index of the output largest possible region. */
+  virtual const IndexType & GetOutputIndex();
+
+  /** Set the region of the output image. */
+  itkSetMacro( OutputRegion, OutputImageRegionType );
+
+  /** Get the region of the output image. */
+  itkGetConstReferenceMacro( OutputRegion, OutputImageRegionType );
+     
+  /** Set the output image spacing. */
+  itkSetMacro( OutputSpacing, SpacingType );
+  virtual void SetOutputSpacing( const double* values );
+
+  /** Get the output image spacing. */
+  itkGetConstReferenceMacro( OutputSpacing, SpacingType );
+
+  /** Set the output image origin. */
+  itkSetMacro( OutputOrigin, OriginType );
+  virtual void SetOutputOrigin( const double* values);
+
+  /** Get the output image origin. */
+  itkGetConstReferenceMacro( OutputOrigin, OriginType );
+
+  /** Set the output direction cosine matrix. */
+  itkSetMacro( OutputDirection, DirectionType );
+  itkGetConstReferenceMacro( OutputDirection, DirectionType );
+
+  /** Helper method to set the output parameters based on this image */
+  void SetOutputParametersFromImage( const ImageBaseType * image );
+  
+  /** DeformationFieldImageFilter produces a vector image. */
+  virtual void GenerateOutputInformation( void );
+
+  /** Just checking if transform is set. */
+  virtual void BeforeThreadedGenerateData( void );
+
+  /** Compute the Modified Time based on changes to the components. */
+  unsigned long GetMTime( void ) const;
+
+  // JV To allow 4D DVF conversion
+// #ifdef ITK_USE_CONCEPT_CHECKING
+//   /** Begin concept checking */
+//   itkStaticConstMacro(PixelDimension, unsigned int,
+//                       PixelType::Dimension );
+//   itkConceptMacro(SameDimensionCheck,
+//     (Concept::SameDimension<ImageDimension,PixelDimension>));
+//   /** End concept checking */
+// #endif
+
+protected:
+  TransformToDeformationFieldSource( );
+  ~TransformToDeformationFieldSource( ) {};
+
+  void PrintSelf( std::ostream& os, itk::Indent indent ) const;
+
+  /** TransformToDeformationFieldSource can be implemented as a multithreaded
+   * filter.
+   */
+  void ThreadedGenerateData(
+    const OutputImageRegionType & outputRegionForThread,
+    int threadId );
+
+  /** Default implementation for resampling that works for any
+   * transformation type.
+   */
+  void NonlinearThreadedGenerateData(
+    const OutputImageRegionType& outputRegionForThread,
+    int threadId );
+
+  /** Faster implementation for resampling that works for with linear
+   *  transformation types. 
+   */
+  void LinearThreadedGenerateData(
+    const OutputImageRegionType & outputRegionForThread,
+    int threadId );
+  
+private:
+
+  TransformToDeformationFieldSource( const Self& ); //purposely not implemented
+  void operator=( const Self& ); //purposely not implemented
+
+  /** Member variables. */
+  RegionType              m_OutputRegion;      // region of the output image
+  TransformPointerType    m_Transform;         // Coordinate transform to use
+  SpacingType             m_OutputSpacing;     // output image spacing
+  OriginType              m_OutputOrigin;      // output image origin
+  DirectionType           m_OutputDirection;   // output image direction cosines
+
+}; // end class TransformToDeformationFieldSource
+  
+} // end namespace clitk
+  
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkTransformToDeformationFieldSource.txx"
+#endif
+  
+#endif // end #ifndef __clitkTransformToDeformationFieldSource_h
diff --git a/registration/clitkTransformToDeformationFieldSource.txx b/registration/clitkTransformToDeformationFieldSource.txx
new file mode 100644 (file)
index 0000000..a509304
--- /dev/null
@@ -0,0 +1,380 @@
+/*=========================================================================
+  Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
+
+  Authors belong to: 
+  - University of LYON              http://www.universite-lyon.fr/
+  - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
+  - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the copyright notices for more information.
+
+  It is distributed under dual licence
+
+  - BSD        See included LICENSE.txt file
+  - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
+======================================================================-====*/
+#ifndef __clitkTransformToDeformationFieldSource_txx
+#define __clitkTransformToDeformationFieldSource_txx
+#include "clitkTransformToDeformationFieldSource.h"
+
+#include "itkIdentityTransform.h"
+#include "itkProgressReporter.h"
+#include "itkImageRegionIteratorWithIndex.h"
+#include "itkImageLinearIteratorWithIndex.h"
+
+namespace clitk
+{
+/**
+ * Constructor
+ */
+  template <class TOutputImage, class TTransformPrecisionType>
+  TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>::TransformToDeformationFieldSource()
+{
+  this->m_OutputSpacing.Fill(1.0);
+  this->m_OutputOrigin.Fill(0.0);
+  this->m_OutputDirection.SetIdentity();
+
+  SizeType size;
+  size.Fill( 0 );
+  this->m_OutputRegion.SetSize( size );
+
+  IndexType index;
+  index.Fill( 0 );
+  this->m_OutputRegion.SetIndex( index );
+
+  this->m_Transform
+    = itk::IdentityTransform<TTransformPrecisionType, ImageDimension>::New();
+} // end Constructor
+
+/**
+ * Print out a description of self
+ *
+ * \todo Add details about this class
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+::PrintSelf( std::ostream & os, itk::Indent indent ) const
+{
+  Superclass::PrintSelf( os, indent );
+
+  os << indent << "OutputRegion: " << this->m_OutputRegion << std::endl;
+  os << indent << "OutputSpacing: " << this->m_OutputSpacing << std::endl;
+  os << indent << "OutputOrigin: " << this->m_OutputOrigin << std::endl;
+  os << indent << "OutputDirection: " << this->m_OutputDirection << std::endl;
+  os << indent << "Transform: " << this->m_Transform.GetPointer() << std::endl;
+} // end PrintSelf()
+
+/**
+ * Set the output image size.
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::SetOutputSize( const SizeType & size )
+{
+  this->m_OutputRegion.SetSize( size );
+}
+
+/**
+ * Get the output image size.
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+const typename TransformToDeformationFieldSource<TOutputImage,
+  TTransformPrecisionType>
+  ::SizeType &
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::GetOutputSize()
+{
+  return this->m_OutputRegion.GetSize();
+}
+
+/**
+ * Set the output image index.
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::SetOutputIndex( const IndexType & index )
+{
+  this->m_OutputRegion.SetIndex( index );
+}
+
+/**
+ * Get the output image index.
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+const typename TransformToDeformationFieldSource<TOutputImage,
+  TTransformPrecisionType>
+  ::IndexType &
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::GetOutputIndex()
+{
+  return this->m_OutputRegion.GetIndex();
+}
+
+/**
+ * Set the output image spacing.
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::SetOutputSpacing( const double *spacing )
+{
+  SpacingType s( spacing );
+
+  this->SetOutputSpacing( s );
+} // end SetOutputSpacing()
+
+/**
+ * Set the output image origin.
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::SetOutputOrigin( const double *origin )
+{
+  OriginType p( origin );
+
+  this->SetOutputOrigin( p );
+}
+
+/** Helper method to set the output parameters based on this image */
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::SetOutputParametersFromImage ( const ImageBaseType *image )
+{
+  if ( !image )
+    {
+    itkExceptionMacro(<< "Cannot use a null image reference");
+    }
+
+  this->SetOutputOrigin( image->GetOrigin() );
+  this->SetOutputSpacing( image->GetSpacing() );
+  this->SetOutputDirection( image->GetDirection() );
+  this->SetOutputRegion( image->GetLargestPossibleRegion() );
+} // end SetOutputParametersFromImage()
+
+/**
+ * Set up state of filter before multi-threading.
+ * InterpolatorType::SetInputImage is not thread-safe and hence
+ * has to be set up before ThreadedGenerateData
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::BeforeThreadedGenerateData( void )
+{
+  if ( !this->m_Transform )
+    {
+    itkExceptionMacro(<< "Transform not set");
+    }
+} // end BeforeThreadedGenerateData()
+
+/**
+ * ThreadedGenerateData
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::ThreadedGenerateData(
+  const OutputImageRegionType & outputRegionForThread,
+  int threadId )
+{
+  // Check whether we can use a fast path for resampling. Fast path
+  // can be used if the transformation is linear. Transform respond
+  // to the IsLinear() call.
+  if ( this->m_Transform->IsLinear() )
+    {
+    this->LinearThreadedGenerateData( outputRegionForThread, threadId );
+    return;
+    }
+
+  // Otherwise, we use the normal method where the transform is called
+  // for computing the transformation of every point.
+  this->NonlinearThreadedGenerateData( outputRegionForThread, threadId );
+} // end ThreadedGenerateData()
+
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::NonlinearThreadedGenerateData(
+  const OutputImageRegionType & outputRegionForThread,
+  int threadId )
+{
+  // Get the output pointer
+  OutputImagePointer outputPtr = this->GetOutput();
+
+  // Create an iterator that will walk the output region for this thread.
+  typedef itk::ImageRegionIteratorWithIndex<TOutputImage> OutputIteratorType;
+  OutputIteratorType outIt( outputPtr, outputRegionForThread );
+
+  // Define a few variables that will be used to translate from an input pixel
+  // to an output pixel
+  PointType outputPoint;         // Coordinates of output pixel
+  PointType transformedPoint;    // Coordinates of transformed pixel
+  PixelType deformation;         // the difference
+
+  // Support for progress methods/callbacks
+  itk::ProgressReporter progress( this, threadId,
+                            outputRegionForThread.GetNumberOfPixels() );
+
+  // Walk the output region
+  outIt.GoToBegin();
+  while ( !outIt.IsAtEnd() )
+    {
+    // Determine the index of the current output pixel
+    outputPtr->TransformIndexToPhysicalPoint( outIt.GetIndex(), outputPoint );
+
+    // Compute corresponding input pixel position
+    transformedPoint = this->m_Transform->TransformPoint( outputPoint );
+
+    // Compute the deformation
+    for ( unsigned int i = 0; i < SpaceDimension; ++i )
+      {
+      deformation[i] = static_cast<PixelValueType>(
+        transformedPoint[i] - outputPoint[i] );
+      }
+
+    // Set it
+    outIt.Set( deformation );
+
+    // Update progress and iterator
+    progress.CompletedPixel();
+    ++outIt;
+    }
+} // end NonlinearThreadedGenerateData()
+
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::LinearThreadedGenerateData(
+  const OutputImageRegionType & outputRegionForThread,
+  int threadId )
+{
+  // Get the output pointer
+  OutputImagePointer outputPtr = this->GetOutput();
+
+  // Create an iterator that will walk the output region for this thread.
+  typedef itk::ImageLinearIteratorWithIndex<TOutputImage> OutputIteratorType;
+  OutputIteratorType outIt( outputPtr, outputRegionForThread );
+
+  outIt.SetDirection( 0 );
+
+  // Define a few indices that will be used to translate from an input pixel
+  // to an output pixel
+  PointType outputPoint;         // Coordinates of current output pixel
+  PointType transformedPoint;    // Coordinates of transformed pixel
+  PixelType deformation;         // the difference
+
+  IndexType index;
+
+  // Support for progress methods/callbacks
+  itk::ProgressReporter progress( this, threadId,
+                            outputRegionForThread.GetNumberOfPixels() );
+
+  // Determine the position of the first pixel in the scanline
+  outIt.GoToBegin();
+  index = outIt.GetIndex();
+  outputPtr->TransformIndexToPhysicalPoint( index, outputPoint );
+
+  // Compute corresponding transformed pixel position
+  transformedPoint = this->m_Transform->TransformPoint( outputPoint );
+
+  // Compare with the ResampleImageFilter
+
+  // Compute delta
+  PointType outputPointNeighbour;
+  PointType transformedPointNeighbour;
+  typedef typename PointType::VectorType VectorType;
+  VectorType delta;
+  ++index[0];
+  outputPtr->TransformIndexToPhysicalPoint( index, outputPointNeighbour );
+  transformedPointNeighbour = this->m_Transform->TransformPoint(
+    outputPointNeighbour );
+  delta = transformedPointNeighbour - transformedPoint
+          - ( outputPointNeighbour - outputPoint );
+
+  // loop over the vector image
+  while ( !outIt.IsAtEnd() )
+    {
+    // Get current point
+    index = outIt.GetIndex();
+    outputPtr->TransformIndexToPhysicalPoint( index, outputPoint );
+
+    // Compute transformed point
+    transformedPoint = this->m_Transform->TransformPoint( outputPoint );
+
+    while ( !outIt.IsAtEndOfLine() )
+      {
+      // Compute the deformation
+      for ( unsigned int i = 0; i < SpaceDimension; ++i )
+        {
+        deformation[i] = static_cast<PixelValueType>(
+          transformedPoint[i] - outputPoint[i] );
+        }
+
+      // Set it
+      outIt.Set( deformation );
+
+      // Update stuff
+      progress.CompletedPixel();
+      ++outIt;
+      transformedPoint += delta;
+      }
+
+    outIt.NextLine();
+    }
+} // end LinearThreadedGenerateData()
+
+/**
+ * Inform pipeline of required output region
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+void
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::GenerateOutputInformation( void )
+{
+  // call the superclass' implementation of this method
+  Superclass::GenerateOutputInformation();
+
+  // get pointer to the output
+  OutputImagePointer outputPtr = this->GetOutput();
+  if ( !outputPtr )
+    {
+    return;
+    }
+
+  outputPtr->SetLargestPossibleRegion( m_OutputRegion );
+
+  outputPtr->SetSpacing( m_OutputSpacing );
+  outputPtr->SetOrigin( m_OutputOrigin );
+  outputPtr->SetDirection( m_OutputDirection );
+} // end GenerateOutputInformation()
+
+/**
+ * Verify if any of the components has been modified.
+ */
+template <class TOutputImage, class TTransformPrecisionType>
+unsigned long
+TransformToDeformationFieldSource<TOutputImage, TTransformPrecisionType>
+  ::GetMTime( void ) const
+{
+  unsigned long latestTime = itk::Object::GetMTime();
+
+  if ( this->m_Transform )
+    {
+    if ( latestTime < this->m_Transform->GetMTime() )
+      {
+      latestTime = this->m_Transform->GetMTime();
+      }
+    }
+
+  return latestTime;
+} // end GetMTime()
+} // end namespace clitk
+
+#endif // end #ifndef _clitkTransformToDeformationFieldSource_txx