+############################## 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)
# 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
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
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"
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"
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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;
+}
--- /dev/null
+#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"
+
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+
+
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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 = ¶meters;
+
+ // 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
--- /dev/null
+/*=========================================================================
+ 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 */
--- /dev/null
+/*=========================================================================
+ 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=¶ms;
+
+ // 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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"
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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"
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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
+
--- /dev/null
+/*=========================================================================
+ 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 */
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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;
+}
--- /dev/null
+#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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+
+
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
/*=========================================================================
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
{
* vnl_lbfgsb into iteration events in ITK.
*/
class ITK_EXPORT LBFGSBOptimizerHelper :
- public vnl_lbfgsb
+ public vnl_lbfgsb
{
public:
typedef LBFGSBOptimizerHelper Self;
LBFGSBOptimizer* m_ItkObj;
};
-
+
/**
m_VnlOptimizer = 0;
m_LowerBound = InternalBoundValueType(0);
- m_UpperBound = InternalBoundValueType(0);
+ m_UpperBound = InternalBoundValueType(0);
m_BoundSelection = InternalBoundSelectionType(0);
m_CostFunctionConvergenceFactor = 1e+7;
m_CurrentIteration = 0;
m_Value = 0.0;
m_InfinityNormOfProjectedGradient = 0.0;
-
+ m_StopConditionDescription.str("");
+
}
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;
+ }
}
/**
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();
}
* Get lower bound
*/
const
-LBFGSBOptimizer
+LBFGSBOptimizer
::BoundValueType &
LBFGSBOptimizer
::GetLowerBound()
{
return m_LowerBound;
-}
+}
/**
* Set upper bound
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();
}
* Get upper bound
*/
const
-LBFGSBOptimizer
+LBFGSBOptimizer
::BoundValueType &
LBFGSBOptimizer
::GetUpperBound()
{
return m_UpperBound;
-}
+}
/**
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();
}
* 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();
}
::SetProjectedGradientTolerance( double value )
{
m_ProjectedGradientTolerance = value;
- if( m_OptimizerInitialized ) {
+ if( m_OptimizerInitialized )
+ {
m_VnlOptimizer->set_projected_gradient_tolerance(
m_ProjectedGradientTolerance );
- }
+ }
this->Modified();
}
::SetMaximumNumberOfEvaluations( unsigned int value )
{
m_MaximumNumberOfEvaluations = value;
- if( m_OptimizerInitialized ) {
+ if( m_OptimizerInitialized )
+ {
m_VnlOptimizer->set_max_function_evals( m_MaximumNumberOfEvaluations );
- }
+ }
this->Modified();
}
::SetMaximumNumberOfCorrections( unsigned int value )
{
m_MaximumNumberOfCorrections = value;
- if( m_OptimizerInitialized ) {
+ if( m_OptimizerInitialized )
+ {
m_VnlOptimizer->set_max_variable_metric_corrections(
m_MaximumNumberOfCorrections );
- }
+ }
this->Modified();
}
{
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 );
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(
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 );
// 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
/*=========================================================================
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
*
* 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. */
typedef itk::SingleValuedNonLinearVnlOptimizer Superclass;
typedef itk::SmartPointer<Self> Pointer;
typedef itk::SmartPointer<const Self> ConstPointer;
-
+
/** Method for creation through the object factory. */
itkNewMacro(Self);
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;
/** 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 );
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 );
* function. */
itkGetConstReferenceMacro( InfinityNormOfProjectedGradient, double );
+ /** Get the reason for termination */
+ const std::string GetStopConditionDescription() const;
+
protected:
LBFGSBOptimizer();
virtual ~LBFGSBOptimizer();
bool m_OptimizerInitialized;
InternalOptimizerType * m_VnlOptimizer;
-
+ mutable itk::OStringStream m_StopConditionDescription;
BoundValueType m_LowerBound;
BoundValueType m_UpperBound;
BoundSelectionType m_BoundSelection;
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
--- /dev/null
+/*=========================================================================
+ 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;
+ // }
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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"
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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"
+
+
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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 */
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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"
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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
+
+
+
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
+
+//--------------------------------------------------------------------
--- /dev/null
+#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"
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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 = ¶meters;
+
+ // 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
+
--- /dev/null
+/*=========================================================================
+ 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 */
--- /dev/null
+/*=========================================================================
+ 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=¶ms;
+
+ // 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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
--- /dev/null
+/*=========================================================================
+ 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