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