]> Creatis software - clitk.git/commitdiff
Add a new Transformation that wraps multiple BSplineDeformableTransform to be
authordelmon <delmon>
Tue, 11 Jan 2011 10:25:42 +0000 (10:25 +0000)
committerdelmon <delmon>
Tue, 11 Jan 2011 10:25:42 +0000 (10:25 +0000)
able to optimize them at the same time.

registration/clitkMultipleBSplineDeformableTransform.h [new file with mode: 0644]
registration/clitkMultipleBSplineDeformableTransform.txx [new file with mode: 0644]
registration/clitkMultipleBSplineDeformableTransformInitializer.h [new file with mode: 0644]
registration/clitkMultipleBSplineDeformableTransformInitializer.txx [new file with mode: 0644]

diff --git a/registration/clitkMultipleBSplineDeformableTransform.h b/registration/clitkMultipleBSplineDeformableTransform.h
new file mode 100644 (file)
index 0000000..93277c3
--- /dev/null
@@ -0,0 +1,276 @@
+/*=========================================================================
+  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 __clitkMultipleBSplineDeformableTransform_h
+#define __clitkMultipleBSplineDeformableTransform_h
+
+#include <clitkBSplineDeformableTransform.h>
+
+#include <itkNearestNeighborInterpolateImageFunction.h>
+
+#include <vector>
+
+namespace clitk
+{
+  template <
+    class TCoordRep = double,
+    unsigned int NInputDimensions = 3,
+    unsigned int NOutputDimensions = 3 >
+  class ITK_EXPORT MultipleBSplineDeformableTransform : public itk::Transform< TCoordRep, NInputDimensions, NOutputDimensions >
+  {
+  public:
+
+    //====================================================================
+    // Typedefs
+    //====================================================================
+    typedef MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>  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( MultipleBSplineDeformableTransform, 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;
+
+    /** Typedef of the bulk transform. */
+    typedef itk::Transform<ScalarType, InputDimension, OutputDimension> BulkTransformType;
+    typedef BulkTransformType*                  BulkTransformPointer;
+
+    typedef itk::Image< unsigned char, InputDimension>   ImageLabelType;
+    typedef ImageLabelType* ImageLabelPointer;
+    //typedef typename ImageLabelType::Pointer ImageLabelPointer;
+
+    typedef itk::NearestNeighborInterpolateImageFunction<ImageLabelType, TCoordRep> ImageLabelInterpolator;
+    typedef typename ImageLabelInterpolator::Pointer ImageLabelInterpolatorPointer;
+
+    void SetLabels(ImageLabelPointer labels);
+    ImageLabelPointer GetLabels() {return m_labels;}
+
+    itkGetMacro(nLabels, unsigned);
+
+    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 const std::vector<CoefficientImagePointer>& GetCoefficientImages() const;
+    virtual void SetCoefficientImages(std::vector<CoefficientImagePointer>& images);
+
+    /** 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
+    void SetBulkTransform(BulkTransformPointer b);
+    BulkTransformPointer GetBulkTransform(void) {return m_BulkTransform;}
+
+    /** 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;
+
+    /** 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;
+
+    virtual bool IsLinear() const { return false; }
+
+    typedef  clitk::BSplineDeformableTransform<TCoordRep,InputDimension, OutputDimension > TransformType;
+
+  protected:
+
+    void PrintSelf(std::ostream &os, itk::Indent indent) const;
+
+    MultipleBSplineDeformableTransform();
+    virtual ~MultipleBSplineDeformableTransform();
+
+    void TransformPointToContinuousIndex( const InputPointType & point, ContinuousIndexType & index ) const;
+
+  private:
+    MultipleBSplineDeformableTransform(const Self&); //purposely not implemented
+    void operator=(const Self&); //purposely not implemented
+
+    /** The bulk transform. */
+    BulkTransformPointer  m_BulkTransform;
+
+    /** 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 a pointer to the input parameters. */
+    const ParametersType *  m_InputParametersPointer;
+
+    /** Internal parameters buffer. */
+    ParametersType          m_InternalParametersBuffer;
+
+    unsigned int                                    m_nLabels;
+    ImageLabelPointer                               m_labels;
+    ImageLabelInterpolatorPointer                   m_labelInterpolator;
+    std::vector<typename TransformType::Pointer>    m_trans;
+    std::vector<ParametersType>                     m_parameters;
+    mutable std::vector<CoefficientImagePointer>    m_CoefficientImages;
+    mutable int                                     m_LastJacobian;
+
+    void InitJacobian();
+    // FIXME it seems not used
+    bool InsideValidRegion( const ContinuousIndexType& index ) const;
+  };
+
+}  // namespace clitk
+
+#if ITK_TEMPLATE_TXX
+# include "clitkMultipleBSplineDeformableTransform.txx"
+#endif
+
+#endif // __clitkMultipleBSplineDeformableTransform_h
diff --git a/registration/clitkMultipleBSplineDeformableTransform.txx b/registration/clitkMultipleBSplineDeformableTransform.txx
new file mode 100644 (file)
index 0000000..3a609a2
--- /dev/null
@@ -0,0 +1,487 @@
+/*=========================================================================
+  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 __clitkMultipleBSplineDeformableTransform_txx
+#define __clitkMultipleBSplineDeformableTransform_txx
+
+// clitk
+#include "clitkMultipleBSplineDeformableTransformInitializer.h"
+
+// itk
+#include <itkRelabelComponentImageFilter.h>
+
+namespace clitk
+{
+  // Constructor with default arguments
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::MultipleBSplineDeformableTransform() : Superclass(OutputDimension, 0)
+  {
+    m_nLabels = 1;
+    m_labels = 0;
+    m_labelInterpolator = 0;
+    m_trans.resize(1);
+    m_trans[0] = TransformType::New();
+    m_parameters.resize(1);
+
+    this->m_FixedParameters.SetSize(NInputDimensions * (NInputDimensions + 5) + 4);
+    this->m_FixedParameters.Fill(0.0);
+
+    m_InternalParametersBuffer = ParametersType(0);
+    // Make sure the parameters pointer is not NULL after construction.
+    m_InputParametersPointer = &m_InternalParametersBuffer;
+    m_BulkTransform = 0;
+    m_LastJacobian = -1;
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::~MultipleBSplineDeformableTransform()
+  {
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetLabels(ImageLabelPointer labels)
+  {
+    GetFixedParameters(); // Update m_FixedParameters
+    if (labels)
+    {
+      typedef itk::RelabelComponentImageFilter<ImageLabelType, ImageLabelType> RelabelImageFilterType;
+      typename RelabelImageFilterType::Pointer relabelImageFilter = RelabelImageFilterType::New();
+      relabelImageFilter->SetInput(labels);
+      relabelImageFilter->Update();
+      m_labels = relabelImageFilter->GetOutput();
+      m_nLabels = relabelImageFilter->GetNumberOfObjects();
+      m_trans.resize(m_nLabels);
+      m_parameters.resize(m_nLabels);
+      for (unsigned i = 0; i < m_nLabels; ++i)
+        m_trans[i] = TransformType::New();
+      m_labelInterpolator = ImageLabelInterpolator::New();
+      m_labelInterpolator->SetInputImage(m_labels);
+    }
+    else
+    {
+      m_nLabels = 1;
+      m_trans.resize(1);
+      m_parameters.resize(1);
+      m_trans[0] = TransformType::New();
+    }
+    this->m_FixedParameters[(5+NInputDimensions)*NInputDimensions + 2] = (double)((size_t) m_labels);
+    this->m_FixedParameters[(5+NInputDimensions)*NInputDimensions + 3] = m_nLabels;
+    SetFixedParameters(this->m_FixedParameters);
+  }
+
+#define LOOP_ON_LABELS(FUNC, ARGS)          \
+  for (unsigned i = 0; i < m_nLabels; ++i)  \
+    m_trans[i]->FUNC(ARGS);
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetSplineOrder(const unsigned int & splineOrder)
+  {
+    LOOP_ON_LABELS(SetSplineOrder, splineOrder);
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetSplineOrders(const SizeType & splineOrders)
+  {
+    LOOP_ON_LABELS(SetSplineOrders, splineOrders);
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetLUTSamplingFactor( const int & samplingFactor)
+  {
+    LOOP_ON_LABELS(SetLUTSamplingFactor, samplingFactor);
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetLUTSamplingFactors( const SizeType & samplingFactors)
+  {
+    LOOP_ON_LABELS(SetLUTSamplingFactors, samplingFactors);
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridRegion( const RegionType & region )
+  {
+    LOOP_ON_LABELS(SetGridRegion, region);
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridSpacing( const SpacingType & spacing )
+  {
+    LOOP_ON_LABELS(SetGridSpacing, spacing);
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridDirection( const DirectionType & direction )
+  {
+    LOOP_ON_LABELS(SetGridDirection, direction);
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetGridOrigin( const OriginType& origin )
+  {
+    LOOP_ON_LABELS(SetGridOrigin, origin);
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetIdentity()
+  {
+    LOOP_ON_LABELS(SetIdentity, );
+    if ( m_InputParametersPointer )
+    {
+      ParametersType * parameters =
+        const_cast<ParametersType *>( m_InputParametersPointer );
+      parameters->Fill( 0.0 );
+    }
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline const std::vector<typename MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>::CoefficientImagePointer>&
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetCoefficientImages() const
+  {
+    m_CoefficientImages.resize(m_nLabels);
+    for (unsigned i = 0; i < m_nLabels; ++i)
+      m_CoefficientImages[i] = m_trans[i]->GetCoefficientImage();
+    return m_CoefficientImages;
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetCoefficientImages(std::vector<CoefficientImagePointer>& images)
+  {
+    if (images.size() != m_nLabels)
+    {
+      itkExceptionMacro( << "Mismatched between the number of labels "
+          << m_nLabels
+          << " and the number of coefficient images "
+          << images.size());
+    }
+    for (unsigned i = 0; i < m_nLabels; ++i)
+      m_trans[i]->SetCoefficientImage(images[i]);
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetParameters( const ParametersType & parameters )
+  {
+    if ( parameters.Size() != this->GetNumberOfParameters() )
+      {
+       itkExceptionMacro(<<"Mismatched between parameters size "
+                         << parameters.size()
+                         << " and region size "
+                         << this->GetNumberOfParameters() );
+      }
+
+    // Clean up buffered parameters
+    m_InternalParametersBuffer = ParametersType( 0 );
+
+    // Keep a reference to the input parameters
+    m_InputParametersPointer = &parameters;
+
+    double * dataPointer = const_cast<double *>(m_InputParametersPointer->data_block());
+    unsigned tot = 0;
+    for (unsigned i = 0; i < m_nLabels; ++i)
+    {
+      unsigned int numberOfParameters = m_trans[i]->GetNumberOfParameters();
+      m_parameters[i].SetData(dataPointer + tot, numberOfParameters);
+      m_trans[i]->SetParameters(m_parameters[i]);
+      tot += numberOfParameters;
+    }
+    InitJacobian();
+
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetFixedParameters( const ParametersType & parameters )
+  {
+    // BSplineSeformableTransform parameters + m_labels pointer
+    if ( parameters.Size() != NInputDimensions * (5 + NInputDimensions) + 4)
+      {
+       itkExceptionMacro(<< "Mismatched between parameters size "
+                         << parameters.size()
+                         << " and number of fixed parameters "
+                         << NInputDimensions * (5 + NInputDimensions) + 4);
+      }
+    ImageLabelPointer tmp2 = ((ImageLabelPointer)( (size_t)parameters[(5+NInputDimensions)*NInputDimensions+2]));
+    if (tmp2 != m_labels)
+    {
+      if (tmp2)
+      {
+        m_labels = tmp2;
+        m_nLabels = parameters[(5+NInputDimensions) * NInputDimensions + 3 ];
+        m_trans.resize(m_nLabels);
+        m_parameters.resize(m_nLabels);
+        for (unsigned i = 0; i < m_nLabels; ++i)
+          m_trans[i] = TransformType::New();
+        m_labelInterpolator = ImageLabelInterpolator::New();
+        m_labelInterpolator->SetInputImage(m_labels);
+      }
+      else
+      {
+        m_labels = tmp2;
+        m_nLabels = 1;
+        m_trans.resize(1);
+        m_parameters.resize(1);
+        m_trans[0] = TransformType::New();
+      }
+    }
+    unsigned int numberOfParameters = NInputDimensions * (5 + NInputDimensions) + 2;
+    ParametersType tmp(numberOfParameters);
+    for (unsigned j = 0; j < numberOfParameters; ++j)
+      tmp.SetElement(j, parameters.GetElement(j));
+    LOOP_ON_LABELS(SetFixedParameters, tmp);
+    this->m_FixedParameters = parameters;
+    this->Modified();
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetParametersByValue( const ParametersType & parameters )
+  {
+    if ( parameters.Size() != this->GetNumberOfParameters() )
+      {
+       itkExceptionMacro(<<"Mismatched between parameters size "
+                         << parameters.size()
+                         << " and region size "
+                         << this->GetNumberOfParameters() );
+      }
+
+    // Copy it
+    m_InternalParametersBuffer = parameters;
+    m_InputParametersPointer = &m_InternalParametersBuffer;
+
+    for (unsigned i = 0, tot = 0; i < m_nLabels; ++i)
+    {
+      unsigned int numberOfParameters = m_trans[i]->GetNumberOfParameters();
+      ParametersType tmp(numberOfParameters);
+      for (unsigned j = 0; j < numberOfParameters; ++j, ++tot)
+        tmp.SetElement(j, parameters.GetElement(tot));
+      m_trans[i]->SetParametersByValue(tmp);
+    }
+    InitJacobian();
+    this->Modified();
+  }
+
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::SetBulkTransform(BulkTransformPointer b)
+  {
+    m_BulkTransform = b;
+    LOOP_ON_LABELS(SetBulkTransform, b);
+  }
+
+#undef LOOP_ON_LABELS
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline unsigned int
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetNumberOfParameters(void) const
+  {
+    unsigned int sum = 0;
+    for (unsigned i = 0; i < m_nLabels; ++i)
+      sum += m_trans[i]->GetNumberOfParameters();
+    return sum;
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline unsigned int
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetNumberOfParametersPerDimension(void) const
+  {
+    unsigned int sum = 0;
+    for (unsigned i = 0; i < m_nLabels; ++i)
+      sum += m_trans[i]->GetNumberOfParametersPerDimension();
+    return sum;
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline const typename MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>::ParametersType &
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetParameters() const
+  {
+    if (NULL == m_InputParametersPointer)
+      {
+       itkExceptionMacro( <<"Cannot GetParameters() because m_InputParametersPointer is NULL. Perhaps SetCoefficientImage() has been called causing the NULL pointer." );
+      }
+
+    return (*m_InputParametersPointer);
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline const typename MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>::ParametersType &
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetFixedParameters() const
+  {
+    const ParametersType& trans0Para = m_trans[0]->GetFixedParameters();
+    for (unsigned i = 0; i < trans0Para.Size() ; ++i)
+      this->m_FixedParameters.SetElement(i, trans0Para.GetElement(i));
+    this->m_FixedParameters[(5+NInputDimensions)*NInputDimensions + 2] = (double)((size_t) m_labels);
+    this->m_FixedParameters[(5+NInputDimensions)*NInputDimensions + 3] = m_nLabels;
+    return this->m_FixedParameters;
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::PrintSelf(std::ostream &os, itk::Indent indent) const
+  {
+    this->Superclass::PrintSelf(os, indent);
+    os << indent << "nLabels" << m_nLabels << std::endl;
+    itk::Indent ind = indent.GetNextIndent();
+
+    for (unsigned i = 0; i < m_nLabels; ++i)
+    {
+      os << indent << "Label " << i << std::endl;
+      m_trans[i]->Print(os, ind);
+    }
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline bool
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::InsideValidRegion( const ContinuousIndexType& index ) const
+  {
+    bool res = false;
+    for (unsigned i = 0; i < m_nLabels; ++i)
+      res |= m_trans[i]->InsideValidRegion(index);
+    return res;
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline typename MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>::OutputPointType
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::TransformPoint(const InputPointType &inputPoint) const
+  {
+    int lidx = 0;
+    if (m_labels)
+      lidx = m_labelInterpolator->Evaluate(inputPoint) - 1;
+    if (lidx == -1)
+      return inputPoint;
+    return m_trans[lidx]->TransformPoint(inputPoint);
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline typename MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>::OutputPointType
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::DeformablyTransformPoint(const InputPointType &inputPoint) const
+  {
+    int lidx = 0;
+    if (m_labels)
+      lidx = m_labelInterpolator->Evaluate(inputPoint) - 1;
+    if (lidx == -1)
+      return inputPoint;
+    return m_trans[lidx]->DeformablyTransformPoint(inputPoint);
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline const typename MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>::JacobianType &
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions, NOutputDimensions>
+  ::GetJacobian( const InputPointType & point ) const
+  {
+    /*
+    for (unsigned i = 0; i < m_nLabels; ++i)
+      m_trans[i]->ResetJacobian();
+      */
+    if (m_LastJacobian != -1)
+      m_trans[m_LastJacobian]->ResetJacobian();
+
+    int lidx = 0;
+    if (m_labels)
+      lidx = m_labelInterpolator->Evaluate(point) - 1;
+    if (lidx == -1)
+    {
+      m_LastJacobian = lidx;
+      return this->m_Jacobian;
+    }
+
+    m_trans[lidx]->GetJacobian(point);
+    m_LastJacobian = lidx;
+
+    return this->m_Jacobian;
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions,NOutputDimensions>
+  ::TransformPointToContinuousIndex( const InputPointType & point, ContinuousIndexType & index ) const
+  {
+    m_trans[0]->TransformPointToContinuousIndex(point, index);
+  }
+
+  template<class TCoordRep, unsigned int NInputDimensions, unsigned int NOutputDimensions>
+  inline void
+  MultipleBSplineDeformableTransform<TCoordRep, NInputDimensions,NOutputDimensions>::InitJacobian()
+  {
+    unsigned numberOfParameters = this->GetNumberOfParameters();
+    this->m_Jacobian.set_size(OutputDimension, numberOfParameters);
+    JacobianPixelType * jacobianDataPointer = reinterpret_cast<JacobianPixelType *>(this->m_Jacobian.data_block());
+    memset(jacobianDataPointer, 0,  numberOfParameters * sizeof (JacobianPixelType));
+
+    unsigned tot = 0;
+    for (unsigned int j = 0; j < OutputDimension; j++)
+    {
+      for (unsigned i = 0; i < m_nLabels; ++i)
+      {
+        unsigned numberOfPixels = m_trans[i]->SetJacobianImageData(jacobianDataPointer, j);
+        jacobianDataPointer += numberOfPixels;
+        tot += numberOfPixels;
+      }
+    }
+    assert(tot == numberOfParameters);
+  }
+
+}  // namespace clitk
+
+#endif // __clitkMultipleBSplineDeformableTransform_txx
diff --git a/registration/clitkMultipleBSplineDeformableTransformInitializer.h b/registration/clitkMultipleBSplineDeformableTransformInitializer.h
new file mode 100644 (file)
index 0000000..63a30c7
--- /dev/null
@@ -0,0 +1,173 @@
+/*=========================================================================
+  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 __clitkMultipleBSplineDeformableTransformInitializer_h
+#define __clitkMultipleBSplineDeformableTransformInitializer_h
+#include "clitkResampleBSplineDeformableTransformImageFilter.h"
+
+#include "itkObject.h"
+#include "itkObjectFactory.h"
+#include <iostream>
+
+namespace clitk
+{
+
+  template < class TTransform, class TImage >
+    class ITK_EXPORT MultipleBSplineDeformableTransformInitializer : public itk::Object
+  {
+    public:
+      /** Standard class typedefs. */
+      typedef MultipleBSplineDeformableTransformInitializer     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( MultipleBSplineDeformableTransformInitializer, 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(std::vector<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:
+      MultipleBSplineDeformableTransformInitializer();
+      ~MultipleBSplineDeformableTransformInitializer(){};
+
+    private:
+      MultipleBSplineDeformableTransformInitializer(const Self&); //purposely not implemented
+      void operator=(const Self&); //purposely not implemented
+
+      bool m_Verbose;
+      TransformPointer    m_Transform;
+      ImagePointer        m_Image;
+
+  }; //class MultipleBSplineDeformableTransformInitializer
+
+
+}  // namespace clitk
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "clitkMultipleBSplineDeformableTransformInitializer.txx"
+#endif
+
+#endif /* __clitkMultipleBSplineDeformableTransformInitializer_h */
diff --git a/registration/clitkMultipleBSplineDeformableTransformInitializer.txx b/registration/clitkMultipleBSplineDeformableTransformInitializer.txx
new file mode 100644 (file)
index 0000000..1ee4be9
--- /dev/null
@@ -0,0 +1,260 @@
+/*=========================================================================
+  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 __clitkMultipleBSplineDeformableTransformInitializer_txx
+#define __clitkMultipleBSplineDeformableTransformInitializer_txx
+#include "clitkMultipleBSplineDeformableTransformInitializer.h"
+
+namespace clitk
+{
+
+  template < class TTransform, class TImage >
+  MultipleBSplineDeformableTransformInitializer<TTransform, TImage >
+  ::MultipleBSplineDeformableTransformInitializer()
+  {
+    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
+  MultipleBSplineDeformableTransformInitializer<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
+  MultipleBSplineDeformableTransformInitializer<TTransform, TImage >
+  ::SetInitialParameters( const std::string& s, ParametersType& params)
+  {
+    //---------------------------------------
+    // Read Initial parameters
+    //---------------------------------------
+    typedef itk::ImageFileReader<CoefficientImageType> CoefficientReaderType;
+    typename CoefficientReaderType::Pointer coeffReader = CoefficientReaderType::New();
+    std::vector<typename CoefficientImageType::Pointer> coefficientImages;
+    unsigned nLabels = m_Transform->GetnLabels();
+
+    int dotpos = s.length() - 1;
+    while (dotpos >= 0 && s[dotpos] != '.')
+      dotpos--;
+
+    for (unsigned i = 0; i < nLabels; ++i)
+    {
+      std::ostringstream osfname;
+      osfname << s.substr(0, dotpos) << '_' << i << s.substr(dotpos);
+      coeffReader->SetFileName(osfname.str());
+      if (m_Verbose)
+        std::cout << "Reading initial coefficients from file: " << osfname << "..." << std::endl;
+      coeffReader->Update();
+      coefficientImages[i] = coeffReader->GetOutput();
+    }
+    this->SetInitialParameters(coefficientImages, params);
+  }
+
+  template < class TTransform, class TImage >
+  void
+  MultipleBSplineDeformableTransformInitializer<TTransform, TImage >
+  ::SetInitialParameters(std::vector<typename CoefficientImageType::Pointer> coefficientImages, ParametersType& params)
+  {
+    // Keep a reference
+    m_Parameters=&params;
+
+    // Resample
+    typedef ResampleBSplineDeformableTransformImageFilter<CoefficientImageType,CoefficientImageType> ResamplerType;
+    typename ResamplerType::Pointer resampler;
+    unsigned int i = 0;
+    for (unsigned l = 0; l < coefficientImages.size(); ++l)
+    {
+      typename ResamplerType::Pointer resampler = ResamplerType::New();
+      resampler->SetInput(coefficientImages[l]);
+      resampler->SetOutputParametersFromImage(m_Transform->GetCoefficientImages()[l]);
+      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();
+      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