<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Change SYSTEM "https://itk.org/migrationv4/ITKMigration.dtd">

<!--**
**
** BSplineRegistrationRefactoring.xml
**
**-->
<Change>
    <!--**
    ** Title for the online migration page
    **-->
    <Title>
      B-spline Registration Refactoring
    </Title>

    <!--**
    ** The author of the change
    **-->
    <Author>
      Nick Tustison
    </Author>

    <!--**
    ** Date of creation for the XML document
    **-->
    <Date>
      2011-07-15
    </Date>

    <!--**
    ** Plain text description of the change
    ** Extracted from git commit messages
    **-->
    <Description>
      A couple items associated with the B-spline registration refactoring:
      1.  In the bug report filed by Hans Johnson,
      http://public.kitware.com/Bug/view.php?id=11512,
      it was noted that the B-spline grid initialized by the
      BSplineTransformDomainInitializer
      lays out the control points according to the image information.
      Thus, an image and its permuted axis or flip axis analog could end up
      with different control point grids.  Instead, it seems much more
      intuitive if the control point grid were laid out based on
      the image location in physical space which is what the new
      BSplineTransformDomainInitializer does.
      2. The API of the B-spline deformable transform has been
      fixed such that the user does not need to understand the nuances
      of how the B-spline grid is laid out relative to the transform
      domain.  Instead, it is much more intuitive for the user to simply define
      the desired transform domain in terms of the domain origin, direction,
      and physical dimensions.  Given this information, as well as the
      spline order and mesh size, the control point grid is laid out
      automatically inside the transform class.  Note that the mesh size refers
      to the number of B-spline polynomial patches comprising the transform
      domain where the degree of polynomial is specified by the order.  Since
      the assumption is that these are uniform B-splines, each mesh element
      is the same size in terms of physical size.  More mesh elements means
      greater flexibility in the transform.
      3.  The previous version of the B-spline deformable
      transform set up the grid such that the mesh elements at the
      upper index of the transform were not used.  So, if you wanted
      to do a 2-D B-spline registration using a mesh size of 10x10,
      only 9x9 elements would be used in the transform domain. In
      my opinion this is a bug which should be fixed.
      4. We got rid of the bulk transform in the B-spline transform.
      We expect to handle global alignment via another mechanism
      outside a specific transform.

      The ITKv3 api is available when ITKv4 configured with
      ITKV3_COMPATIBILITY:BOOL=ON
    </Description>

    <!--**
    ** Sample code snippets
    ** Extracted from git diff of changed files in Examples and Testing
    **-->
    <SampleCode>
      <Old>
        <![CDATA[

        //
        // This is the old api for specifying a B-spline deformable transform
        // initializer.
        //

        typedef itk::BSplineDeformableTransform<
                                  CoordinateRepType,
                                  SpaceDimension,
                                  SplineOrder >     TransformType;

        TransformType::Pointer bsplineTransform = TransformType::New();

        typedef itk::BSplineDeformableTransformInitializer<
                        TransformType,
                        FixedImageType >      InitializerType;
        InitializerType::Pointer transformInitializer = InitializerType::New();

        transformInitializer->SetTransform( bsplineTransform );
        transformInitializer->SetImage( fixedImage );

        typedef TransformType::RegionType RegionType;
        RegionType::SizeType size;

        const unsigned int numberOfGridNodesInsideTheImageSupport = 5;

        size.Fill( numberOfGridNodesInsideTheImageSupport );

        transformInitializer->SetGridSizeInsideTheImage( size );

        transformInitializer->InitializeTransform();
        ]]>
      </Old>

      <New>
        <![CDATA[

        //
        // This is the new api for specifying a B-spline deformable transform
        // initializer.
        //

        typedef itk::BSplineTransform<
                                  CoordinateRepType,
                                  SpaceDimension,
                                  SplineOrder >     TransformType;

        TransformType::Pointer bsplineTransform = TransformType::New();

        typedef itk::BSplineTransformInitializer<
                        TransformType,
                        FixedImageType >      InitializerType;
        InitializerType::Pointer transformInitializer = InitializerType::New();

        transformInitializer->SetTransform( bsplineTransform );
        transformInitializer->SetImage( fixedImage );

        transformInitializer->InitializeTransform();

        TransformType::MeshSizeType meshSize;
        meshSize.Fill( 5 );

        bsplineTransform->SetTransformDomainMeshSize( meshSize );
        ]]>
      </New>

    </SampleCode>

    <SampleCode>
      <Old>
        <![CDATA[

        //
        // This is the old api for specifying a B-spline deformable transform
        //

        typedef TransformType::RegionType RegionType;
        RegionType bsplineRegion;
        RegionType::SizeType   gridSizeOnImage;
        RegionType::SizeType   gridBorderSize;
        RegionType::SizeType   totalGridSize;

        gridSizeOnImage.Fill( numberOfGridNodesInOneDimension );
        // Border for spline order = 3 ( 1 lower, 2 upper )
        gridBorderSize.Fill( SplineOrder );
        totalGridSize = gridSizeOnImage + gridBorderSize;

        bsplineRegion.SetSize( totalGridSize );

        typedef TransformType::SpacingType SpacingType;
        SpacingType spacing = fixedImage->GetSpacing();

        typedef TransformType::OriginType OriginType;
        OriginType origin = fixedImage->GetOrigin();
        FixedImageType::SizeType fixedImageSize = fixedRegion.GetSize();
        for(unsigned int r = 0; r < ImageDimension; r++ )
          {
          spacing[r] *= static_cast<double>(fixedImageSize[r] - 1)  /
            static_cast<double>(gridSizeOnImage[r] - 1);
          }
        FixedImageType::DirectionType gridDirection =
        SpacingType gridOriginOffset = gridDirection * spacing;

        OriginType gridOrigin = origin - gridOriginOffset;

        transform->SetGridSpacing( spacing );
        transform->SetGridOrigin( gridOrigin );
        transform->SetGridRegion( bsplineRegion );
        transform->SetGridDirection( fixedImage->GetDirection() );
        ]]>
      </Old>

      <New>
        <![CDATA[

        //
        // This is the new api for specifying a B-spline deformable transform
        //

        TransformType::PhysicalDimensionsType   fixedPhysicalDimensions;
        TransformType::MeshSizeType             meshSize;
        for( unsigned int i=0; i < ImageDimension; i++ )
          {
          fixedPhysicalDimensions[i] = fixedImage->GetSpacing()[i] *
            static_cast<double>(
            fixedImage->GetLargestPossibleRegion().GetSize()[i] - 1 );
          }
        meshSize.Fill( numberOfGridNodesInOneDimension - SplineOrder );
        transform->SetTransformDomainOrigin( fixedImage->GetOrigin() );
        transform->SetTransformDomainPhysicalDimensions(
          fixedPhysicalDimensions );
        transform->SetTransformDomainMeshSize( meshSize );
        transform->SetTransformDomainDirection( fixedImage->GetDirection() );
        ]]>
      </New>

    </SampleCode>

    <!--**
    ** The change-ids for all commits in the topic branch
    **-->
    <Gerrit-ChangeId>
      Ic5d7849ea2695dd7e26b8caf547dc1472b2f1265
    </Gerrit-ChangeId>

    <!--**
    ** List of all changed files from the topic branch
    **-->
    <FileList>
      Examples/Data/BSplineDisplacements1.txt
      Examples/Data/BSplineDisplacements3.txt
      Examples/Data/BSplineDisplacements5.txt
      Examples/IO/TransformReadWrite.cxx
      Examples/Registration/BSplineWarping1.cxx
      Examples/Registration/BSplineWarping2.cxx
      Examples/Registration/DeformableRegistration12.cxx
      Examples/Registration/DeformableRegistration13.cxx
      Examples/Registration/DeformableRegistration14.cxx
      Examples/Registration/DeformableRegistration15.cxx
      Examples/Registration/DeformableRegistration4.cxx
      Examples/Registration/DeformableRegistration6.cxx
      Examples/Registration/DeformableRegistration7.cxx
      Examples/Registration/DeformableRegistration8.cxx
      Modules/Core/Transform/include/itkBSplineTransform.h
      Modules/Core/Transform/include/itkBSplineTransform.txx
      Modules/Nonunit/Review/test/itkBSplineTransformInitializerTest1.cxx
      Modules/Nonunit/Review/test/itkBSplineTransformInitializerTest2.cxx
      Modules/Core/Transform/test/CMakeLists.txt
      Modules/Core/Transform/test/itkBSplineTransformTest.cxx
      Modules/Core/Transform/test/itkBSplineTransformTest2.cxx
      Modules/Core/Transform/test/itkBSplineTransformTest3.cxx
      Modules/Nonunit/Review/include/itkBSplineTransformInitializer.h
      Modules/Nonunit/Review/include/itkBSplineTransformInitializer.txx
      Modules/Nonunit/Review/include/itkOptImageToImageMetricsTest2.h
      Modules/Nonunit/Review/test/itkTransformToDisplacementFieldSourceTest.cxx
      Modules/Registration/Common/test/itkMattesMutualInformationImageToImageMetricTest.cxx
      Modules/Core/Transform/include/itkBSplineDeformableTransform.h
      Modules/Core/Transform/include/itkBSplineDeformableTransform.txx
      Modules/Nonunit/Review/test/itkBSplineDeformableTransformInitializerTest1.cxx
      Modules/Nonunit/Review/test/itkBSplineDeformableTransformInitializerTest2.cxx
    </FileList>

    <!--**
    ** If the migration can be accomplished by a simple string
    ** substitution, then use the following construct to define
    ** the substitution rule.
    **
    ** <MigrationFix-Automatic>
    **   <Old>
    **     <![CDATA[MipsleledName]]>
    **   </Old>
    **   <New>
    **     <![CDATA[MisspelledName]]>
    **   </New>
    ** </MigrationFix-Automatic>
    **-->

    <!--**
    ** If the migration can NOT be accomplished by a simple string
    ** substitution, but potential problem spots can be identified,
    ** use the following construct to define a migration flag rule.
    **
    ** <MigrationFix-Manual>
    **   OldFunctionName
    ** </MigrationFix-Manual>
    **-->

</Change>
