C3DAffineTool messes up?

Hey there,

This is my workflow in nipype:

  • Realign using SPM, coregister with BBRegister (Freesurfer), convert to ITK format using C3DAffineTool, Register T1 to template using ANTs, merge BBRegister and ANTs matrices, and apply them to the mean image from the Realign step using AntsApplyTransform.

The registration works out just fine, but the transformation is horrible. I tried just transforming using the ITK converted BBRegister matrix and the result is faulty. Would love to know what I’m doing wrong here. Here’s my code:

bbreg = MapNode(BBRegister(),
                   # overwrite=True,
                    iterfield=['source_file'],
                    name='bbreg')
bbreg.inputs.init = 'header'
bbreg.inputs.contrast_type = 't2'
bbreg.inputs.subjects_dir = fs_sub_dir
bbreg.inputs.out_fsl_file = True
bbreg.inputs.epi_mask = True
bbreg.inputs.registered_file = True

preproc.connect([
    (infosource, bbreg, [('subject_id', 'subject_id')]),
    (realignUnwarp, bbreg, [('mean_image', 'source_file')]),
    ])


# Convert BBRegister transformation to ANTS ITK format.
convert2itk = MapNode(C3dAffineTool(),
                          iterfield=['source_file', 'transform_file'],
                          name='convert2itk')
convert2itk.inputs.fsl2ras = True
convert2itk.inputs.itk_transform = True

preproc.connect([
    (bbreg, convert2itk, [('out_fsl_file', 'transform_file')]),
    (realignUnwarp, convert2itk, [('mean_image', 'source_file')]),
    (brainextract, convert2itk, [('out_file', 'reference_file')])
    ])

# Concatenate the affine and ants transforms into a list.
merge = MapNode(Merge(2), overwrite=True, iterfield=['in2'], name='mergexfm')
preproc.connect(convert2itk, 'itk_transform', merge, 'in2')
preproc.connect(reg, 'composite_transform', merge, 'in1')

# Transform the mean image, first to anatomical then to target.
warpmean = MapNode(ants.ApplyTransforms(),
                       overwrite=False,
                    iterfield=['input_image', 'transforms'],
                    name='warpmean')
warpmean.inputs.input_image_type = 0
warpmean.inputs.interpolation = 'Linear'
warpmean.inputs.invert_transform_flags = [False, False]
warpmean.inputs.terminal_output = 'file'
warpmean.inputs.args = '--float'
warpmean.inputs.num_threads = 4
warpmean.plugin_args = {'sbatch_args': '-c%d' % 4}
warpmean.inputs.reference_image = template_image

preproc.connect([
    (realignUnwarp, warpmean, [('mean_image', 'input_image')]),
    (merge, warpmean, [('out', 'transforms')])
    ])

Another thing, the ANTs registration is also faulty. I’m using a quick registration procedure in order to test the pipeline. Here’s the code. Although if I use the same transform matrix to register the brain extracted T1 image it works. But using those same matrices on the BOLD images it fails. I’m very puzzled.

# ANTs registration for testing.
reg = Node(ants.Registration(), name='antsRegister')
reg.inputs.output_transform_prefix = "output_"
reg.inputs.transforms = ['Rigid', 'Affine', 'SyN']
reg.inputs.transform_parameters = [(0.1,), (0.1,), (0.2, 3.0, 0.0)]
reg.inputs.number_of_iterations =  [[10000, 0, 0]] * 2 + [[100, 0, 0]] # [[10000, 11110, 11110]] * 2 + [[100, 30, 20]]
reg.inputs.dimension = 3
reg.inputs.write_composite_transform = True
reg.inputs.collapse_output_transforms = True
reg.inputs.initial_moving_transform_com = True
reg.inputs.metric = ['Mattes'] * 2 + [['Mattes', 'CC']]
reg.inputs.metric_weight = [1] * 2 + [[0.5, 0.5]]
reg.inputs.radius_or_number_of_bins = [32] * 2 + [[32, 4]]
reg.inputs.sampling_strategy = ['Regular'] * 2 + [[None, None]]
reg.inputs.sampling_percentage = [0.1] * 2 + [[None, None]]
reg.inputs.convergence_threshold = [1.e-8] * 2 + [0]
reg.inputs.convergence_window_size = [20] * 2 + [5]
reg.inputs.smoothing_sigmas = [[4, 2, 1]] * 2 + [[1, 0.5, 0]]
reg.inputs.sigma_units = ['vox'] * 3
reg.inputs.shrink_factors = [[3, 2, 1]] * 2 + [[4, 2, 1]]
reg.inputs.use_estimate_learning_rate_once = [True] * 3
reg.inputs.use_histogram_matching = [False] * 2 + [True]
reg.inputs.winsorize_lower_quantile = 0.005
reg.inputs.winsorize_upper_quantile = 0.995
reg.inputs.float = True
reg.inputs.output_warped_image = 'output_warped_image.nii.gz'
reg.inputs.num_threads = 32
reg.plugin_args = {'sbatch_args': '-c%d' % 4}
reg.inputs.fixed_image = '/data/pt_nmc002/Template_ANTs/reg_2_mni_34-subs/antsreg/transform_Warped_brain.nii.gz'
preproc.connect(brainextract, 'out_file', reg, 'moving_image')

In this case the bold and T1 images are not matched in resolution or coregistered, hence the ANTs transform that works for the T1 will not work for the bold. This is why you will need the merged transforms.

This workflow implements the same registration that you are trying and perhaps you can check out the differences.

1 Like

Hey Satra,

Thanks for the tip. I messed up the T1 reference images. For the bbregister I used the freesurfer reconall brain image and for the applyTransform I used the extracted brain from fsl.BET which aren’t in the same space. If I use the reconall brain image for both steps it works.