def register_slicereg2d_rigid(fname_source, fname_dest, window_length=31, paramreg=Paramreg(step='0', type='im', algo='Rigid', metric='MeanSquares', iter='10', shrink='1', smooth='0', gradStep='0.5'), fname_mask='', warp_forward_out='step0Warp.nii.gz', warp_inverse_out='step0InverseWarp.nii.gz', factor=2, remove_temp_files=1, verbose=0, ants_registration_params={'rigid': '', 'affine': '', 'compositeaffine': '', 'similarity': '', 'translation': '','bspline': ',10', 'gaussiandisplacementfield': ',3,0', 'bsplinedisplacementfield': ',5,10', 'syn': ',3,0', 'bsplinesyn': ',1,3'}): """Slice-by-slice regularized registration (rigid) of two images. We first register slice-by-slice the two images using antsRegistration in 2D. Then we remove outliers using Median Absolute Deviation technique (MAD) and smooth the translations and angle of rotation along x and y axis using moving average hanning window. Eventually, we generate two warping fields (forward and inverse) resulting from this regularized registration technique. The images must be of same size (otherwise generate_warping_field will not work for forward or inverse creation). input: fname_source: name of moving image (type: string) fname_dest: name of fixed image (type: string) window_length[optional]: size of window for moving average smoothing (type: int) paramreg[optional]: parameters of antsRegistration (type: Paramreg class from sct_register_multimodal) fname_mask[optional]: name of mask file (type: string) (parameter -x of antsRegistration) warp_forward_out[optional]: name of output forward warp (type: string) warp_inverse_out[optional]: name of output inverse warp (type: string) factor[optional]: sensibility factor for outlier detection (higher the factor, smaller the detection) (type: int or float) remove_temp_files[optional]: 1 to remove, 0 to keep (type: int) verbose[optional]: display parameter (type: int, value: 0,1 or 2) ants_registration_params[optional]: specific algorithm's parameters for antsRegistration (type: dictionary) output: creation of warping field files of name 'warp_forward_out' and 'warp_inverse_out'. """ from msct_register_regularized import register_images, generate_warping_field from numpy import asarray from msct_smooth import smoothing_window, outliers_detection, outliers_completion # Calculate displacement x_disp, y_disp, theta_rot = register_images(fname_source, fname_dest, mask=fname_mask, paramreg=paramreg, remove_tmp_folder=remove_temp_files, ants_registration_params=ants_registration_params) # Change to array x_disp_a = asarray(x_disp) y_disp_a = asarray(y_disp) theta_rot_a = asarray(theta_rot) # Detect outliers mask_x_a = outliers_detection(x_disp_a, type='median', factor=factor, return_filtered_signal='no', verbose=verbose) mask_y_a = outliers_detection(y_disp_a, type='median', factor=factor, return_filtered_signal='no', verbose=verbose) mask_theta_a = outliers_detection(theta_rot_a, type='median', factor=2, return_filtered_signal='no', verbose=verbose) # Replace value of outliers by linear interpolation using closest non-outlier points x_disp_a_no_outliers = outliers_completion(mask_x_a, verbose=0) y_disp_a_no_outliers = outliers_completion(mask_y_a, verbose=0) theta_rot_a_no_outliers = outliers_completion(mask_theta_a, verbose=0) # Smooth results x_disp_smooth = smoothing_window(x_disp_a_no_outliers, window_len=int(window_length), window='hanning', verbose = verbose) y_disp_smooth = smoothing_window(y_disp_a_no_outliers, window_len=int(window_length), window='hanning', verbose = verbose) theta_rot_smooth = smoothing_window(theta_rot_a_no_outliers, window_len=int(window_length), window='hanning', verbose = verbose) # Generate warping field generate_warping_field(fname_dest, x_disp_smooth, y_disp_smooth, theta_rot_smooth, fname=warp_forward_out) # Inverse warping field generate_warping_field(fname_source, -x_disp_smooth, -y_disp_smooth, -theta_rot_smooth, fname=warp_inverse_out)
def register_slicereg2d_pointwise(fname_source, fname_dest, window_length=31, paramreg=Paramreg(step='0', type='seg', algo='slicereg2d_pointwise', metric='MeanSquares', iter='10', shrink='1', smooth='0', gradStep='0.5'), warp_forward_out='step0Warp.nii.gz', warp_inverse_out='step0InverseWarp.nii.gz', factor=2, verbose=0): """Slice-by-slice regularized registration by translation of two segmentations. First we estimate for each slice the translation vector by calculating the difference of position of the two centers of mass of the two segmentations. Then we remove outliers using Median Absolute Deviation technique (MAD) and smooth the translation along x and y axis using moving average hanning window. Eventually, we generate two warping fields (forward and inverse) resulting from this regularized registration technique. The segmentations must be of same size (otherwise generate_warping_field will not work for forward or inverse creation). input: fname_source: name of moving image (type: string) fname_dest: name of fixed image (type: string) window_length: size of window for moving average smoothing (type: int) paramreg[optional]: parameters of antsRegistration (type: Paramreg class from sct_register_multimodal) warp_forward_out: name of output forward warp (type: string) warp_inverse_out: name of output inverse warp (type: string) factor: sensibility factor for outlier detection (higher the factor, smaller the detection) (type: int or float) verbose: display parameter (type: int, value: 0,1 or 2) output: creation of warping field files of name 'warp_forward_out' and 'warp_inverse_out'. """ if paramreg.type != 'seg': print '\nERROR: Algorithm slicereg2d_pointwise only operates for segmentation type.' sys.exit(2) else: from msct_register_regularized import register_seg, generate_warping_field from numpy import asarray from msct_smooth import smoothing_window, outliers_detection, outliers_completion # Calculate displacement x_disp, y_disp = register_seg(fname_source, fname_dest) # Change to array x_disp_a = asarray(x_disp) y_disp_a = asarray(y_disp) # Detect outliers mask_x_a = outliers_detection(x_disp_a, type='median', factor=factor, return_filtered_signal='no', verbose=verbose) mask_y_a = outliers_detection(y_disp_a, type='median', factor=factor, return_filtered_signal='no', verbose=verbose) # Replace value of outliers by linear interpolation using closest non-outlier points x_disp_a_no_outliers = outliers_completion(mask_x_a, verbose=0) y_disp_a_no_outliers = outliers_completion(mask_y_a, verbose=0) # Smooth results x_disp_smooth = smoothing_window(x_disp_a_no_outliers, window_len=int(window_length), window='hanning', verbose=verbose) y_disp_smooth = smoothing_window(y_disp_a_no_outliers, window_len=int(window_length), window='hanning', verbose=verbose) # Generate warping field generate_warping_field(fname_dest, x_disp_smooth, y_disp_smooth, fname=warp_forward_out) #name_warp= 'step'+str(paramreg.step) # Inverse warping field generate_warping_field(fname_source, -x_disp_smooth, -y_disp_smooth, fname=warp_inverse_out)
def register_slicereg2d_bsplinesyn(fname_source, fname_dest, window_length=31, paramreg=Paramreg(step='0', type='im', algo='BSplineSyN', metric='MeanSquares', iter='10', shrink='1', smooth='0', gradStep='0.5'), fname_mask='', warp_forward_out='step0Warp.nii.gz', warp_inverse_out='step0InverseWarp.nii.gz', factor=2, remove_temp_files=1, verbose=0, ants_registration_params={'rigid': '', 'affine': '', 'compositeaffine': '', 'similarity': '', 'translation': '','bspline': ',10', 'gaussiandisplacementfield': ',3,0', 'bsplinedisplacementfield': ',5,10', 'syn': ',3,0', 'bsplinesyn': ',1,3'}): """Slice-by-slice regularized registration (bsplinesyn) of two images. We first register slice-by-slice the two images using antsRegistration in 2D (algo: bsplinesyn) and create 3D warping fields (forward and inverse) by merging the 2D warping fields along z. Then we directly detect outliers and smooth the 3d warping fields applying a moving average hanning window on each pixel of the plan xOy (i.e. we consider that for a position (x,y) in the plan xOy, the variation along z of the vector of displacement (xo, yo, zo) of the warping field should not be too abrupt). Eventually, we generate two warping fields (forward and inverse) resulting from this regularized registration technique. The images must be of same size (otherwise generate_warping_field will not work for forward or inverse creation). input: fname_source: name of moving image (type: string) fname_dest: name of fixed image (type: string) window_length[optional]: size of window for moving average smoothing (type: int) paramreg[optional]: parameters of antsRegistration (type: Paramreg class from sct_register_multimodal) fname_mask[optional]: name of mask file (type: string) (parameter -x of antsRegistration) warp_forward_out[optional]: name of output forward warp (type: string) warp_inverse_out[optional]: name of output inverse warp (type: string) factor[optional]: sensibility factor for outlier detection (higher the factor, smaller the detection) (type: int or float) remove_temp_files[optional]: 1 to remove, 0 to keep (type: int) verbose[optional]: display parameter (type: int, value: 0,1 or 2) ants_registration_params[optional]: specific algorithm's parameters for antsRegistration (type: dictionary) output: creation of warping field files of name 'warp_forward_out' and 'warp_inverse_out'. """ from nibabel import load, Nifti1Image, save from msct_smooth import smoothing_window, outliers_detection, outliers_completion from msct_register_regularized import register_images from numpy import apply_along_axis, zeros import sct_utils as sct from msct_image import Image name_warp_syn = 'Warp_total' # Registrating images register_images(fname_source, fname_dest, mask=fname_mask, paramreg=paramreg, remove_tmp_folder=remove_temp_files, ants_registration_params=ants_registration_params) print'\nRegularizing warping fields along z axis...' print'\n\tSplitting warping fields ...' # sct.run('isct_c3d -mcs ' + name_warp_syn + '.nii.gz -oo ' + name_warp_syn + '_x.nii.gz ' + name_warp_syn + '_y.nii.gz') # sct.run('isct_c3d -mcs ' + name_warp_syn + '_inverse.nii.gz -oo ' + name_warp_syn + '_x_inverse.nii.gz ' + name_warp_syn + '_y_inverse.nii.gz') sct.run('sct_maths -i ' + name_warp_syn + '.nii.gz -w -mcs -o ' + name_warp_syn + '_x.nii.gz,' + name_warp_syn + '_y.nii.gz') sct.run('sct_maths -i ' + name_warp_syn + '_inverse.nii.gz -w -mcs -o ' + name_warp_syn + '_x_inverse.nii.gz,' + name_warp_syn + '_y_inverse.nii.gz') data_warp_x = load(name_warp_syn + '_x.nii.gz').get_data() data_warp_y = load(name_warp_syn + '_y.nii.gz').get_data() hdr_warp = load(name_warp_syn + '_x.nii.gz').get_header() data_warp_x_inverse = load(name_warp_syn + '_x_inverse.nii.gz').get_data() data_warp_y_inverse = load(name_warp_syn + '_y_inverse.nii.gz').get_data() hdr_warp_inverse = load(name_warp_syn + '_x_inverse.nii.gz').get_header() #Outliers deletion print'\n\tDeleting outliers...' mask_x_a = apply_along_axis(lambda m: outliers_detection(m, type='median', factor=factor, return_filtered_signal='no', verbose=0), axis=-1, arr=data_warp_x) mask_y_a = apply_along_axis(lambda m: outliers_detection(m, type='median', factor=factor, return_filtered_signal='no', verbose=0), axis=-1, arr=data_warp_y) mask_x_inverse_a = apply_along_axis(lambda m: outliers_detection(m, type='median', factor=factor, return_filtered_signal='no', verbose=0), axis=-1, arr=data_warp_x_inverse) mask_y_inverse_a = apply_along_axis(lambda m: outliers_detection(m, type='median', factor=factor, return_filtered_signal='no', verbose=0), axis=-1, arr=data_warp_y_inverse) #Outliers replacement by linear interpolation using closest non-outlier points data_warp_x_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_x_a) data_warp_y_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_y_a) data_warp_x_inverse_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_x_inverse_a) data_warp_y_inverse_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_y_inverse_a) #Smoothing of results along z print'\n\tSmoothing results...' data_warp_x_smooth = apply_along_axis(lambda m: smoothing_window(m, window_len=int(window_length), window='hanning', verbose=0), axis=-1, arr=data_warp_x_no_outliers) data_warp_x_smooth_inverse = apply_along_axis(lambda m: smoothing_window(m, window_len=int(window_length), window='hanning', verbose=0), axis=-1, arr=data_warp_x_inverse_no_outliers) data_warp_y_smooth = apply_along_axis(lambda m: smoothing_window(m, window_len=int(window_length), window='hanning', verbose=0), axis=-1, arr=data_warp_y_no_outliers) data_warp_y_smooth_inverse = apply_along_axis(lambda m: smoothing_window(m, window_len=int(window_length), window='hanning', verbose=0), axis=-1, arr=data_warp_y_inverse_no_outliers) print'\nSaving regularized warping fields...' #Get image dimensions of destination image nx, ny, nz, nt, px, py, pz, pt = Image(fname_dest).dim data_warp_smooth = zeros(((((nx, ny, nz, 1, 3))))) data_warp_smooth[:,:,:,0,0] = data_warp_x_smooth data_warp_smooth[:,:,:,0,1] = data_warp_y_smooth data_warp_smooth_inverse = zeros(((((nx, ny, nz, 1, 3))))) data_warp_smooth_inverse[:,:,:,0,0] = data_warp_x_smooth_inverse data_warp_smooth_inverse[:,:,:,0,1] = data_warp_y_smooth_inverse # Force header's parameter to intent so that the file may be recognised as a warping field by ants hdr_warp.set_intent('vector', (), '') hdr_warp_inverse.set_intent('vector', (), '') img = Nifti1Image(data_warp_smooth, None, header=hdr_warp) img_inverse = Nifti1Image(data_warp_smooth_inverse, None, header=hdr_warp_inverse) save(img, filename=warp_forward_out) print'\tFile ' + warp_forward_out + ' saved.' save(img_inverse, filename=warp_inverse_out) print'\tFile ' + warp_inverse_out + ' saved.'
def register_slicereg2d(fname_source, fname_dest, fname_mask='', window_length='0', warp_forward_out='step0Warp.nii.gz', warp_inverse_out='step0InverseWarp.nii.gz', paramreg=None, ants_registration_params=None, detect_outlier='0', remove_temp_files=1, verbose=0): from msct_register_regularized import register_seg, register_images, generate_warping_field from numpy import asarray, apply_along_axis, zeros from msct_smooth import smoothing_window, outliers_detection, outliers_completion # Calculate displacement current_algo = paramreg.algo if paramreg.type == 'seg': # calculate translation of center of mass between source and destination in voxel space res_reg = register_seg(fname_source, fname_dest, verbose) elif paramreg.type == 'im': if paramreg.algo == 'slicereg2d_pointwise': sct.printv('\nERROR: Algorithm slicereg2d_pointwise only operates for segmentation type.', verbose, 'error') sys.exit(2) algo_dic = {'slicereg2d_pointwise': 'Translation', 'slicereg2d_translation': 'Translation', 'slicereg2d_rigid': 'Rigid', 'slicereg2d_affine': 'Affine', 'slicereg2d_syn': 'SyN', 'slicereg2d_bsplinesyn': 'BSplineSyN'} paramreg.algo = algo_dic[current_algo] res_reg = register_images(fname_source, fname_dest, mask=fname_mask, paramreg=paramreg, remove_tmp_folder=remove_temp_files, ants_registration_params=ants_registration_params) else: sct.printv('\nERROR: wrong registration type inputed. pleas choose \'im\', or \'seg\'.', verbose, 'error') sys.exit(2) # if algo is slicereg2d _pointwise, -translation or _rigid: x_disp and y_disp are displacement fields # if algo is slicereg2d _affine, _syn or _bsplinesyn: x_disp and y_disp are warping fields names if current_algo in ['slicereg2d_pointwise', 'slicereg2d_translation', 'slicereg2d_rigid']: # Change to array x_disp, y_disp, theta_rot = res_reg x_disp_a = asarray(x_disp) y_disp_a = asarray(y_disp) # Detect outliers if not detect_outlier == '0': mask_x_a = outliers_detection(x_disp_a, type='median', factor=int(detect_outlier), return_filtered_signal='no', verbose=verbose) mask_y_a = outliers_detection(y_disp_a, type='median', factor=int(detect_outlier), return_filtered_signal='no', verbose=verbose) # Replace value of outliers by linear interpolation using closest non-outlier points x_disp_a_no_outliers = outliers_completion(mask_x_a, verbose=0) y_disp_a_no_outliers = outliers_completion(mask_y_a, verbose=0) else: x_disp_a_no_outliers = x_disp_a y_disp_a_no_outliers = y_disp_a # Smooth results if not window_length == '0': x_disp_smooth = smoothing_window(x_disp_a_no_outliers, window_len=int(window_length), window='hanning', verbose=verbose) y_disp_smooth = smoothing_window(y_disp_a_no_outliers, window_len=int(window_length), window='hanning', verbose=verbose) else: x_disp_smooth = x_disp_a_no_outliers y_disp_smooth = y_disp_a_no_outliers if theta_rot is not None: # same steps for theta_rot: theta_rot_a = asarray(theta_rot) mask_theta_a = outliers_detection(theta_rot_a, type='median', factor=int(detect_outlier), return_filtered_signal='no', verbose=verbose) theta_rot_a_no_outliers = outliers_completion(mask_theta_a, verbose=0) theta_rot_smooth = smoothing_window(theta_rot_a_no_outliers, window_len=int(window_length), window='hanning', verbose = verbose) else: theta_rot_smooth = None # Generate warping field generate_warping_field(fname_dest, x_disp_smooth, y_disp_smooth, theta_rot_smooth, fname=warp_forward_out) #name_warp= 'step'+str(paramreg.step) # Inverse warping field generate_warping_field(fname_source, -x_disp_smooth, -y_disp_smooth, -theta_rot_smooth if theta_rot_smooth is not None else None, fname=warp_inverse_out) elif current_algo in ['slicereg2d_affine', 'slicereg2d_syn', 'slicereg2d_bsplinesyn']: from msct_image import Image warp_x, inv_warp_x, warp_y, inv_warp_y = res_reg im_warp_x = Image(warp_x) im_inv_warp_x = Image(inv_warp_x) im_warp_y = Image(warp_y) im_inv_warp_y = Image(inv_warp_y) data_warp_x = im_warp_x.data data_warp_x_inverse = im_inv_warp_x.data data_warp_y = im_warp_y.data data_warp_y_inverse = im_inv_warp_y.data hdr_warp = im_warp_x.hdr hdr_warp_inverse = im_inv_warp_x.hdr #Outliers deletion print'\n\tDeleting outliers...' mask_x_a = apply_along_axis(lambda m: outliers_detection(m, type='median', factor=int(detect_outlier), return_filtered_signal='no', verbose=0), axis=-1, arr=data_warp_x) mask_y_a = apply_along_axis(lambda m: outliers_detection(m, type='median', factor=int(detect_outlier), return_filtered_signal='no', verbose=0), axis=-1, arr=data_warp_y) mask_x_inverse_a = apply_along_axis(lambda m: outliers_detection(m, type='median', factor=int(detect_outlier), return_filtered_signal='no', verbose=0), axis=-1, arr=data_warp_x_inverse) mask_y_inverse_a = apply_along_axis(lambda m: outliers_detection(m, type='median', factor=int(detect_outlier), return_filtered_signal='no', verbose=0), axis=-1, arr=data_warp_y_inverse) #Outliers replacement by linear interpolation using closest non-outlier points data_warp_x_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_x_a) data_warp_y_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_y_a) data_warp_x_inverse_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_x_inverse_a) data_warp_y_inverse_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_y_inverse_a) #Smoothing of results along z print'\n\tSmoothing results...' data_warp_x_smooth = apply_along_axis(lambda m: smoothing_window(m, window_len=int(window_length), window='hanning', verbose=0), axis=-1, arr=data_warp_x_no_outliers) data_warp_x_smooth_inverse = apply_along_axis(lambda m: smoothing_window(m, window_len=int(window_length), window='hanning', verbose=0), axis=-1, arr=data_warp_x_inverse_no_outliers) data_warp_y_smooth = apply_along_axis(lambda m: smoothing_window(m, window_len=int(window_length), window='hanning', verbose=0), axis=-1, arr=data_warp_y_no_outliers) data_warp_y_smooth_inverse = apply_along_axis(lambda m: smoothing_window(m, window_len=int(window_length), window='hanning', verbose=0), axis=-1, arr=data_warp_y_inverse_no_outliers) print'\nSaving regularized warping fields...' # TODO: MODIFY NEXT PART #Get image dimensions of destination image from msct_image import Image from nibabel import load, Nifti1Image, save nx, ny, nz, nt, px, py, pz, pt = Image(fname_dest).dim data_warp_smooth = zeros(((((nx, ny, nz, 1, 3))))) data_warp_smooth[:,:,:,0,0] = data_warp_x_smooth data_warp_smooth[:,:,:,0,1] = data_warp_y_smooth data_warp_smooth_inverse = zeros(((((nx, ny, nz, 1, 3))))) data_warp_smooth_inverse[:,:,:,0,0] = data_warp_x_smooth_inverse data_warp_smooth_inverse[:,:,:,0,1] = data_warp_y_smooth_inverse # Force header's parameter to intent so that the file may be recognised as a warping field by ants hdr_warp.set_intent('vector', (), '') hdr_warp_inverse.set_intent('vector', (), '') img = Nifti1Image(data_warp_smooth, None, header=hdr_warp) img_inverse = Nifti1Image(data_warp_smooth_inverse, None, header=hdr_warp_inverse) save(img, filename=warp_forward_out) print'\tFile ' + warp_forward_out + ' saved.' save(img_inverse, filename=warp_inverse_out) print'\tFile ' + warp_inverse_out + ' saved.' return warp_forward_out, warp_inverse_out
def register_slicereg2d_bsplinesyn( src, dest, window_length=31, paramreg=Paramreg( step="0", type="im", algo="BSplineSyN", metric="MeanSquares", iter="10", shrink="1", smooth="0", gradStep="0.5" ), fname_mask="", warp_forward_out="step0Warp.nii.gz", warp_inverse_out="step0InverseWarp.nii.gz", factor=2, remove_temp_files=1, verbose=0, ants_registration_params={ "rigid": "", "affine": "", "compositeaffine": "", "similarity": "", "translation": "", "bspline": ",10", "gaussiandisplacementfield": ",3,0", "bsplinedisplacementfield": ",5,10", "syn": ",3,0", "bsplinesyn": ",1,3", }, ): """Slice-by-slice regularized registration (bsplinesyn) of two images. We first register slice-by-slice the two images using antsRegistration in 2D (algo: bsplinesyn) and create 3D warping fields (forward and inverse) by merging the 2D warping fields along z. Then we directly detect outliers and smooth the 3d warping fields applying a moving average hanning window on each pixel of the plan xOy (i.e. we consider that for a position (x,y) in the plan xOy, the variation along z of the vector of displacement (xo, yo, zo) of the warping field should not be too abrupt). Eventually, we generate two warping fields (forward and inverse) resulting from this regularized registration technique. The images must be of same size (otherwise generate_warping_field will not work for forward or inverse creation). input: src: name of moving image (type: string) dest: name of fixed image (type: string) window_length[optional]: size of window for moving average smoothing (type: int) paramreg[optional]: parameters of antsRegistration (type: Paramreg class from sct_register_multimodal) fname_mask[optional]: name of mask file (type: string) (parameter -x of antsRegistration) warp_forward_out[optional]: name of output forward warp (type: string) warp_inverse_out[optional]: name of output inverse warp (type: string) factor[optional]: sensibility factor for outlier detection (higher the factor, smaller the detection) (type: int or float) remove_temp_files[optional]: 1 to remove, 0 to keep (type: int) verbose[optional]: display parameter (type: int, value: 0,1 or 2) ants_registration_params[optional]: specific algorithm's parameters for antsRegistration (type: dictionary) output: creation of warping field files of name 'warp_forward_out' and 'warp_inverse_out'. """ from nibabel import load, Nifti1Image, save from msct_smooth import smoothing_window, outliers_detection, outliers_completion from msct_register_regularized import register_images from numpy import apply_along_axis, zeros import sct_utils as sct name_warp_syn = "Warp_total" # Registrating images register_images( src, dest, mask=fname_mask, paramreg=paramreg, remove_tmp_folder=remove_temp_files, ants_registration_params=ants_registration_params, ) print "\nRegularizing warping fields along z axis..." print "\n\tSplitting warping fields ..." sct.run( "isct_c3d -mcs " + name_warp_syn + ".nii.gz -oo " + name_warp_syn + "_x.nii.gz " + name_warp_syn + "_y.nii.gz" ) sct.run( "isct_c3d -mcs " + name_warp_syn + "_inverse.nii.gz -oo " + name_warp_syn + "_x_inverse.nii.gz " + name_warp_syn + "_y_inverse.nii.gz" ) data_warp_x = load(name_warp_syn + "_x.nii.gz").get_data() data_warp_y = load(name_warp_syn + "_y.nii.gz").get_data() hdr_warp = load(name_warp_syn + "_x.nii.gz").get_header() data_warp_x_inverse = load(name_warp_syn + "_x_inverse.nii.gz").get_data() data_warp_y_inverse = load(name_warp_syn + "_y_inverse.nii.gz").get_data() hdr_warp_inverse = load(name_warp_syn + "_x_inverse.nii.gz").get_header() # Outliers deletion print "\n\tDeleting outliers..." mask_x_a = apply_along_axis( lambda m: outliers_detection(m, type="median", factor=factor, return_filtered_signal="no", verbose=0), axis=-1, arr=data_warp_x, ) mask_y_a = apply_along_axis( lambda m: outliers_detection(m, type="median", factor=factor, return_filtered_signal="no", verbose=0), axis=-1, arr=data_warp_y, ) mask_x_inverse_a = apply_along_axis( lambda m: outliers_detection(m, type="median", factor=factor, return_filtered_signal="no", verbose=0), axis=-1, arr=data_warp_x_inverse, ) mask_y_inverse_a = apply_along_axis( lambda m: outliers_detection(m, type="median", factor=factor, return_filtered_signal="no", verbose=0), axis=-1, arr=data_warp_y_inverse, ) # Outliers replacement by linear interpolation using closest non-outlier points data_warp_x_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_x_a) data_warp_y_no_outliers = apply_along_axis(lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_y_a) data_warp_x_inverse_no_outliers = apply_along_axis( lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_x_inverse_a ) data_warp_y_inverse_no_outliers = apply_along_axis( lambda m: outliers_completion(m, verbose=0), axis=-1, arr=mask_y_inverse_a ) # Smoothing of results along z print "\n\tSmoothing results..." data_warp_x_smooth = apply_along_axis( lambda m: smoothing_window(m, window_len=int(window_length), window="hanning", verbose=0), axis=-1, arr=data_warp_x_no_outliers, ) data_warp_x_smooth_inverse = apply_along_axis( lambda m: smoothing_window(m, window_len=int(window_length), window="hanning", verbose=0), axis=-1, arr=data_warp_x_inverse_no_outliers, ) data_warp_y_smooth = apply_along_axis( lambda m: smoothing_window(m, window_len=int(window_length), window="hanning", verbose=0), axis=-1, arr=data_warp_y_no_outliers, ) data_warp_y_smooth_inverse = apply_along_axis( lambda m: smoothing_window(m, window_len=int(window_length), window="hanning", verbose=0), axis=-1, arr=data_warp_y_inverse_no_outliers, ) print "\nSaving regularized warping fields..." # Get image dimensions of destination image nx, ny, nz, nt, px, py, pz, pt = sct.get_dimension(dest) data_warp_smooth = zeros(((((nx, ny, nz, 1, 3))))) data_warp_smooth[:, :, :, 0, 0] = data_warp_x_smooth data_warp_smooth[:, :, :, 0, 1] = data_warp_y_smooth data_warp_smooth_inverse = zeros(((((nx, ny, nz, 1, 3))))) data_warp_smooth_inverse[:, :, :, 0, 0] = data_warp_x_smooth_inverse data_warp_smooth_inverse[:, :, :, 0, 1] = data_warp_y_smooth_inverse # Force header's parameter to intent so that the file may be recognised as a warping field by ants hdr_warp.set_intent("vector", (), "") hdr_warp_inverse.set_intent("vector", (), "") img = Nifti1Image(data_warp_smooth, None, header=hdr_warp) img_inverse = Nifti1Image(data_warp_smooth_inverse, None, header=hdr_warp_inverse) save(img, filename=warp_forward_out) print "\tFile " + warp_forward_out + " saved." save(img_inverse, filename=warp_inverse_out) print "\tFile " + warp_inverse_out + " saved."
def register_slicereg2d_translation( src, dest, window_length=31, paramreg=Paramreg( step="0", type="im", algo="Translation", metric="MeanSquares", iter="10", shrink="1", smooth="0", gradStep="0.5" ), fname_mask="", warp_forward_out="step0Warp.nii.gz", warp_inverse_out="step0InverseWarp.nii.gz", factor=2, remove_temp_files=1, verbose=0, ants_registration_params={ "rigid": "", "affine": "", "compositeaffine": "", "similarity": "", "translation": "", "bspline": ",10", "gaussiandisplacementfield": ",3,0", "bsplinedisplacementfield": ",5,10", "syn": ",3,0", "bsplinesyn": ",1,3", }, ): """Slice-by-slice regularized registration by translation of two images. We first register slice-by-slice the two images using antsRegistration in 2D. Then we remove outliers using Median Absolute Deviation technique (MAD) and smooth the translations along x and y axis using moving average hanning window. Eventually, we generate two warping fields (forward and inverse) resulting from this regularized registration technique. The images must be of same size (otherwise generate_warping_field will not work for forward or inverse creation). input: src: name of moving image (type: string) dest: name of fixed image (type: string) window_length[optional]: size of window for moving average smoothing (type: int) paramreg[optional]: parameters of antsRegistration (type: Paramreg class from sct_register_multimodal) fname_mask[optional]: name of mask file (type: string) (parameter -x of antsRegistration) warp_forward_out[optional]: name of output forward warp (type: string) warp_inverse_out[optional]: name of output inverse warp (type: string) factor[optional]: sensibility factor for outlier detection (higher the factor, smaller the detection) (type: int or float) remove_temp_files[optional]: 1 to remove, 0 to keep (type: int) verbose[optional]: display parameter (type: int, value: 0,1 or 2) ants_registration_params[optional]: specific algorithm's parameters for antsRegistration (type: dictionary) output: creation of warping field files of name 'warp_forward_out' and 'warp_inverse_out'. """ from msct_register_regularized import register_images, generate_warping_field from numpy import asarray from msct_smooth import smoothing_window, outliers_detection, outliers_completion # Calculate displacement x_disp, y_disp = register_images( src, dest, mask=fname_mask, paramreg=paramreg, remove_tmp_folder=remove_temp_files, ants_registration_params=ants_registration_params, ) # Change to array x_disp_a = asarray(x_disp) y_disp_a = asarray(y_disp) # Detect outliers mask_x_a = outliers_detection(x_disp_a, type="median", factor=factor, return_filtered_signal="no", verbose=verbose) mask_y_a = outliers_detection(y_disp_a, type="median", factor=factor, return_filtered_signal="no", verbose=verbose) # Replace value of outliers by linear interpolation using closest non-outlier points x_disp_a_no_outliers = outliers_completion(mask_x_a, verbose=0) y_disp_a_no_outliers = outliers_completion(mask_y_a, verbose=0) # Smooth results x_disp_smooth = smoothing_window( x_disp_a_no_outliers, window_len=int(window_length), window="hanning", verbose=verbose ) y_disp_smooth = smoothing_window( y_disp_a_no_outliers, window_len=int(window_length), window="hanning", verbose=verbose ) # Generate warping field generate_warping_field(dest, x_disp_smooth, y_disp_smooth, fname=warp_forward_out) # Inverse warping field generate_warping_field(src, -x_disp_smooth, -y_disp_smooth, fname=warp_inverse_out)