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'}

    fsloutput = 'export FSLOUTPUTTYPE=NIFTI; '  # for faster processing, all outputs are in NIFTI'

    # 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':
        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
        # 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+','+src+'_regStep'+i_step_str+'.nii] '  # 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'

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_pointwise':
        from msct_register import register_slicereg2d_pointwise
        warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_pointwise(src, dest, window_length=paramreg.steps[i_step_str].window_length, paramreg=Paramreg(step=paramreg.steps[i_step_str].step, type=paramreg.steps[i_step_str].type, algo='Translation', metric=paramreg.steps[i_step_str].metric, iter= paramreg.steps[i_step_str].iter, shrink=paramreg.steps[i_step_str].shrink, smooth=paramreg.steps[i_step_str].smooth, gradStep=paramreg.steps[i_step_str].gradStep),
                                      warp_forward_out=warp_forward_out, warp_inverse_out=warp_inverse_out, factor=param.outlier_factor, verbose=param.verbose)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_translation':
        from msct_register import register_slicereg2d_translation
        warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_translation(src, dest, window_length=paramreg.steps[i_step_str].window_length, paramreg=Paramreg(step=paramreg.steps[i_step_str].step, type=paramreg.steps[i_step_str].type, algo='Translation', metric=paramreg.steps[i_step_str].metric, iter= paramreg.steps[i_step_str].iter, shrink=paramreg.steps[i_step_str].shrink, smooth=paramreg.steps[i_step_str].smooth, gradStep=paramreg.steps[i_step_str].gradStep),
                                        fname_mask=fname_mask, warp_forward_out=warp_forward_out, warp_inverse_out=warp_inverse_out, factor=param.outlier_factor, remove_temp_files=param.remove_temp_files,
                                        verbose=param.verbose, ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_rigid':
        from msct_register import register_slicereg2d_rigid
        warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_rigid(src, dest, window_length=paramreg.steps[i_step_str].window_length, paramreg=Paramreg(step=paramreg.steps[i_step_str].step, type=paramreg.steps[i_step_str].type, algo='Rigid', metric=paramreg.steps[i_step_str].metric, iter= paramreg.steps[i_step_str].iter, shrink=paramreg.steps[i_step_str].shrink, smooth=paramreg.steps[i_step_str].smooth, gradStep=paramreg.steps[i_step_str].gradStep),
                                  fname_mask=fname_mask, warp_forward_out=warp_forward_out, warp_inverse_out=warp_inverse_out, factor=param.outlier_factor, remove_temp_files=param.remove_temp_files,
                                  verbose=param.verbose, ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_affine':
        from msct_register import register_slicereg2d_affine
        warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_affine(src, dest, window_length=paramreg.steps[i_step_str].window_length, paramreg=Paramreg(step=paramreg.steps[i_step_str].step, type=paramreg.steps[i_step_str].type, algo='Affine', metric=paramreg.steps[i_step_str].metric, iter= paramreg.steps[i_step_str].iter, shrink=paramreg.steps[i_step_str].shrink, smooth=paramreg.steps[i_step_str].smooth, gradStep=paramreg.steps[i_step_str].gradStep),
                                   fname_mask=fname_mask, warp_forward_out=warp_forward_out, warp_inverse_out=warp_inverse_out, factor=param.outlier_factor, remove_temp_files=param.remove_temp_files,
                                   verbose=param.verbose, ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_syn':
        from msct_register import register_slicereg2d_syn
        warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_syn(src, dest, window_length=paramreg.steps[i_step_str].window_length, paramreg=Paramreg(step=paramreg.steps[i_step_str].step, type=paramreg.steps[i_step_str].type, algo='SyN', metric=paramreg.steps[i_step_str].metric, iter= paramreg.steps[i_step_str].iter, shrink=paramreg.steps[i_step_str].shrink, smooth=paramreg.steps[i_step_str].smooth, gradStep=paramreg.steps[i_step_str].gradStep),
                                fname_mask=fname_mask, warp_forward_out=warp_forward_out, warp_inverse_out=warp_inverse_out, factor=param.outlier_factor, remove_temp_files=param.remove_temp_files,
                                verbose=param.verbose, ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo == 'slicereg2d_bsplinesyn':
        from msct_register import register_slicereg2d_bsplinesyn
        warp_forward_out = 'step'+i_step_str + 'Warp.nii.gz'
        warp_inverse_out = 'step'+i_step_str + 'InverseWarp.nii.gz'
        register_slicereg2d_bsplinesyn(src, dest, window_length=paramreg.steps[i_step_str].window_length, paramreg=Paramreg(step=paramreg.steps[i_step_str].step, type=paramreg.steps[i_step_str].type, algo='BSplineSyN', metric=paramreg.steps[i_step_str].metric, iter= paramreg.steps[i_step_str].iter, shrink=paramreg.steps[i_step_str].shrink, smooth=paramreg.steps[i_step_str].smooth, gradStep=paramreg.steps[i_step_str].gradStep),
                                       fname_mask=fname_mask, warp_forward_out=warp_forward_out, warp_inverse_out=warp_inverse_out, factor=param.outlier_factor, remove_temp_files=param.remove_temp_files,
                                       verbose=param.verbose, ants_registration_params=ants_registration_params)
        cmd = ('')

    elif paramreg.steps[i_step_str].algo.lower() in ants_registration_params:
        # 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_maths -i '+dest+' -o '+dest_pad+' -pad 0x0x'+str(param.padding))
            dest = dest_pad

        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+','+src+'_regStep'+i_step_str+'.nii] '
               '--interpolation BSpline[3] '
               +masking)
        if param.verbose >= 1:
            cmd += ' --verbose 1'
        if paramreg.steps[i_step_str].algo in ['rigid', 'affine']:
            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'
    else:
        sct.printv('\nERROR: algo '+paramreg.steps[i_step_str].algo+' does not exist. Exit program\n', 1, 'error')

    # run registration
    status, output = sct.run(cmd, param.verbose)

    if not os.path.isfile(warp_forward_out):
        sct.printv('\nERROR: file '+warp_forward_out+' doesn\'t exist (or is not a file).\n', 1, 'error')
        sct.printv(output, 1, 'error')
        sct.printv('\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    elif not os.path.isfile(warp_inverse_out):
        sct.printv('\nERROR: file '+warp_inverse_out+' doesn\'t exist (or is not a file).\n', 1, 'error')
        sct.printv(output, 1, 'error')
        sct.printv('\nERROR: ANTs failed. Exit program.\n', 1, 'error')
    else:
        # rename warping fields
        if paramreg.steps[i_step_str].algo in ['rigid', 'affine']:
            warp_forward = 'warp_forward_'+i_step_str+'.mat'
            os.rename(warp_forward_out, warp_forward)
            warp_inverse = '-warp_forward_'+i_step_str+'.mat'
        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)

    print '*********************************************************************************************************************\n'
    print warp_forward, warp_inverse
    print '*********************************************************************************************************************\n'

    return warp_forward, warp_inverse


# START PROGRAM
# ==========================================================================================
dataset/ETHPy150Open neuropoly/spinalcordtoolbox/dev/sct_register_multimodal_old/sct_register_multimodal.py/register/original