Exemple #1
0
def register(src, dest, paramreg, param, i_step_str):
    # initiate default parameters of antsRegistration transformation
    ants_registration_params = {
        'rigid': '',
        'affine': '',
        'compositeaffine': '',
        'similarity': '',
        'translation': '',
        'bspline': ',10',
        'gaussiandisplacementfield': ',3,0',
        'bsplinedisplacementfield': ',5,10',
        'syn': ',3,0',
        'bsplinesyn': ',1,3'
    }
    output = ''  # default output if problem

    # display arguments
    sct.printv('Registration parameters:', param.verbose)
    sct.printv('  type ........... ' + paramreg.steps[i_step_str].type,
               param.verbose)
    sct.printv('  algo ........... ' + paramreg.steps[i_step_str].algo,
               param.verbose)
    sct.printv('  slicewise ...... ' + paramreg.steps[i_step_str].slicewise,
               param.verbose)
    sct.printv('  metric ......... ' + paramreg.steps[i_step_str].metric,
               param.verbose)
    sct.printv('  iter ........... ' + paramreg.steps[i_step_str].iter,
               param.verbose)
    sct.printv('  smooth ......... ' + paramreg.steps[i_step_str].smooth,
               param.verbose)
    sct.printv('  laplacian ...... ' + paramreg.steps[i_step_str].laplacian,
               param.verbose)
    sct.printv('  shrink ......... ' + paramreg.steps[i_step_str].shrink,
               param.verbose)
    sct.printv('  gradStep ....... ' + paramreg.steps[i_step_str].gradStep,
               param.verbose)
    sct.printv('  deformation .... ' + paramreg.steps[i_step_str].deformation,
               param.verbose)
    sct.printv('  init ........... ' + paramreg.steps[i_step_str].init,
               param.verbose)
    sct.printv('  poly ........... ' + paramreg.steps[i_step_str].poly,
               param.verbose)
    sct.printv('  dof ............ ' + paramreg.steps[i_step_str].dof,
               param.verbose)
    sct.printv('  smoothWarpXY ... ' + paramreg.steps[i_step_str].smoothWarpXY,
               param.verbose)

    # set metricSize
    if paramreg.steps[i_step_str].metric == 'MI':
        metricSize = '32'  # corresponds to number of bins
    else:
        metricSize = '4'  # corresponds to radius (for CC, MeanSquares...)

    # set masking
    if param.fname_mask:
        fname_mask = 'mask.nii.gz'
        masking = ['-x', 'mask.nii.gz']
    else:
        fname_mask = ''
        masking = []

    if paramreg.steps[i_step_str].algo == 'slicereg':
        # check if user used type=label
        if paramreg.steps[i_step_str].type == 'label':
            sct.printv(
                '\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg',
                1, 'error')
        else:
            # Find the min (and max) z-slice index below which (and above which) slices only have voxels below a given
            # threshold.
            list_fname = [src, dest]
            if not masking == []:
                list_fname.append(fname_mask)
            zmin_global, zmax_global = 0, 99999  # this is assuming that typical image has less slice than 99999
            for fname in list_fname:
                im = Image(fname)
                zmin, zmax = msct_image.find_zmin_zmax(im, threshold=0.1)
                if zmin > zmin_global:
                    zmin_global = zmin
                if zmax < zmax_global:
                    zmax_global = zmax
            # crop images (see issue #293)
            src_crop = sct.add_suffix(src, '_crop')
            msct_image.spatial_crop(Image(src),
                                    dict(
                                        ((2, (zmin_global,
                                              zmax_global)), ))).save(src_crop)
            dest_crop = sct.add_suffix(dest, '_crop')
            msct_image.spatial_crop(Image(dest),
                                    dict(((2,
                                           (zmin_global,
                                            zmax_global)), ))).save(dest_crop)
            # update variables
            src = src_crop
            dest = dest_crop
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            # estimate transfo
            # TODO fixup isct_ants* parsers
            cmd = [
                'isct_antsSliceRegularizedRegistration',
                '-t',
                'Translation[' + paramreg.steps[i_step_str].gradStep + ']',
                '-m',
                paramreg.steps[i_step_str].metric + '[' + dest + ',' + src +
                ',1,' + metricSize + ',Regular,0.2]',
                '-p',
                paramreg.steps[i_step_str].poly,
                '-i',
                paramreg.steps[i_step_str].iter,
                '-f',
                paramreg.steps[i_step_str].shrink,
                '-s',
                paramreg.steps[i_step_str].smooth,
                '-v',
                '1',  # verbose (verbose=2 does not exist, so we force it to 1)
                '-o',
                '[step' + i_step_str + ',' + scr_regStep +
                ']',  # here the warp name is stage10 because
                # antsSliceReg add "Warp"
            ] + masking
            warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
            # run command
            status, output = sct.run(cmd, param.verbose)

    # ANTS 3d
    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params \
            and paramreg.steps[i_step_str].slicewise == '0':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            # Pad the destination image (because ants doesn't deform the extremities)
            # N.B. no need to pad if iter = 0
            if not paramreg.steps[i_step_str].iter == '0':
                dest_pad = sct.add_suffix(dest, '_pad')
                sct.run([
                    'sct_image', '-i', dest, '-o', dest_pad, '-pad',
                    '0,0,' + str(param.padding)
                ])
                dest = dest_pad
            # apply Laplacian filter
            if not paramreg.steps[i_step_str].laplacian == '0':
                sct.printv('\nApply Laplacian filter', param.verbose)
                sct.run([
                    'sct_maths', '-i', src, '-laplacian',
                    paramreg.steps[i_step_str].laplacian + ',' +
                    paramreg.steps[i_step_str].laplacian + ',0', '-o',
                    sct.add_suffix(src, '_laplacian')
                ])
                sct.run([
                    'sct_maths', '-i', dest, '-laplacian',
                    paramreg.steps[i_step_str].laplacian + ',' +
                    paramreg.steps[i_step_str].laplacian + ',0', '-o',
                    sct.add_suffix(dest, '_laplacian')
                ])
                src = sct.add_suffix(src, '_laplacian')
                dest = sct.add_suffix(dest, '_laplacian')
            # Estimate transformation
            sct.printv('\nEstimate transformation', param.verbose)
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            # TODO fixup isct_ants* parsers
            cmd = [
                'isct_antsRegistration',
                '--dimensionality',
                '3',
                '--transform',
                paramreg.steps[i_step_str].algo + '[' +
                paramreg.steps[i_step_str].gradStep + ants_registration_params[
                    paramreg.steps[i_step_str].algo.lower()] + ']',
                '--metric',
                paramreg.steps[i_step_str].metric + '[' + dest + ',' + src +
                ',1,' + metricSize + ']',
                '--convergence',
                paramreg.steps[i_step_str].iter,
                '--shrink-factors',
                paramreg.steps[i_step_str].shrink,
                '--smoothing-sigmas',
                paramreg.steps[i_step_str].smooth + 'mm',
                '--restrict-deformation',
                paramreg.steps[i_step_str].deformation,
                '--output',
                '[step' + i_step_str + ',' + scr_regStep + ']',
                '--interpolation',
                'BSpline[3]',
                '--verbose',
                '1',
            ] + masking
            # add init translation
            if not paramreg.steps[i_step_str].init == '':
                init_dict = {
                    'geometric': '0',
                    'centermass': '1',
                    'origin': '2'
                }
                cmd += [
                    '-r', '[' + dest + ',' + src + ',' +
                    init_dict[paramreg.steps[i_step_str].init] + ']'
                ]
            # run command
            status, output = sct.run(cmd, param.verbose)
            # get appropriate file name for transformation
            if paramreg.steps[i_step_str].algo in [
                    'rigid', 'affine', 'translation'
            ]:
                warp_forward_out = 'step' + i_step_str + '0GenericAffine.mat'
                warp_inverse_out = '-step' + i_step_str + '0GenericAffine.mat'
            else:
                warp_forward_out = 'step' + i_step_str + '0Warp.nii.gz'
                warp_inverse_out = 'step' + i_step_str + '0InverseWarp.nii.gz'

    # ANTS 2d
    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params \
            and paramreg.steps[i_step_str].slicewise == '1':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            from msct_register import register_slicewise
            # if shrink!=1, force it to be 1 (otherwise, it generates a wrong 3d warping field). TODO: fix that!
            if not paramreg.steps[i_step_str].shrink == '1':
                sct.printv(
                    '\nWARNING: when using slicewise with SyN or BSplineSyN, shrink factor needs to be one. '
                    'Forcing shrink=1.', 1, 'warning')
                paramreg.steps[i_step_str].shrink = '1'
            warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
            register_slicewise(
                src,
                dest,
                paramreg=paramreg.steps[i_step_str],
                fname_mask=fname_mask,
                warp_forward_out=warp_forward_out,
                warp_inverse_out=warp_inverse_out,
                ants_registration_params=ants_registration_params,
                remove_temp_files=param.remove_temp_files,
                verbose=param.verbose)

    # slice-wise transfo
    elif paramreg.steps[i_step_str].algo in [
            'centermass', 'centermassrot', 'columnwise'
    ]:
        # if type=im, sends warning
        if paramreg.steps[i_step_str].type == 'im':
            sct.printv(
                '\nWARNING: algo ' + paramreg.steps[i_step_str].algo +
                ' should be used with type=seg.\n', 1, 'warning')
        # if type=label, exit with error
        elif paramreg.steps[i_step_str].type == 'label':
            sct.printv(
                '\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg',
                1, 'error')
        # check if user provided a mask-- if so, inform it will be ignored
        if not fname_mask == '':
            sct.printv(
                '\nWARNING: algo ' + paramreg.steps[i_step_str].algo +
                ' will ignore the provided mask.\n', 1, 'warning')
        # smooth data
        if not paramreg.steps[i_step_str].smooth == '0':
            sct.printv('\nSmooth data', param.verbose)
            sct.run([
                'sct_maths', '-i', src, '-smooth',
                paramreg.steps[i_step_str].smooth + ',' +
                paramreg.steps[i_step_str].smooth + ',0', '-o',
                sct.add_suffix(src, '_smooth')
            ])
            sct.run([
                'sct_maths', '-i', dest, '-smooth',
                paramreg.steps[i_step_str].smooth + ',' +
                paramreg.steps[i_step_str].smooth + ',0', '-o',
                sct.add_suffix(dest, '_smooth')
            ])
            src = sct.add_suffix(src, '_smooth')
            dest = sct.add_suffix(dest, '_smooth')
        from msct_register import register_slicewise
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        register_slicewise(src,
                           dest,
                           paramreg=paramreg.steps[i_step_str],
                           fname_mask=fname_mask,
                           warp_forward_out=warp_forward_out,
                           warp_inverse_out=warp_inverse_out,
                           ants_registration_params=ants_registration_params,
                           remove_temp_files=param.remove_temp_files,
                           verbose=param.verbose)

    else:
        sct.printv(
            '\nERROR: algo ' + paramreg.steps[i_step_str].algo +
            ' does not exist. Exit program\n', 1, 'error')

    # landmark-based registration
    if paramreg.steps[i_step_str].type in ['label']:
        # check if user specified ilabel and dlabel
        # TODO
        warp_forward_out = 'step' + i_step_str + '0GenericAffine.txt'
        warp_inverse_out = '-step' + i_step_str + '0GenericAffine.txt'
        from msct_register_landmarks import register_landmarks
        register_landmarks(src,
                           dest,
                           paramreg.steps[i_step_str].dof,
                           fname_affine=warp_forward_out,
                           verbose=param.verbose)

    if not os.path.isfile(warp_forward_out):
        # no forward warping field for rigid and affine
        sct.printv(
            '\nERROR: file ' + warp_forward_out +
            ' doesn\'t exist (or is not a file).\n' + output +
            '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    elif not os.path.isfile(warp_inverse_out) and \
            paramreg.steps[i_step_str].algo not in ['rigid', 'affine', 'translation'] and \
            paramreg.steps[i_step_str].type not in ['label']:
        # no inverse warping field for rigid and affine
        sct.printv(
            '\nERROR: file ' + warp_inverse_out +
            ' doesn\'t exist (or is not a file).\n' + output +
            '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    else:
        # rename warping fields
        if (paramreg.steps[i_step_str].algo.lower()
                in ['rigid', 'affine', 'translation']
                and paramreg.steps[i_step_str].slicewise == '0'):
            # if ANTs is used with affine/rigid --> outputs .mat file
            warp_forward = 'warp_forward_' + i_step_str + '.mat'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_' + i_step_str + '.mat'
        elif paramreg.steps[i_step_str].type in ['label']:
            # if label-based registration is used --> outputs .txt file
            warp_forward = 'warp_forward_' + i_step_str + '.txt'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_' + i_step_str + '.txt'
        else:
            warp_forward = 'warp_forward_' + i_step_str + '.nii.gz'
            warp_inverse = 'warp_inverse_' + i_step_str + '.nii.gz'
            os.rename(warp_forward_out, warp_forward)
            os.rename(warp_inverse_out, warp_inverse)

    return warp_forward, warp_inverse
Exemple #2
0
def register(src, dest, paramreg, param, i_step_str):

    # initiate default parameters of antsRegistration transformation
    ants_registration_params = {'rigid': '', 'affine': '', 'compositeaffine': '', 'similarity': '', 'translation': '',
                                'bspline': ',10', 'gaussiandisplacementfield': ',3,0',
                                'bsplinedisplacementfield': ',5,10', 'syn': ',3,0', 'bsplinesyn': ',1,3'}
    output = ''  # default output if problem

    # display arguments
    sct.printv('Registration parameters:', param.verbose)
    sct.printv('  type ........... '+paramreg.steps[i_step_str].type, param.verbose)
    sct.printv('  algo ........... '+paramreg.steps[i_step_str].algo, param.verbose)
    sct.printv('  slicewise ...... '+paramreg.steps[i_step_str].slicewise, param.verbose)
    sct.printv('  metric ......... '+paramreg.steps[i_step_str].metric, param.verbose)
    sct.printv('  iter ........... '+paramreg.steps[i_step_str].iter, param.verbose)
    sct.printv('  smooth ......... '+paramreg.steps[i_step_str].smooth, param.verbose)
    sct.printv('  laplacian ...... '+paramreg.steps[i_step_str].laplacian, param.verbose)
    sct.printv('  shrink ......... '+paramreg.steps[i_step_str].shrink, param.verbose)
    sct.printv('  gradStep ....... '+paramreg.steps[i_step_str].gradStep, param.verbose)
    sct.printv('  init ........... '+paramreg.steps[i_step_str].init, param.verbose)
    sct.printv('  poly ........... '+paramreg.steps[i_step_str].poly, param.verbose)
    sct.printv('  dof ............ '+paramreg.steps[i_step_str].dof, param.verbose)
    sct.printv('  smoothWarpXY ... '+paramreg.steps[i_step_str].smoothWarpXY, param.verbose)

    # set metricSize
    if paramreg.steps[i_step_str].metric == 'MI':
        metricSize = '32'  # corresponds to number of bins
    else:
        metricSize = '4'  # corresponds to radius (for CC, MeanSquares...)

    # set masking
    if param.fname_mask:
        fname_mask = 'mask.nii.gz'
        masking = '-x mask.nii.gz'
    else:
        fname_mask = ''
        masking = ''

    if paramreg.steps[i_step_str].algo == 'slicereg':
        # check if user used type=label
        if paramreg.steps[i_step_str].type == 'label':
            sct.printv('\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg', 1, 'error')
        else:
            from msct_image import find_zmin_zmax
            # threshold images (otherwise, automatic crop does not work -- see issue #293)
            src_th = sct.add_suffix(src, '_th')
            from msct_image import Image
            nii = Image(src)
            data = nii.data
            data[data < 0.1] = 0
            nii.data = data
            nii.setFileName(src_th)
            nii.save()
            # sct.run(fsloutput+'fslmaths '+src+' -thr 0.1 '+src_th, param.verbose)
            dest_th = sct.add_suffix(dest, '_th')
            nii = Image(dest)
            data = nii.data
            data[data < 0.1] = 0
            nii.data = data
            nii.setFileName(dest_th)
            nii.save()
            # sct.run(fsloutput+'fslmaths '+dest+' -thr 0.1 '+dest_th, param.verbose)
            # find zmin and zmax
            zmin_src, zmax_src = find_zmin_zmax(src_th)
            zmin_dest, zmax_dest = find_zmin_zmax(dest_th)
            zmin_total = max([zmin_src, zmin_dest])
            zmax_total = min([zmax_src, zmax_dest])
            # crop data
            src_crop = sct.add_suffix(src, '_crop')
            sct.run('sct_crop_image -i '+src+' -o '+src_crop+' -dim 2 -start '+str(zmin_total)+' -end '+str(zmax_total), param.verbose)
            dest_crop = sct.add_suffix(dest, '_crop')
            sct.run('sct_crop_image -i '+dest+' -o '+dest_crop+' -dim 2 -start '+str(zmin_total)+' -end '+str(zmax_total), param.verbose)
            # update variables
            src = src_crop
            dest = dest_crop
            scr_regStep = sct.add_suffix(src, '_regStep'+i_step_str)
            # estimate transfo
            cmd = ('isct_antsSliceRegularizedRegistration '
                   '-t Translation[0.5] '
                   '-m '+paramreg.steps[i_step_str].metric+'['+dest+','+src+',1,'+metricSize+',Regular,0.2] '
                   '-p '+paramreg.steps[i_step_str].poly+' '
                   '-i '+paramreg.steps[i_step_str].iter+' '
                   '-f 1 '
                   '-s '+paramreg.steps[i_step_str].smooth+' '
                   '-v 1 '  # verbose (verbose=2 does not exist, so we force it to 1)
                   '-o [step'+i_step_str+','+scr_regStep+'] '  # here the warp name is stage10 because antsSliceReg add "Warp"
                   +masking)
            warp_forward_out = 'step'+i_step_str+'Warp.nii.gz'
            warp_inverse_out = 'step'+i_step_str+'InverseWarp.nii.gz'
            # run command
            status, output = sct.run(cmd, param.verbose)

    # ANTS 3d
    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params and paramreg.steps[i_step_str].slicewise == '0':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            # Pad the destination image (because ants doesn't deform the extremities)
            # N.B. no need to pad if iter = 0
            if not paramreg.steps[i_step_str].iter == '0':
                dest_pad = sct.add_suffix(dest, '_pad')
                sct.run('sct_image -i '+dest+' -o '+dest_pad+' -pad 0,0,'+str(param.padding))
                dest = dest_pad
            # apply Laplacian filter
            if not paramreg.steps[i_step_str].laplacian == '0':
                sct.printv('\nApply Laplacian filter', param.verbose)
                sct.run('sct_maths -i '+src+' -laplacian '+paramreg.steps[i_step_str].laplacian+','+paramreg.steps[i_step_str].laplacian+',0 -o '+sct.add_suffix(src, '_laplacian'))
                sct.run('sct_maths -i '+dest+' -laplacian '+paramreg.steps[i_step_str].laplacian+','+paramreg.steps[i_step_str].laplacian+',0 -o '+sct.add_suffix(dest, '_laplacian'))
                src = sct.add_suffix(src, '_laplacian')
                dest = sct.add_suffix(dest, '_laplacian')
            # Estimate transformation
            sct.printv('\nEstimate transformation', param.verbose)
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            cmd = ('isct_antsRegistration '
                   '--dimensionality 3 '
                   '--transform '+paramreg.steps[i_step_str].algo+'['+paramreg.steps[i_step_str].gradStep +
                   ants_registration_params[paramreg.steps[i_step_str].algo.lower()]+'] '
                   '--metric '+paramreg.steps[i_step_str].metric+'['+dest+','+src+',1,'+metricSize+'] '
                   '--convergence '+paramreg.steps[i_step_str].iter+' '
                   '--shrink-factors '+paramreg.steps[i_step_str].shrink+' '
                   '--smoothing-sigmas '+paramreg.steps[i_step_str].smooth+'mm '
                   '--restrict-deformation 1x1x0 '
                   '--output [step'+i_step_str+','+scr_regStep+'] '
                   '--interpolation BSpline[3] '
                   +masking)
            # add verbose
            if param.verbose >= 1:
                cmd += ' --verbose 1'
            # add init translation
            if not paramreg.steps[i_step_str].init == '':
                init_dict = {'geometric': '0', 'centermass': '1', 'origin': '2'}
                cmd += ' -r ['+dest+','+src+','+init_dict[paramreg.steps[i_step_str].init]+']'
            # run command
            status, output = sct.run(cmd, param.verbose)
            # get appropriate file name for transformation
            if paramreg.steps[i_step_str].algo in ['rigid', 'affine', 'translation']:
                warp_forward_out = 'step'+i_step_str+'0GenericAffine.mat'
                warp_inverse_out = '-step'+i_step_str+'0GenericAffine.mat'
            else:
                warp_forward_out = 'step'+i_step_str+'0Warp.nii.gz'
                warp_inverse_out = 'step'+i_step_str+'0InverseWarp.nii.gz'

    # ANTS 2d
    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params and paramreg.steps[i_step_str].slicewise == '1':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            from msct_register import register_slicewise
            # if shrink!=1, force it to be 1 (otherwise, it generates a wrong 3d warping field). TODO: fix that!
            if not paramreg.steps[i_step_str].shrink == '1':
                sct.printv('\nWARNING: when using slicewise with SyN or BSplineSyN, shrink factor needs to be one. Forcing shrink=1.', 1, 'warning')
                paramreg.steps[i_step_str].shrink = '1'
            warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
            register_slicewise(src,
                               dest,
                               paramreg=paramreg.steps[i_step_str],
                               fname_mask=fname_mask,
                               warp_forward_out=warp_forward_out,
                               warp_inverse_out=warp_inverse_out,
                               ants_registration_params=ants_registration_params,
                               path_qc=param.path_qc,
                               verbose=param.verbose)

    # slice-wise transfo
    elif paramreg.steps[i_step_str].algo in ['centermass', 'centermassrot', 'columnwise']:
        # if type=im, sends warning
        if paramreg.steps[i_step_str].type == 'im':
            sct.printv('\nWARNING: algo '+paramreg.steps[i_step_str].algo+' should be used with type=seg.\n', 1, 'warning')
        # if type=label, exit with error
        elif paramreg.steps[i_step_str].type == 'label':
            sct.printv('\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg', 1, 'error')
        # check if user provided a mask-- if so, inform it will be ignored
        if not fname_mask == '':
            sct.printv('\nWARNING: algo '+paramreg.steps[i_step_str].algo+' will ignore the provided mask.\n', 1, 'warning')
        # smooth data
        if not paramreg.steps[i_step_str].smooth == '0':
            sct.printv('\nSmooth data', param.verbose)
            sct.run('sct_maths -i '+src+' -smooth '+paramreg.steps[i_step_str].smooth+','+paramreg.steps[i_step_str].smooth+',0 -o '+sct.add_suffix(src, '_smooth'))
            sct.run('sct_maths -i '+dest+' -smooth '+paramreg.steps[i_step_str].smooth+','+paramreg.steps[i_step_str].smooth+',0 -o '+sct.add_suffix(dest, '_smooth'))
            src = sct.add_suffix(src, '_smooth')
            dest = sct.add_suffix(dest, '_smooth')
        from msct_register import register_slicewise
        warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
        register_slicewise(src,
                           dest,
                           paramreg=paramreg.steps[i_step_str],
                           fname_mask=fname_mask,
                           warp_forward_out=warp_forward_out,
                           warp_inverse_out=warp_inverse_out,
                           ants_registration_params=ants_registration_params,
                           path_qc=param.path_qc,
                           verbose=param.verbose)

    else:
        sct.printv('\nERROR: algo '+paramreg.steps[i_step_str].algo+' does not exist. Exit program\n', 1, 'error')

    # landmark-based registration
    if paramreg.steps[i_step_str].type in ['label']:
        # check if user specified ilabel and dlabel
        # TODO
        warp_forward_out = 'step' + i_step_str + '0GenericAffine.txt'
        warp_inverse_out = '-step' + i_step_str + '0GenericAffine.txt'
        from msct_register_landmarks import register_landmarks
        register_landmarks(src,
                           dest,
                           paramreg.steps[i_step_str].dof,
                           fname_affine=warp_forward_out,
                           verbose=param.verbose,
                           path_qc=param.path_qc)

    if not os.path.isfile(warp_forward_out):
        # no forward warping field for rigid and affine
        sct.printv('\nERROR: file '+warp_forward_out+' doesn\'t exist (or is not a file).\n' + output +
                   '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    elif not os.path.isfile(warp_inverse_out) and paramreg.steps[i_step_str].algo not in ['rigid', 'affine', 'translation'] and paramreg.steps[i_step_str].type not in ['label']:
        # no inverse warping field for rigid and affine
        sct.printv('\nERROR: file '+warp_inverse_out+' doesn\'t exist (or is not a file).\n' + output +
                   '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    else:
        # rename warping fields
        if (paramreg.steps[i_step_str].algo.lower() in ['rigid', 'affine', 'translation'] and paramreg.steps[i_step_str].slicewise == '0'):
            # if ANTs is used with affine/rigid --> outputs .mat file
            warp_forward = 'warp_forward_'+i_step_str+'.mat'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_'+i_step_str+'.mat'
        elif paramreg.steps[i_step_str].type in ['label']:
            # if label-based registration is used --> outputs .txt file
            warp_forward = 'warp_forward_'+i_step_str+'.txt'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_'+i_step_str+'.txt'
        else:
            warp_forward = 'warp_forward_'+i_step_str+'.nii.gz'
            warp_inverse = 'warp_inverse_'+i_step_str+'.nii.gz'
            os.rename(warp_forward_out, warp_forward)
            os.rename(warp_inverse_out, warp_inverse)

    return warp_forward, warp_inverse
def register(src, dest, paramreg, param, i_step_str):

    # initiate default parameters of antsRegistration transformation
    ants_registration_params = {
        'rigid': '',
        'affine': '',
        'compositeaffine': '',
        'similarity': '',
        'translation': '',
        'bspline': ',10',
        'gaussiandisplacementfield': ',3,0',
        'bsplinedisplacementfield': ',5,10',
        'syn': ',3,0',
        'bsplinesyn': ',1,3'
    }
    output = ''  # default output if problem

    # display arguments
    sct.printv('Registration parameters:', param.verbose)
    sct.printv('  type ........... ' + paramreg.steps[i_step_str].type,
               param.verbose)
    sct.printv('  algo ........... ' + paramreg.steps[i_step_str].algo,
               param.verbose)
    sct.printv('  slicewise ...... ' + paramreg.steps[i_step_str].slicewise,
               param.verbose)
    sct.printv('  metric ......... ' + paramreg.steps[i_step_str].metric,
               param.verbose)
    sct.printv('  iter ........... ' + paramreg.steps[i_step_str].iter,
               param.verbose)
    sct.printv('  smooth ......... ' + paramreg.steps[i_step_str].smooth,
               param.verbose)
    sct.printv('  laplacian ...... ' + paramreg.steps[i_step_str].laplacian,
               param.verbose)
    sct.printv('  shrink ......... ' + paramreg.steps[i_step_str].shrink,
               param.verbose)
    sct.printv('  gradStep ....... ' + paramreg.steps[i_step_str].gradStep,
               param.verbose)
    sct.printv('  deformation .... ' + paramreg.steps[i_step_str].deformation,
               param.verbose)
    sct.printv('  init ........... ' + paramreg.steps[i_step_str].init,
               param.verbose)
    sct.printv('  poly ........... ' + paramreg.steps[i_step_str].poly,
               param.verbose)
    sct.printv('  dof ............ ' + paramreg.steps[i_step_str].dof,
               param.verbose)
    sct.printv('  smoothWarpXY ... ' + paramreg.steps[i_step_str].smoothWarpXY,
               param.verbose)

    # set metricSize
    if paramreg.steps[i_step_str].metric == 'MI':
        metricSize = '32'  # corresponds to number of bins
    else:
        metricSize = '4'  # corresponds to radius (for CC, MeanSquares...)

    # set masking
    if param.fname_mask:
        fname_mask = 'mask.nii.gz'
        masking = '-x mask.nii.gz'
    else:
        fname_mask = ''
        masking = ''

    if paramreg.steps[i_step_str].algo == 'slicereg':
        # check if user used type=label
        if paramreg.steps[i_step_str].type == 'label':
            sct.printv(
                '\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg',
                1, 'error')
        else:
            from msct_image import find_zmin_zmax
            # threshold images (otherwise, automatic crop does not work -- see issue #293)
            src_th = sct.add_suffix(src, '_th')
            from msct_image import Image
            nii = Image(src)
            data = nii.data
            data[data < 0.1] = 0
            nii.data = data
            nii.setFileName(src_th)
            nii.save()
            # sct.run(fsloutput+'fslmaths '+src+' -thr 0.1 '+src_th, param.verbose)
            dest_th = sct.add_suffix(dest, '_th')
            nii = Image(dest)
            data = nii.data
            data[data < 0.1] = 0
            nii.data = data
            nii.setFileName(dest_th)
            nii.save()
            # sct.run(fsloutput+'fslmaths '+dest+' -thr 0.1 '+dest_th, param.verbose)
            # find zmin and zmax
            zmin_src, zmax_src = find_zmin_zmax(src_th)
            zmin_dest, zmax_dest = find_zmin_zmax(dest_th)
            zmin_total = max([zmin_src, zmin_dest])
            zmax_total = min([zmax_src, zmax_dest])
            # crop data
            src_crop = sct.add_suffix(src, '_crop')
            sct.run(
                'sct_crop_image -i ' + src + ' -o ' + src_crop +
                ' -dim 2 -start ' + str(zmin_total) + ' -end ' +
                str(zmax_total), param.verbose)
            dest_crop = sct.add_suffix(dest, '_crop')
            sct.run(
                'sct_crop_image -i ' + dest + ' -o ' + dest_crop +
                ' -dim 2 -start ' + str(zmin_total) + ' -end ' +
                str(zmax_total), param.verbose)
            # update variables
            src = src_crop
            dest = dest_crop
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            # estimate transfo
            cmd = (
                'isct_antsSliceRegularizedRegistration '
                '-t Translation[' + paramreg.steps[i_step_str].gradStep + '] '
                '-m ' + paramreg.steps[i_step_str].metric + '[' + dest + ',' +
                src + ',1,' + metricSize + ',Regular,0.2] '
                '-p ' + paramreg.steps[i_step_str].poly + ' '
                '-i ' + paramreg.steps[i_step_str].iter + ' '
                '-f ' + paramreg.steps[i_step_str].shrink + ' '
                '-s ' + paramreg.steps[i_step_str].smooth + ' '
                '-v 1 '  # verbose (verbose=2 does not exist, so we force it to 1)
                '-o [step' + i_step_str + ',' + scr_regStep +
                '] '  # here the warp name is stage10 because antsSliceReg add "Warp"
                + masking)
            warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
            # run command
            status, output = sct.run(cmd, param.verbose)

    # ANTS 3d
    elif paramreg.steps[i_step_str].algo.lower(
    ) in ants_registration_params and paramreg.steps[
            i_step_str].slicewise == '0':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            # Pad the destination image (because ants doesn't deform the extremities)
            # N.B. no need to pad if iter = 0
            if not paramreg.steps[i_step_str].iter == '0':
                dest_pad = sct.add_suffix(dest, '_pad')
                sct.run('sct_image -i ' + dest + ' -o ' + dest_pad +
                        ' -pad 0,0,' + str(param.padding))
                dest = dest_pad
            # apply Laplacian filter
            if not paramreg.steps[i_step_str].laplacian == '0':
                sct.printv('\nApply Laplacian filter', param.verbose)
                sct.run('sct_maths -i ' + src + ' -laplacian ' +
                        paramreg.steps[i_step_str].laplacian + ',' +
                        paramreg.steps[i_step_str].laplacian + ',0 -o ' +
                        sct.add_suffix(src, '_laplacian'))
                sct.run('sct_maths -i ' + dest + ' -laplacian ' +
                        paramreg.steps[i_step_str].laplacian + ',' +
                        paramreg.steps[i_step_str].laplacian + ',0 -o ' +
                        sct.add_suffix(dest, '_laplacian'))
                src = sct.add_suffix(src, '_laplacian')
                dest = sct.add_suffix(dest, '_laplacian')
            # Estimate transformation
            sct.printv('\nEstimate transformation', param.verbose)
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            cmd = ('isct_antsRegistration '
                   '--dimensionality 3 '
                   '--transform ' + paramreg.steps[i_step_str].algo + '[' +
                   paramreg.steps[i_step_str].gradStep +
                   ants_registration_params[
                       paramreg.steps[i_step_str].algo.lower()] + '] '
                   '--metric ' + paramreg.steps[i_step_str].metric + '[' +
                   dest + ',' + src + ',1,' + metricSize + '] '
                   '--convergence ' + paramreg.steps[i_step_str].iter + ' '
                   '--shrink-factors ' + paramreg.steps[i_step_str].shrink +
                   ' '
                   '--smoothing-sigmas ' + paramreg.steps[i_step_str].smooth +
                   'mm '
                   '--restrict-deformation ' +
                   paramreg.steps[i_step_str].deformation + ' '
                   '--output [step' + i_step_str + ',' + scr_regStep + '] '
                   '--interpolation BSpline[3] '
                   '--verbose 1 ' + masking)
            # add init translation
            if not paramreg.steps[i_step_str].init == '':
                init_dict = {
                    'geometric': '0',
                    'centermass': '1',
                    'origin': '2'
                }
                cmd += ' -r [' + dest + ',' + src + ',' + init_dict[
                    paramreg.steps[i_step_str].init] + ']'
            # run command
            status, output = sct.run(cmd, param.verbose)
            # get appropriate file name for transformation
            if paramreg.steps[i_step_str].algo in [
                    'rigid', 'affine', 'translation'
            ]:
                warp_forward_out = 'step' + i_step_str + '0GenericAffine.mat'
                warp_inverse_out = '-step' + i_step_str + '0GenericAffine.mat'
            else:
                warp_forward_out = 'step' + i_step_str + '0Warp.nii.gz'
                warp_inverse_out = 'step' + i_step_str + '0InverseWarp.nii.gz'

    # ANTS 2d
    elif paramreg.steps[i_step_str].algo.lower(
    ) in ants_registration_params and paramreg.steps[
            i_step_str].slicewise == '1':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            from msct_register import register_slicewise
            # if shrink!=1, force it to be 1 (otherwise, it generates a wrong 3d warping field). TODO: fix that!
            if not paramreg.steps[i_step_str].shrink == '1':
                sct.printv(
                    '\nWARNING: when using slicewise with SyN or BSplineSyN, shrink factor needs to be one. Forcing shrink=1.',
                    1, 'warning')
                paramreg.steps[i_step_str].shrink = '1'
            warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
            register_slicewise(
                src,
                dest,
                paramreg=paramreg.steps[i_step_str],
                fname_mask=fname_mask,
                warp_forward_out=warp_forward_out,
                warp_inverse_out=warp_inverse_out,
                ants_registration_params=ants_registration_params,
                path_qc=param.path_qc,
                verbose=param.verbose)

    # slice-wise transfo
    elif paramreg.steps[i_step_str].algo in [
            'centermass', 'centermassrot', 'columnwise'
    ]:
        # if type=im, sends warning
        if paramreg.steps[i_step_str].type == 'im':
            sct.printv(
                '\nWARNING: algo ' + paramreg.steps[i_step_str].algo +
                ' should be used with type=seg.\n', 1, 'warning')
        # if type=label, exit with error
        elif paramreg.steps[i_step_str].type == 'label':
            sct.printv(
                '\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg',
                1, 'error')
        # check if user provided a mask-- if so, inform it will be ignored
        if not fname_mask == '':
            sct.printv(
                '\nWARNING: algo ' + paramreg.steps[i_step_str].algo +
                ' will ignore the provided mask.\n', 1, 'warning')
        # smooth data
        if not paramreg.steps[i_step_str].smooth == '0':
            sct.printv('\nSmooth data', param.verbose)
            sct.run('sct_maths -i ' + src + ' -smooth ' +
                    paramreg.steps[i_step_str].smooth + ',' +
                    paramreg.steps[i_step_str].smooth + ',0 -o ' +
                    sct.add_suffix(src, '_smooth'))
            sct.run('sct_maths -i ' + dest + ' -smooth ' +
                    paramreg.steps[i_step_str].smooth + ',' +
                    paramreg.steps[i_step_str].smooth + ',0 -o ' +
                    sct.add_suffix(dest, '_smooth'))
            src = sct.add_suffix(src, '_smooth')
            dest = sct.add_suffix(dest, '_smooth')
        from msct_register import register_slicewise
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        register_slicewise(src,
                           dest,
                           paramreg=paramreg.steps[i_step_str],
                           fname_mask=fname_mask,
                           warp_forward_out=warp_forward_out,
                           warp_inverse_out=warp_inverse_out,
                           ants_registration_params=ants_registration_params,
                           path_qc=param.path_qc,
                           verbose=param.verbose)

    else:
        sct.printv(
            '\nERROR: algo ' + paramreg.steps[i_step_str].algo +
            ' does not exist. Exit program\n', 1, 'error')

    # landmark-based registration
    if paramreg.steps[i_step_str].type in ['label']:
        # check if user specified ilabel and dlabel
        # TODO
        warp_forward_out = 'step' + i_step_str + '0GenericAffine.txt'
        warp_inverse_out = '-step' + i_step_str + '0GenericAffine.txt'
        from msct_register_landmarks import register_landmarks
        register_landmarks(src,
                           dest,
                           paramreg.steps[i_step_str].dof,
                           fname_affine=warp_forward_out,
                           verbose=param.verbose,
                           path_qc=param.path_qc)

    if not os.path.isfile(warp_forward_out):
        # no forward warping field for rigid and affine
        sct.printv(
            '\nERROR: file ' + warp_forward_out +
            ' doesn\'t exist (or is not a file).\n' + output +
            '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    elif not os.path.isfile(
            warp_inverse_out) and paramreg.steps[i_step_str].algo not in [
                'rigid', 'affine', 'translation'
            ] and paramreg.steps[i_step_str].type not in ['label']:
        # no inverse warping field for rigid and affine
        sct.printv(
            '\nERROR: file ' + warp_inverse_out +
            ' doesn\'t exist (or is not a file).\n' + output +
            '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    else:
        # rename warping fields
        if (paramreg.steps[i_step_str].algo.lower()
                in ['rigid', 'affine', 'translation']
                and paramreg.steps[i_step_str].slicewise == '0'):
            # if ANTs is used with affine/rigid --> outputs .mat file
            warp_forward = 'warp_forward_' + i_step_str + '.mat'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_' + i_step_str + '.mat'
        elif paramreg.steps[i_step_str].type in ['label']:
            # if label-based registration is used --> outputs .txt file
            warp_forward = 'warp_forward_' + i_step_str + '.txt'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_' + i_step_str + '.txt'
        else:
            warp_forward = 'warp_forward_' + i_step_str + '.nii.gz'
            warp_inverse = 'warp_inverse_' + i_step_str + '.nii.gz'
            os.rename(warp_forward_out, warp_forward)
            os.rename(warp_inverse_out, warp_inverse)

    return warp_forward, warp_inverse
def register(src, dest, paramreg, param, i_step_str):
    # initiate default parameters of antsRegistration transformation
    ants_registration_params = {'rigid': '', 'affine': '', 'compositeaffine': '', 'similarity': '', 'translation': '',
                                'bspline': ',10', 'gaussiandisplacementfield': ',3,0',
                                'bsplinedisplacementfield': ',5,10', 'syn': ',3,0', 'bsplinesyn': ',1,3'}
    output = ''  # default output if problem

    if paramreg.steps[i_step_str].algo == "centermassrot" and paramreg.steps[i_step_str].rot_method == 'hog':
        src_im = src[0]  # user is expected to input images to src and dest
        dest_im = dest[0]
        src_seg = src[1]
        dest_seg = dest[1]
        del src
        del dest  # to be sure it is not missused later


    # display arguments
    sct.printv('Registration parameters:', param.verbose)
    sct.printv('  type ........... ' + paramreg.steps[i_step_str].type, param.verbose)
    sct.printv('  algo ........... ' + paramreg.steps[i_step_str].algo, param.verbose)
    sct.printv('  slicewise ...... ' + paramreg.steps[i_step_str].slicewise, param.verbose)
    sct.printv('  metric ......... ' + paramreg.steps[i_step_str].metric, param.verbose)
    sct.printv('  iter ........... ' + paramreg.steps[i_step_str].iter, param.verbose)
    sct.printv('  smooth ......... ' + paramreg.steps[i_step_str].smooth, param.verbose)
    sct.printv('  laplacian ...... ' + paramreg.steps[i_step_str].laplacian, param.verbose)
    sct.printv('  shrink ......... ' + paramreg.steps[i_step_str].shrink, param.verbose)
    sct.printv('  gradStep ....... ' + paramreg.steps[i_step_str].gradStep, param.verbose)
    sct.printv('  deformation .... ' + paramreg.steps[i_step_str].deformation, param.verbose)
    sct.printv('  init ........... ' + paramreg.steps[i_step_str].init, param.verbose)
    sct.printv('  poly ........... ' + paramreg.steps[i_step_str].poly, param.verbose)
    sct.printv('  dof ............ ' + paramreg.steps[i_step_str].dof, param.verbose)
    sct.printv('  smoothWarpXY ... ' + paramreg.steps[i_step_str].smoothWarpXY, param.verbose)
    sct.printv('  rot_method ... ' + paramreg.steps[i_step_str].rot_method, param.verbose)

    # set metricSize
    if paramreg.steps[i_step_str].metric == 'MI':
        metricSize = '32'  # corresponds to number of bins
    else:
        metricSize = '4'  # corresponds to radius (for CC, MeanSquares...)

    # set masking
    if param.fname_mask:
        fname_mask = 'mask.nii.gz'
        masking = ['-x', 'mask.nii.gz']
    else:
        fname_mask = ''
        masking = []

    if paramreg.steps[i_step_str].algo == 'slicereg':
        # check if user used type=label
        if paramreg.steps[i_step_str].type == 'label':
            sct.printv('\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg', 1,
                       'error')
        else:
            # Find the min (and max) z-slice index below which (and above which) slices only have voxels below a given
            # threshold.
            list_fname = [src, dest]
            if not masking == []:
                list_fname.append(fname_mask)
            zmin_global, zmax_global = 0, 99999  # this is assuming that typical image has less slice than 99999
            for fname in list_fname:
                im = Image(fname)
                zmin, zmax = msct_image.find_zmin_zmax(im, threshold=0.1)
                if zmin > zmin_global:
                    zmin_global = zmin
                if zmax < zmax_global:
                    zmax_global = zmax
            # crop images (see issue #293)
            src_crop = sct.add_suffix(src, '_crop')
            msct_image.spatial_crop(Image(src), dict(((2, (zmin_global, zmax_global)),))).save(src_crop)
            dest_crop = sct.add_suffix(dest, '_crop')
            msct_image.spatial_crop(Image(dest), dict(((2, (zmin_global, zmax_global)),))).save(dest_crop)
            # update variables
            src = src_crop
            dest = dest_crop
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            # estimate transfo
            # TODO fixup isct_ants* parsers
            cmd = ['isct_antsSliceRegularizedRegistration',
                   '-t', 'Translation[' + paramreg.steps[i_step_str].gradStep + ']',
                   '-m',
                   paramreg.steps[i_step_str].metric + '[' + dest + ',' + src + ',1,' + metricSize + ',Regular,0.2]',
                   '-p', paramreg.steps[i_step_str].poly,
                   '-i', paramreg.steps[i_step_str].iter,
                   '-f', paramreg.steps[i_step_str].shrink,
                   '-s', paramreg.steps[i_step_str].smooth,
                   '-v', '1',  # verbose (verbose=2 does not exist, so we force it to 1)
                   '-o', '[step' + i_step_str + ',' + scr_regStep + ']',  # here the warp name is stage10 because
                   # antsSliceReg add "Warp"
                   ] + masking
            warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
            # run command
            status, output = sct.run(cmd, param.verbose, is_sct_binary=True)

    # ANTS 3d
    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params \
            and paramreg.steps[i_step_str].slicewise == '0':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            # Pad the destination image (because ants doesn't deform the extremities)
            # N.B. no need to pad if iter = 0
            if not paramreg.steps[i_step_str].iter == '0':
                dest_pad = sct.add_suffix(dest, '_pad')
                sct.run(['sct_image', '-i', dest, '-o', dest_pad, '-pad', '0,0,' + str(param.padding)])
                dest = dest_pad
            # apply Laplacian filter
            if not paramreg.steps[i_step_str].laplacian == '0':
                sct.printv('\nApply Laplacian filter', param.verbose)
                sct.run(['sct_maths', '-i', src, '-laplacian', paramreg.steps[i_step_str].laplacian + ','
                         + paramreg.steps[i_step_str].laplacian + ',0', '-o', sct.add_suffix(src, '_laplacian')])
                sct.run(['sct_maths', '-i', dest, '-laplacian', paramreg.steps[i_step_str].laplacian + ','
                         + paramreg.steps[i_step_str].laplacian + ',0', '-o', sct.add_suffix(dest, '_laplacian')])
                src = sct.add_suffix(src, '_laplacian')
                dest = sct.add_suffix(dest, '_laplacian')
            # Estimate transformation
            sct.printv('\nEstimate transformation', param.verbose)
            scr_regStep = sct.add_suffix(src, '_regStep' + i_step_str)
            # TODO fixup isct_ants* parsers
            cmd = ['isct_antsRegistration',
                   '--dimensionality', '3',
                   '--transform', paramreg.steps[i_step_str].algo + '[' + paramreg.steps[i_step_str].gradStep
                   + ants_registration_params[paramreg.steps[i_step_str].algo.lower()] + ']',
                   '--metric', paramreg.steps[i_step_str].metric + '[' + dest + ',' + src + ',1,' + metricSize + ']',
                   '--convergence', paramreg.steps[i_step_str].iter,
                   '--shrink-factors', paramreg.steps[i_step_str].shrink,
                   '--smoothing-sigmas', paramreg.steps[i_step_str].smooth + 'mm',
                   '--restrict-deformation', paramreg.steps[i_step_str].deformation,
                   '--output', '[step' + i_step_str + ',' + scr_regStep + ']',
                   '--interpolation', 'BSpline[3]',
                   '--verbose', '1',
                   ] + masking
            # add init translation
            if not paramreg.steps[i_step_str].init == '':
                init_dict = {'geometric': '0', 'centermass': '1', 'origin': '2'}
                cmd += ['-r', '[' + dest + ',' + src + ',' + init_dict[paramreg.steps[i_step_str].init] + ']']
            # run command
            status, output = sct.run(cmd, param.verbose, is_sct_binary=True)
            # get appropriate file name for transformation
            if paramreg.steps[i_step_str].algo in ['rigid', 'affine', 'translation']:
                warp_forward_out = 'step' + i_step_str + '0GenericAffine.mat'
                warp_inverse_out = '-step' + i_step_str + '0GenericAffine.mat'
            else:
                warp_forward_out = 'step' + i_step_str + '0Warp.nii.gz'
                warp_inverse_out = 'step' + i_step_str + '0InverseWarp.nii.gz'

    # ANTS 2d
    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params \
            and paramreg.steps[i_step_str].slicewise == '1':
        # make sure type!=label. If type==label, this will be addressed later in the code.
        if not paramreg.steps[i_step_str].type == 'label':
            from msct_register import register_slicewise
            # if shrink!=1, force it to be 1 (otherwise, it generates a wrong 3d warping field). TODO: fix that!
            if not paramreg.steps[i_step_str].shrink == '1':
                sct.printv('\nWARNING: when using slicewise with SyN or BSplineSyN, shrink factor needs to be one. '
                           'Forcing shrink=1.', 1, 'warning')
                paramreg.steps[i_step_str].shrink = '1'
            warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
            warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
            register_slicewise(src,
                               dest,
                               paramreg=paramreg.steps[i_step_str],
                               fname_mask=fname_mask,
                               warp_forward_out=warp_forward_out,
                               warp_inverse_out=warp_inverse_out,
                               ants_registration_params=ants_registration_params,
                               remove_temp_files=param.remove_temp_files,
                               verbose=param.verbose)

    # slice-wise transfo
    elif paramreg.steps[i_step_str].algo in ['centermass', 'centermassrot', 'columnwise']:
        # if type=label, exit with error
        if paramreg.steps[i_step_str].type == 'label':
            sct.printv('\nERROR: this algo is not compatible with type=label. Please use type=im or type=seg', 1,
                       'error')
        # check if user provided a mask-- if so, inform it will be ignored
        if not fname_mask == '':
            sct.printv('\nWARNING: algo ' + paramreg.steps[i_step_str].algo + ' will ignore the provided mask.\n', 1,
                       'warning')
        # smooth data
        if not paramreg.steps[i_step_str].smooth == '0':
            sct.printv('\nSmooth data', param.verbose)
            if paramreg.steps[i_step_str].rot_method == 'pca':
                sct.run(['sct_maths', '-i', src, '-smooth', paramreg.steps[i_step_str].smooth + ','
                         + paramreg.steps[i_step_str].smooth + ',0', '-o', sct.add_suffix(src, '_smooth')])
                sct.run(['sct_maths', '-i', dest, '-smooth', paramreg.steps[i_step_str].smooth + ','
                         + paramreg.steps[i_step_str].smooth + ',0', '-o', sct.add_suffix(dest, '_smooth')])
                src = sct.add_suffix(src, '_smooth')
                dest = sct.add_suffix(dest, '_smooth')
            else:
                sct.run(['sct_maths', '-i', src_im, '-smooth', paramreg.steps[i_step_str].smooth + ','
                         + paramreg.steps[i_step_str].smooth + ',0', '-o', sct.add_suffix(src_im, '_smooth')])
                sct.run(['sct_maths', '-i', src_seg, '-smooth', paramreg.steps[i_step_str].smooth + ','
                         + paramreg.steps[i_step_str].smooth + ',0', '-o', sct.add_suffix(src_seg, '_smooth')])
                sct.run(['sct_maths', '-i', dest_im, '-smooth', paramreg.steps[i_step_str].smooth + ','
                         + paramreg.steps[i_step_str].smooth + ',0', '-o', sct.add_suffix(dest_im, '_smooth')])
                sct.run(['sct_maths', '-i', dest_seg, '-smooth', paramreg.steps[i_step_str].smooth + ','
                         + paramreg.steps[i_step_str].smooth + ',0', '-o', sct.add_suffix(dest_seg, '_smooth')])
                src_im = sct.add_suffix(src_im, '_smooth')
                dest_im = sct.add_suffix(dest_im, '_smooth')
                src_seg = sct.add_suffix(src_seg, '_smooth')
                dest_seg = sct.add_suffix(dest_seg, '_smooth')
        from msct_register import register_slicewise
        warp_forward_out = 'step' + i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step' + i_step_str + 'InverseWarp.nii.gz'
        if paramreg.steps[i_step_str].rot_method == 'pca':  #because pca is the default choice, also includes no rotation
            register_slicewise(src,
                           dest,
                           paramreg=paramreg.steps[i_step_str],
                           fname_mask=fname_mask,
                           warp_forward_out=warp_forward_out,
                           warp_inverse_out=warp_inverse_out,
                           ants_registration_params=ants_registration_params,
                           remove_temp_files=param.remove_temp_files,
                           verbose=param.verbose)
        elif paramreg.steps[i_step_str].rot_method == 'hog':  # im_seg case
            register_slicewise([src_im, src_seg],
                           [dest_im, dest_seg],
                           paramreg=paramreg.steps[i_step_str],
                           fname_mask=fname_mask,
                           warp_forward_out=warp_forward_out,
                           warp_inverse_out=warp_inverse_out,
                           ants_registration_params=ants_registration_params,
                           path_qc=param.path_qc,
                           remove_temp_files=param.remove_temp_files,
                           verbose=param.verbose)
        else:
            raise ValueError("rot_method " + paramreg.steps[i_step_str].rot_method + " does not exist")


    else:
        sct.printv('\nERROR: algo ' + paramreg.steps[i_step_str].algo + ' does not exist. Exit program\n', 1, 'error')

    # landmark-based registration
    if paramreg.steps[i_step_str].type in ['label']:
        # check if user specified ilabel and dlabel
        # TODO
        warp_forward_out = 'step' + i_step_str + '0GenericAffine.txt'
        warp_inverse_out = '-step' + i_step_str + '0GenericAffine.txt'
        from msct_register_landmarks import register_landmarks
        register_landmarks(src,
                           dest,
                           paramreg.steps[i_step_str].dof,
                           fname_affine=warp_forward_out,
                           verbose=param.verbose)

    if not os.path.isfile(warp_forward_out):
        # no forward warping field for rigid and affine
        sct.printv('\nERROR: file ' + warp_forward_out + ' doesn\'t exist (or is not a file).\n' + output +
                   '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    elif not os.path.isfile(warp_inverse_out) and \
            paramreg.steps[i_step_str].algo not in ['rigid', 'affine', 'translation'] and \
            paramreg.steps[i_step_str].type not in ['label']:
        # no inverse warping field for rigid and affine
        sct.printv('\nERROR: file ' + warp_inverse_out + ' doesn\'t exist (or is not a file).\n' + output +
                   '\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    else:
        # rename warping fields
        if (paramreg.steps[i_step_str].algo.lower() in ['rigid', 'affine', 'translation'] and
                paramreg.steps[i_step_str].slicewise == '0'):
            # if ANTs is used with affine/rigid --> outputs .mat file
            warp_forward = 'warp_forward_' + i_step_str + '.mat'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_' + i_step_str + '.mat'
        elif paramreg.steps[i_step_str].type in ['label']:
            # if label-based registration is used --> outputs .txt file
            warp_forward = 'warp_forward_' + i_step_str + '.txt'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_' + i_step_str + '.txt'
        else:
            warp_forward = 'warp_forward_' + i_step_str + '.nii.gz'
            warp_inverse = 'warp_inverse_' + i_step_str + '.nii.gz'
            os.rename(warp_forward_out, warp_forward)
            os.rename(warp_inverse_out, warp_inverse)

    return warp_forward, warp_inverse