def generate_output_file(fname_in, fname_out, verbose=1): """ Generate output file. Only works for images (e.g., nifti, nifti_gz) :param fname_in: :param fname_out: :param verbose: :return: fname_out """ # import stuff import shutil # for moving files path_in, file_in, ext_in = extract_fname(fname_in) path_out, file_out, ext_out = extract_fname(fname_out) # if input image does not exist, give error if not os.path.isfile(fname_in): printv(' ERROR: File '+fname_in+' does not exist. Exit program.', 1, 'error') sys.exit(2) # if input and output fnames are the same, do nothing and exit function if fname_in == fname_out: printv(' WARNING: fname_in and fname_out are the same. Do nothing.', verbose, 'warning') print ' File created: '+path_out+file_out+ext_out return path_out+file_out+ext_out # if fname_out already exists in nii or nii.gz format if os.path.isfile(path_out+file_out+ext_out): printv(' WARNING: File '+path_out+file_out+ext_out+' already exists. Deleting it...', 1, 'warning') os.remove(path_out+file_out+ext_out) if ext_in != ext_out: # Generate output file ''' # TRY TO UNCOMMENT THIS LINES AND RUN IT IN AN OTHER STATION THAN EVANS (testing of sct_label_vertebrae and sct_smooth_spinalcord never stops with this lines on evans) if ext_in == '.nii.gz' and ext_out == '.nii': # added to resolve issue #728 run('gunzip -f ' + fname_in) os.rename(path_in + file_in + '.nii', fname_out) else: ''' from sct_convert import convert convert(fname_in, fname_out) else: # Generate output file without changing the extension shutil.move(fname_in, fname_out) # # Move file to output folder (keep the same extension as input) # shutil.move(fname_in, path_out+file_out+ext_in) # # convert to nii (only if necessary) # if ext_out == '.nii' and ext_in != '.nii': # convert(path_out+file_out+ext_in, path_out+file_out+ext_out) # os.remove(path_out+file_out+ext_in) # remove nii.gz file # # convert to nii.gz (only if necessary) # if ext_out == '.nii.gz' and ext_in != '.nii.gz': # convert(path_out+file_out+ext_in, path_out+file_out+ext_out) # os.remove(path_out+file_out+ext_in) # remove nii file # display message printv(' File created: '+path_out+file_out+ext_out, verbose) # if verbose: # print ' File created: '+path_out+file_out+ext_out return path_out+file_out+ext_out
def setup_debug_folder(self): """ Sets up the folder for the step by step files for this algorithm The folder's absolute path can be found in the self.debug_folder property :return: None """ if self.produce_output: import time from sct_utils import slash_at_the_end folder = slash_at_the_end('scad_output_'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+folder, self.verbose) self.debug_folder = os.path.abspath(folder) conv.convert(str(self.input_image.absolutepath), str(self.debug_folder)+"/raw.nii.gz")
def scad_propseg_validation(folder_input, contrast): from sct_get_centerline import ind2sub import time import math import numpy import sct_convert as cnv t0 = time.time() current_folder = os.getcwd() os.chdir(folder_input) try: patients = next(os.walk('.'))[1] for i in patients: directory = i + "/" + str(contrast) try: os.chdir(directory) except Exception, e: print str(i)+" : "+contrast+" directory not found" try: if os.path.isfile(i+"_"+contrast+".nii.gz"): raw_image = Image(i+"_"+contrast+".nii.gz") elif os.path.isfile(contrast+".nii.gz"): raw_image = Image(contrast+".nii.gz") else: raise Exception("Patient scan not found") if os.path.isfile(i+"_"+contrast+"_manual_segmentation.nii.gz"): manual_segmentation = i+"_"+contrast+"_manual_segmentation.nii.gz" # Using propseg default sct.run("sct_propseg -i "+raw_image.absolutepath+" -t "+contrast) cnv.convert(raw_image.file_name+"_seg.nii.gz", "propseg_default.nii.gz") # Using scad scad = SCAD(raw_image, contrast=contrast, rm_tmp_file=1, verbose=1) scad.execute() # Using propseg with scad sct.run("sct_propseg -i "+raw_image.absolutepath+" -t "+contrast+" -init-centerline "+scad.output_filename) cnv.convert(raw_image.file_name+"_seg.nii.gz", "propseg_scad.nii.gz") # Calculate dice of propseg_default sct.run("sct_dice_coefficient propseg_default.nii.gz "+manual_segmentation+" -o propseg_default_result.txt") # Calculate dice of propseg_scad sct.run("sct_dice_coefficient propseg_scad.nii.gz "+manual_segmentation+" -o propseg_scad_result.txt") else: printv("Cannot find the manual segmentation", type="warning") except Exception, e: print e.message os.chdir(folder_input)
def generate_output_file(fname_in, fname_out, verbose=1): """ Generate output file. Only works for images (e.g., nifti, nifti_gz) :param fname_in: :param fname_out: :param verbose: :return: fname_out """ # import stuff import shutil # for moving files path_in, file_in, ext_in = extract_fname(fname_in) path_out, file_out, ext_out = extract_fname(fname_out) # if input image does not exist, give error if not os.path.isfile(fname_in): printv(' ERROR: File '+fname_in+' does not exist. Exit program.', 1, 'error') sys.exit(2) # if input and output fnames are the same, do nothing and exit function if fname_in == fname_out: printv(' WARNING: fname_in and fname_out are the same. Do nothing.', verbose, 'warning') print ' File created: '+path_out+file_out+ext_out return path_out+file_out+ext_out # if fname_out already exists in nii or nii.gz format if os.path.isfile(path_out+file_out+ext_out): printv(' WARNING: File '+path_out+file_out+ext_out+' already exists. Deleting it...', 1, 'warning') os.remove(path_out+file_out+ext_out) if ext_in != ext_out: # Generate output file from sct_convert import convert convert(fname_in, fname_out) else: # Generate output file without changing the extension shutil.move(fname_in, fname_out) # # Move file to output folder (keep the same extension as input) # shutil.move(fname_in, path_out+file_out+ext_in) # # convert to nii (only if necessary) # if ext_out == '.nii' and ext_in != '.nii': # convert(path_out+file_out+ext_in, path_out+file_out+ext_out) # os.remove(path_out+file_out+ext_in) # remove nii.gz file # # convert to nii.gz (only if necessary) # if ext_out == '.nii.gz' and ext_in != '.nii.gz': # convert(path_out+file_out+ext_in, path_out+file_out+ext_out) # os.remove(path_out+file_out+ext_in) # remove nii file # display message printv(' File created: '+path_out+file_out+ext_out, verbose) # if verbose: # print ' File created: '+path_out+file_out+ext_out return path_out+file_out+ext_out
def register_slicewise(fname_src, fname_dest, fname_mask='', warp_forward_out='step0Warp.nii.gz', warp_inverse_out='step0InverseWarp.nii.gz', paramreg=None, ants_registration_params=None, path_qc='./', verbose=0): # create temporary folder path_tmp = sct.tmp_create(verbose) # copy data to temp folder sct.printv('\nCopy input data to temp folder...', verbose) convert(fname_src, path_tmp+'src.nii') convert(fname_dest, path_tmp+'dest.nii') if fname_mask != '': convert(fname_mask, path_tmp+'mask.nii.gz') # go to temporary folder chdir(path_tmp) # Calculate displacement if paramreg.algo == 'centermass': # translation of center of mass between source and destination in voxel space register2d_centermassrot('src.nii', 'dest.nii', fname_warp=warp_forward_out, fname_warp_inv=warp_inverse_out, rot=0, poly=int(paramreg.poly), path_qc=path_qc, verbose=verbose) elif paramreg.algo == 'centermassrot': # translation of center of mass and rotation based on source and destination first eigenvectors from PCA. register2d_centermassrot('src.nii', 'dest.nii', fname_warp=warp_forward_out, fname_warp_inv=warp_inverse_out, rot=1, poly=int(paramreg.poly), path_qc=path_qc, verbose=verbose, pca_eigenratio_th=float(paramreg.pca_eigenratio_th)) elif paramreg.algo == 'columnwise': # scaling R-L, then column-wise center of mass alignment and scaling register2d_columnwise('src.nii', 'dest.nii', fname_warp=warp_forward_out, fname_warp_inv=warp_inverse_out, verbose=verbose, path_qc=path_qc, smoothWarpXY=int(paramreg.smoothWarpXY)) else: # convert SCT flags into ANTs-compatible flags algo_dic = {'translation': 'Translation', 'rigid': 'Rigid', 'affine': 'Affine', 'syn': 'SyN', 'bsplinesyn': 'BSplineSyN', 'centermass': 'centermass'} paramreg.algo = algo_dic[paramreg.algo] # run slicewise registration register2d('src.nii', 'dest.nii', fname_mask=fname_mask, fname_warp=warp_forward_out, fname_warp_inv=warp_inverse_out, paramreg=paramreg, ants_registration_params=ants_registration_params, verbose=verbose) sct.printv('\nMove warping fields to parent folder...', verbose) sct.run('mv '+warp_forward_out+' ../') sct.run('mv '+warp_inverse_out+' ../') # go back to parent folder chdir('../')
def main(): # Initialization fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI fname_data = '' fname_bvecs = '' fname_bvals = '' path_out = '' average = param.average verbose = param.verbose remove_tmp_files = param.remove_tmp_files start_time = time.time() # get path of the toolbox status, path_sct = commands.getstatusoutput('echo $SCT_DIR') # Parameters for debug mode if param.debug: fname_data = path_sct+'/testing/data/errsm_23/dmri/dmri.nii.gz' fname_bvecs = path_sct+'/testing/data/errsm_23/dmri/bvecs.txt' average = 1 verbose = 1 else: # Check input parameters try: opts, args = getopt.getopt(sys.argv[1:],'ha:b:i:m:o:r:v:') except getopt.GetoptError: usage() if not opts: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ("-a"): average = int(arg) elif opt in ("-b"): fname_bvecs = arg elif opt in ("-i"): fname_data = arg elif opt in ('-m'): fname_bvals = arg elif opt in ("-o"): path_out = arg elif opt in ("-r"): remove_temp_file = int(arg) elif opt in ('-v'): verbose = int(arg) # display usage if a mandatory argument is not provided if fname_data == '' or fname_bvecs == '': usage() # check existence of input files sct.check_file_exist(fname_data, verbose) sct.check_file_exist(fname_bvecs, verbose) if not fname_bvals == '': sct.check_file_exist(fname_bvals, verbose) # print arguments sct.printv('\nInput parameters:', verbose) sct.printv(' input file ............'+fname_data, verbose) sct.printv(' bvecs file ............'+fname_bvecs, verbose) sct.printv(' average ...............'+str(average), verbose) # Get full path fname_data = os.path.abspath(fname_data) fname_bvecs = os.path.abspath(fname_bvecs) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(fname_data) # # get output folder # if path_out == '': # path_out = '' # create temporary folder sct.printv('\nCreate temporary folder...', verbose) path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+path_tmp, verbose) # copy files into tmp folder and convert to nifti sct.printv('\nCopy files into temporary folder...', verbose) from sct_convert import convert if not convert(fname_data, path_tmp+'dmri.nii'): sct.printv('ERROR in convert.', 1, 'error') sct.run('cp '+fname_bvecs+' '+path_tmp+'bvecs', verbose) # go to tmp folder os.chdir(path_tmp) # Get size of data sct.printv('\nGet dimensions data...', verbose) nx, ny, nz, nt, px, py, pz, pt = Image('dmri.nii').dim sct.printv('.. '+str(nx)+' x '+str(ny)+' x '+str(nz)+' x '+str(nt), verbose) # Identify b=0 and DWI images index_b0, index_dwi, nb_b0, nb_dwi = identify_b0(fname_bvecs, fname_bvals, param.bval_min, verbose) # Split into T dimension sct.printv('\nSplit along T dimension...', verbose) from sct_split_data import split_data if not split_data('dmri.nii', 3, '_T'): sct.printv('ERROR in split_data.', 1, 'error') # Merge b=0 images sct.printv('\nMerge b=0...', verbose) cmd = 'sct_concat_data -dim t -o b0.nii -i ' for it in range(nb_b0): cmd = cmd + 'dmri_T' + str(index_b0[it]).zfill(4) + '.nii,' cmd = cmd[:-1] # remove ',' at the end of the string status, output = sct.run(cmd, param.verbose) # Average b=0 images if average: sct.printv('\nAverage b=0...', verbose) sct.run('sct_maths -i b0.nii -o b0_mean.nii -mean t', verbose) # Merge DWI sct.printv('\nMerge DWI...', verbose) cmd = 'sct_concat_data -dim t -o dwi.nii -i ' for it in range(nb_dwi): cmd = cmd + 'dmri_T' + str(index_dwi[it]).zfill(4) + '.nii,' cmd = cmd[:-1] # remove ',' at the end of the string status, output = sct.run(cmd, param.verbose) # Average DWI images if average: sct.printv('\nAverage DWI...', verbose) sct.run('sct_maths -i dwi.nii -o dwi_mean.nii -mean t', verbose) # if not average_data_across_dimension('dwi.nii', 'dwi_mean.nii', 3): # sct.printv('ERROR in average_data_across_dimension', 1, 'error') # sct.run(fsloutput + 'fslmaths dwi -Tmean dwi_mean', verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(path_tmp+'b0.nii', path_out+'b0'+ext_data, verbose) sct.generate_output_file(path_tmp+'dwi.nii', path_out+'dwi'+ext_data, verbose) if average: sct.generate_output_file(path_tmp+'b0_mean.nii', path_out+'b0_mean'+ext_data, verbose) sct.generate_output_file(path_tmp+'dwi_mean.nii', path_out+'dwi_mean'+ext_data, verbose) # Remove temporary files if remove_tmp_files == 1: sct.printv('\nRemove temporary files...', verbose) sct.run('rm -rf '+path_tmp, verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: '+str(int(round(elapsed_time)))+'s', verbose) # to view results sct.printv('\nTo view results, type: ', verbose) if average: sct.printv('fslview b0 b0_mean dwi dwi_mean &\n', verbose) else: sct.printv('fslview b0 dwi &\n', verbose)
def main(args=None): # initialization start_time = time.time() param = Param() # reducing the number of CPU used for moco (see issue #201) os.environ["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = "1" # check user arguments if not args: args = sys.argv[1:] # Get parser info parser = get_parser() arguments = parser.parse(sys.argv[1:]) param.fname_data = arguments['-i'] if '-g' in arguments: param.group_size = arguments['-g'] if '-m' in arguments: param.fname_mask = arguments['-m'] if '-param' in arguments: param.update(arguments['-param']) if '-x' in arguments: param.interp = arguments['-x'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-r' in arguments: param.remove_temp_files = int(arguments['-r']) if '-v' in arguments: param.verbose = int(arguments['-v']) sct.printv('\nInput parameters:', param.verbose) sct.printv(' input file ............' + param.fname_data, param.verbose) # Get full path param.fname_data = os.path.abspath(param.fname_data) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) path_tmp = sct.tmp_create(basename="fmri_moco", verbose=param.verbose) # Copying input data to tmp folder and convert to nii # TODO: no need to do that (takes time for nothing) sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, os.path.join(path_tmp, "fmri.nii"), squeeze_data=False) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # run moco fmri_moco(param) # come back os.chdir(curdir) # Generate output files fname_fmri_moco = os.path.join(path_out, file_data + param.suffix + ext_data) sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) if os.path.isfile(os.path.join(path_tmp, "fmri" + param.suffix + '.nii')): sct.printv(os.path.join(path_tmp, "fmri" + param.suffix + '.nii')) sct.printv(os.path.join(path_out, file_data + param.suffix + ext_data)) sct.generate_output_file(os.path.join(path_tmp, "fmri" + param.suffix + '.nii'), os.path.join(path_out, file_data + param.suffix + ext_data), param.verbose) sct.generate_output_file(os.path.join(path_tmp, "fmri" + param.suffix + '_mean.nii'), os.path.join(path_out, file_data + param.suffix + '_mean' + ext_data), param.verbose) # Delete temporary files if param.remove_temp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.rmtree(path_tmp, verbose=param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's', param.verbose) sct.display_viewer_syntax([fname_fmri_moco, file_data], mode='ortho,ortho')
def create_mask(param): fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI # parse argument for method method_type = param.process[0] # check method val if not method_type == 'center': method_val = param.process[1] # check existence of input files if method_type == 'centerline': sct.check_file_exist(method_val, param.verbose) # Extract path/file/extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) # Get output folder and file name if param.fname_out == '': param.fname_out = param.file_prefix + file_data + ext_data # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.tmp_create(param.verbose) # )sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) # sct.run('mkdir '+path_tmp, param.verbose) sct.printv('\nCheck orientation...', param.verbose) orientation_input = get_orientation(Image(param.fname_data)) sct.printv('.. ' + orientation_input, param.verbose) reorient_coordinates = False # copy input data to tmp folder convert(param.fname_data, path_tmp + 'data.nii') if method_type == 'centerline': convert(method_val, path_tmp + 'centerline.nii.gz') if method_type == 'point': convert(method_val, path_tmp + 'point.nii.gz') # go to tmp folder os.chdir(path_tmp) # reorient to RPI sct.printv('\nReorient to RPI...', param.verbose) # if not orientation_input == 'RPI': sct.run('sct_image -i data.nii -o data_RPI.nii -setorient RPI -v 0', verbose=False) if method_type == 'centerline': sct.run( 'sct_image -i centerline.nii.gz -o centerline_RPI.nii.gz -setorient RPI -v 0', verbose=False) if method_type == 'point': sct.run( 'sct_image -i point.nii.gz -o point_RPI.nii.gz -setorient RPI -v 0', verbose=False) # # if method_type == 'centerline': # orientation_centerline = get_orientation_3d(method_val, filename=True) # if not orientation_centerline == 'RPI': # sct.run('sct_image -i ' + method_val + ' -o ' + path_tmp + 'centerline.nii.gz' + ' -setorient RPI -v 0', verbose=False) # else: # convert(method_val, path_tmp+'centerline.nii.gz') # Get dimensions of data sct.printv('\nGet dimensions of data...', param.verbose) nx, ny, nz, nt, px, py, pz, pt = Image('data_RPI.nii').dim sct.printv( ' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt), param.verbose) # in case user input 4d data if nt != 1: sct.printv( 'WARNING in ' + os.path.basename(__file__) + ': Input image is 4d but output mask will 3D.', param.verbose, 'warning') # extract first volume to have 3d reference nii = Image('data_RPI.nii') data3d = nii.data[:, :, :, 0] nii.data = data3d nii.save() if method_type == 'coord': # parse to get coordinate coord = map(int, method_val.split('x')) if method_type == 'point': # get file name fname_point = method_val # extract coordinate of point sct.printv('\nExtract coordinate of point...', param.verbose) # TODO: change this way to remove dependence to sct.run. ProcessLabels.display_voxel returns list of coordinates status, output = sct.run( 'sct_label_utils -i point_RPI.nii.gz -display', param.verbose) # parse to get coordinate coord = output[output.find('Position=') + 10:-17].split(',') if method_type == 'center': # set coordinate at center of FOV coord = round(float(nx) / 2), round(float(ny) / 2) if method_type == 'centerline': # get name of centerline from user argument fname_centerline = 'centerline_RPI.nii.gz' else: # generate volume with line along Z at coordinates 'coord' sct.printv('\nCreate line...', param.verbose) fname_centerline = create_line(param, 'data_RPI.nii', coord, nz) # create mask sct.printv('\nCreate mask...', param.verbose) centerline = nibabel.load(fname_centerline) # open centerline hdr = centerline.get_header() # get header hdr.set_data_dtype('uint8') # set imagetype to uint8 spacing = hdr.structarr['pixdim'] data_centerline = centerline.get_data() # get centerline # if data is 2D, reshape with empty third dimension if len(data_centerline.shape) == 2: data_centerline_shape = list(data_centerline.shape) data_centerline_shape.append(1) data_centerline = data_centerline.reshape(data_centerline_shape) z_centerline_not_null = [ iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any() ] # get center of mass of the centerline cx = [0] * nz cy = [0] * nz for iz in range(0, nz, 1): if iz in z_centerline_not_null: cx[iz], cy[iz] = ndimage.measurements.center_of_mass( numpy.array(data_centerline[:, :, iz])) # create 2d masks file_mask = 'data_mask' for iz in range(nz): if iz not in z_centerline_not_null: # write an empty nifty volume img = nibabel.Nifti1Image(data_centerline[:, :, iz], None, hdr) nibabel.save(img, (file_mask + str(iz) + '.nii')) else: center = numpy.array([cx[iz], cy[iz]]) mask2d = create_mask2d(param, center, param.shape, param.size, nx, ny, even=param.even, spacing=spacing) # Write NIFTI volumes img = nibabel.Nifti1Image(mask2d, None, hdr) nibabel.save(img, (file_mask + str(iz) + '.nii')) # merge along Z # cmd = 'fslmerge -z mask ' # CHANGE THAT CAN IMPACT SPEED: # related to issue #755, we cannot open more than 256 files at one time. # to solve this issue, we do not open more than 100 files ''' im_list = [] im_temp = [] for iz in range(nz_not_null): if iz != 0 and iz % 100 == 0: im_temp.append(concat_data(im_list, 2)) im_list = [Image(file_mask + str(iz) + '.nii')] else: im_list.append(Image(file_mask+str(iz)+'.nii')) if im_temp: im_temp.append(concat_data(im_list, 2)) im_out = concat_data(im_temp, 2, no_expand=True) else: im_out = concat_data(im_list, 2) ''' fname_list = [file_mask + str(iz) + '.nii' for iz in range(nz)] im_out = concat_data(fname_list, dim=2) im_out.setFileName('mask_RPI.nii.gz') im_out.save() # reorient if necessary # if not orientation_input == 'RPI': sct.run( 'sct_image -i mask_RPI.nii.gz -o mask.nii.gz -setorient ' + orientation_input, param.verbose) # copy header input --> mask im_dat = Image('data.nii') im_mask = Image('mask.nii.gz') im_mask = copy_header(im_dat, im_mask) im_mask.save() # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(path_tmp + 'mask.nii.gz', param.fname_out) # Remove temporary files if param.remove_tmp_files == 1: sct.printv('\nRemove temporary files...', param.verbose) sct.run('rm -rf ' + path_tmp, param.verbose, error_exit='warning') # to view results sct.printv('\nDone! To view results, type:', param.verbose) sct.printv( 'fslview ' + param.fname_data + ' ' + param.fname_out + ' -l Red -t 0.5 &', param.verbose, 'info')
def main(args=None): if args is None: args = sys.argv[1:] # initialize parameters param = Param() # Initialization fname_output = '' path_out = '' fname_src_seg = '' fname_dest_seg = '' fname_src_label = '' fname_dest_label = '' generate_warpinv = 1 start_time = time.time() # get path of the toolbox status, path_sct = commands.getstatusoutput('echo $SCT_DIR') # get default registration parameters # step1 = Paramreg(step='1', type='im', algo='syn', metric='MI', iter='5', shrink='1', smooth='0', gradStep='0.5') step0 = Paramreg( step='0', type='im', algo='syn', metric='MI', iter='0', shrink='1', smooth='0', gradStep='0.5', slicewise='0', dof='Tx_Ty_Tz_Rx_Ry_Rz') # only used to put src into dest space step1 = Paramreg(step='1', type='im') paramreg = ParamregMultiStep([step0, step1]) parser = get_parser(paramreg=paramreg) arguments = parser.parse(args) # get arguments fname_src = arguments['-i'] fname_dest = arguments['-d'] if '-iseg' in arguments: fname_src_seg = arguments['-iseg'] if '-dseg' in arguments: fname_dest_seg = arguments['-dseg'] if '-ilabel' in arguments: fname_src_label = arguments['-ilabel'] if '-dlabel' in arguments: fname_dest_label = arguments['-dlabel'] if '-o' in arguments: fname_output = arguments['-o'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-owarp' in arguments: fname_output_warp = arguments['-owarp'] else: fname_output_warp = '' if '-initwarp' in arguments: fname_initwarp = os.path.abspath(arguments['-initwarp']) else: fname_initwarp = '' if '-initwarpinv' in arguments: fname_initwarpinv = os.path.abspath(arguments['-initwarpinv']) else: fname_initwarpinv = '' if '-m' in arguments: fname_mask = arguments['-m'] else: fname_mask = '' padding = arguments['-z'] if "-param" in arguments: paramreg_user = arguments['-param'] # update registration parameters for paramStep in paramreg_user: paramreg.addStep(paramStep) identity = int(arguments['-identity']) interp = arguments['-x'] remove_temp_files = int(arguments['-r']) verbose = int(arguments['-v']) # sct.printv(arguments) sct.printv('\nInput parameters:') sct.printv(' Source .............. ' + fname_src) sct.printv(' Destination ......... ' + fname_dest) sct.printv(' Init transfo ........ ' + fname_initwarp) sct.printv(' Mask ................ ' + fname_mask) sct.printv(' Output name ......... ' + fname_output) # sct.printv(' Algorithm ........... '+paramreg.algo) # sct.printv(' Number of iterations '+paramreg.iter) # sct.printv(' Metric .............. '+paramreg.metric) sct.printv(' Remove temp files ... ' + str(remove_temp_files)) sct.printv(' Verbose ............. ' + str(verbose)) # update param param.verbose = verbose param.padding = padding param.fname_mask = fname_mask param.remove_temp_files = remove_temp_files # Get if input is 3D sct.printv('\nCheck if input data are 3D...', verbose) sct.check_if_3d(fname_src) sct.check_if_3d(fname_dest) # Check if user selected type=seg, but did not input segmentation data if 'paramreg_user' in locals(): if True in [ 'type=seg' in paramreg_user[i] for i in range(len(paramreg_user)) ]: if fname_src_seg == '' or fname_dest_seg == '': sct.printv( '\nERROR: if you select type=seg you must specify -iseg and -dseg flags.\n', 1, 'error') # Extract path, file and extension path_src, file_src, ext_src = sct.extract_fname(fname_src) path_dest, file_dest, ext_dest = sct.extract_fname(fname_dest) # check if source and destination images have the same name (related to issue #373) # If so, change names to avoid conflict of result files and warns the user suffix_src, suffix_dest = '_reg', '_reg' if file_src == file_dest: suffix_src, suffix_dest = '_src_reg', '_dest_reg' # define output folder and file name if fname_output == '': path_out = '' if not path_out else path_out # output in user's current directory file_out = file_src + suffix_src file_out_inv = file_dest + suffix_dest ext_out = ext_src else: path, file_out, ext_out = sct.extract_fname(fname_output) path_out = path if not path_out else path_out file_out_inv = file_out + '_inv' # create QC folder sct.create_folder(param.path_qc) # create temporary folder path_tmp = sct.tmp_create() # copy files to temporary folder from sct_convert import convert sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) convert(fname_src, path_tmp + 'src.nii') convert(fname_dest, path_tmp + 'dest.nii') if fname_src_seg: convert(fname_src_seg, path_tmp + 'src_seg.nii') convert(fname_dest_seg, path_tmp + 'dest_seg.nii') if fname_src_label: convert(fname_src_label, path_tmp + 'src_label.nii') convert(fname_dest_label, path_tmp + 'dest_label.nii') if fname_mask != '': convert(fname_mask, path_tmp + 'mask.nii.gz') # go to tmp folder os.chdir(path_tmp) # reorient destination to RPI sct.run('sct_image -i dest.nii -setorient RPI -o dest_RPI.nii') if fname_dest_seg: sct.run('sct_image -i dest_seg.nii -setorient RPI -o dest_seg_RPI.nii') if fname_dest_label: sct.run( 'sct_image -i dest_label.nii -setorient RPI -o dest_label_RPI.nii') if identity: # overwrite paramreg and only do one identity transformation step0 = Paramreg(step='0', type='im', algo='syn', metric='MI', iter='0', shrink='1', smooth='0', gradStep='0.5') paramreg = ParamregMultiStep([step0]) # Put source into destination space using header (no estimation -- purely based on header) # TODO: Check if necessary to do that # TODO: use that as step=0 # sct.printv('\nPut source into destination space using header...', verbose) # sct.run('isct_antsRegistration -d 3 -t Translation[0] -m MI[dest_pad.nii,src.nii,1,16] -c 0 -f 1 -s 0 -o [regAffine,src_regAffine.nii] -n BSpline[3]', verbose) # if segmentation, also do it for seg # initialize list of warping fields warp_forward = [] warp_inverse = [] # initial warping is specified, update list of warping fields and skip step=0 if fname_initwarp: sct.printv('\nSkip step=0 and replace with initial transformations: ', param.verbose) sct.printv(' ' + fname_initwarp, param.verbose) # sct.run('cp '+fname_initwarp+' warp_forward_0.nii.gz', verbose) warp_forward = [fname_initwarp] start_step = 1 if fname_initwarpinv: warp_inverse = [fname_initwarpinv] else: sct.printv( '\nWARNING: No initial inverse warping field was specified, therefore the inverse warping field will NOT be generated.', param.verbose, 'warning') generate_warpinv = 0 else: start_step = 0 # loop across registration steps for i_step in range(start_step, len(paramreg.steps)): sct.printv('\n--\nESTIMATE TRANSFORMATION FOR STEP #' + str(i_step), param.verbose) # identify which is the src and dest if paramreg.steps[str(i_step)].type == 'im': src = 'src.nii' dest = 'dest_RPI.nii' interp_step = 'spline' elif paramreg.steps[str(i_step)].type == 'seg': src = 'src_seg.nii' dest = 'dest_seg_RPI.nii' interp_step = 'nn' elif paramreg.steps[str(i_step)].type == 'label': src = 'src_label.nii' dest = 'dest_label_RPI.nii' interp_step = 'nn' else: # src = dest = interp_step = None sct.printv('ERROR: Wrong image type.', 1, 'error') # if step>0, apply warp_forward_concat to the src image to be used if i_step > 0: sct.printv('\nApply transformation from previous step', param.verbose) sct.run( 'sct_apply_transfo -i ' + src + ' -d ' + dest + ' -w ' + ','.join(warp_forward) + ' -o ' + sct.add_suffix(src, '_reg') + ' -x ' + interp_step, verbose) src = sct.add_suffix(src, '_reg') # register src --> dest warp_forward_out, warp_inverse_out = register(src, dest, paramreg, param, str(i_step)) warp_forward.append(warp_forward_out) warp_inverse.insert(0, warp_inverse_out) # Concatenate transformations sct.printv('\nConcatenate transformations...', verbose) sct.run( 'sct_concat_transfo -w ' + ','.join(warp_forward) + ' -d dest.nii -o warp_src2dest.nii.gz', verbose) sct.run( 'sct_concat_transfo -w ' + ','.join(warp_inverse) + ' -d src.nii -o warp_dest2src.nii.gz', verbose) # Apply warping field to src data sct.printv('\nApply transfo source --> dest...', verbose) sct.run( 'sct_apply_transfo -i src.nii -o src_reg.nii -d dest.nii -w warp_src2dest.nii.gz -x ' + interp, verbose) sct.printv('\nApply transfo dest --> source...', verbose) sct.run( 'sct_apply_transfo -i dest.nii -o dest_reg.nii -d src.nii -w warp_dest2src.nii.gz -x ' + interp, verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', verbose) # generate: src_reg fname_src2dest = sct.generate_output_file(path_tmp + 'src_reg.nii', path_out + file_out + ext_out, verbose) # generate: forward warping field if fname_output_warp == '': fname_output_warp = path_out + 'warp_' + file_src + '2' + file_dest + '.nii.gz' sct.generate_output_file(path_tmp + 'warp_src2dest.nii.gz', fname_output_warp, verbose) if generate_warpinv: # generate: dest_reg fname_dest2src = sct.generate_output_file( path_tmp + 'dest_reg.nii', path_out + file_out_inv + ext_dest, verbose) # generate: inverse warping field sct.generate_output_file( path_tmp + 'warp_dest2src.nii.gz', path_out + 'warp_' + file_dest + '2' + file_src + '.nii.gz', verbose) # Delete temporary files if remove_temp_files: sct.printv('\nRemove temporary files...', verbose) sct.run('rm -rf ' + path_tmp, verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv( '\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's', verbose) sct.printv('\nTo view results, type:', verbose) if generate_warpinv: sct.printv('fslview ' + fname_src + ' ' + fname_dest2src + ' &', verbose, 'info') sct.printv('fslview ' + fname_dest + ' ' + fname_src2dest + ' &\n', verbose, 'info')
def moco(param): # retrieve parameters file_data = param.file_data file_target = param.file_target folder_mat = param.mat_moco # output folder of mat file todo = param.todo suffix = param.suffix verbose = param.verbose # other parameters file_mask = 'mask.nii' sct.printv('\nInput parameters:', param.verbose) sct.printv(' Input file ............' + file_data, param.verbose) sct.printv(' Reference file ........' + file_target, param.verbose) sct.printv(' Polynomial degree .....' + param.poly, param.verbose) sct.printv(' Smoothing kernel ......' + param.smooth, param.verbose) sct.printv(' Gradient step .........' + param.gradStep, param.verbose) sct.printv(' Metric ................' + param.metric, param.verbose) sct.printv(' Sampling ..............' + param.sampling, param.verbose) sct.printv(' Todo ..................' + todo, param.verbose) sct.printv(' Mask .................' + param.fname_mask, param.verbose) sct.printv(' Output mat folder .....' + folder_mat, param.verbose) # create folder for mat files sct.create_folder(folder_mat) # Get size of data sct.printv('\nData dimensions:', verbose) im_data = Image(param.file_data) nx, ny, nz, nt, px, py, pz, pt = im_data.dim sct.printv( (' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt)), verbose) # copy file_target to a temporary file sct.printv('\nCopy file_target to a temporary file...', verbose) file_target = "target.nii.gz" convert(param.file_target, file_target) # If scan is sagittal, split src and target along Z (slice) if param.is_sagittal: dim_sag = 2 # TODO: find it # z-split data (time series) im_z_list = split_data(im_data, dim=dim_sag, squeeze_data=False) file_data_splitZ = [] for im_z in im_z_list: im_z.save() file_data_splitZ.append(im_z.absolutepath) # z-split target im_targetz_list = split_data(Image(file_target), dim=dim_sag, squeeze_data=False) file_target_splitZ = [] for im_targetz in im_targetz_list: im_targetz.save() file_target_splitZ.append(im_targetz.absolutepath) # z-split mask (if exists) if not param.fname_mask == '': im_maskz_list = split_data(Image(file_mask), dim=dim_sag, squeeze_data=False) file_mask_splitZ = [] for im_maskz in im_maskz_list: im_maskz.save() file_mask_splitZ.append(im_maskz.absolutepath) # initialize file list for output matrices file_mat = np.empty((nz, nt), dtype=object) # axial orientation else: file_data_splitZ = [file_data] # TODO: make it absolute like above file_target_splitZ = [file_target] # TODO: make it absolute like above # initialize file list for output matrices file_mat = np.empty((1, nt), dtype=object) # deal with mask if not param.fname_mask == '': convert(param.fname_mask, file_mask, squeeze_data=False) im_maskz_list = [Image(file_mask) ] # use a list with single element # Loop across file list, where each file is either a 2D volume (if sagittal) or a 3D volume (otherwise) # file_mat = tuple([[[] for i in range(nt)] for i in range(nz)]) file_data_splitZ_moco = [] sct.printv( '\nRegister. Loop across Z (note: there is only one Z if orientation is axial' ) for file in file_data_splitZ: iz = file_data_splitZ.index(file) # Split data along T dimension # sct.printv('\nSplit data along T dimension.', verbose) im_z = Image(file) list_im_zt = split_data(im_z, dim=3) file_data_splitZ_splitT = [] for im_zt in list_im_zt: im_zt.save(verbose=0) file_data_splitZ_splitT.append(im_zt.absolutepath) # file_data_splitT = file_data + '_T' # Motion correction: initialization index = np.arange(nt) file_data_splitT_num = [] file_data_splitZ_splitT_moco = [] failed_transfo = [0 for i in range(nt)] # Motion correction: Loop across T for indice_index in tqdm(range(nt), unit='iter', unit_scale=False, desc="Z=" + str(iz) + "/" + str(len(file_data_splitZ) - 1), ascii=True, ncols=80): # create indices and display stuff it = index[indice_index] file_mat[iz][it] = os.path.join( folder_mat, "mat.Z") + str(iz).zfill(4) + 'T' + str(it).zfill(4) file_data_splitZ_splitT_moco.append( sct.add_suffix(file_data_splitZ_splitT[it], '_moco')) # deal with masking if not param.fname_mask == '': input_mask = im_maskz_list[iz] else: input_mask = None # run 3D registration failed_transfo[it] = register(param, file_data_splitZ_splitT[it], file_target_splitZ[iz], file_mat[iz][it], file_data_splitZ_splitT_moco[it], im_mask=input_mask) # average registered volume with target image # N.B. use weighted averaging: (target * nb_it + moco) / (nb_it + 1) if param.iterAvg and indice_index < 10 and failed_transfo[ it] == 0 and not param.todo == 'apply': im_targetz = Image(file_target_splitZ[iz]) data_targetz = im_targetz.data data_mocoz = Image(file_data_splitZ_splitT_moco[it]).data data_targetz = (data_targetz * (indice_index + 1) + data_mocoz) / (indice_index + 2) im_targetz.data = data_targetz im_targetz.save(verbose=0) # Replace failed transformation with the closest good one fT = [i for i, j in enumerate(failed_transfo) if j == 1] gT = [i for i, j in enumerate(failed_transfo) if j == 0] for it in range(len(fT)): abs_dist = [np.abs(gT[i] - fT[it]) for i in range(len(gT))] if not abs_dist == []: index_good = abs_dist.index(min(abs_dist)) sct.printv( ' transfo #' + str(fT[it]) + ' --> use transfo #' + str(gT[index_good]), verbose) # copy transformation sct.copy(file_mat[iz][gT[index_good]] + 'Warp.nii.gz', file_mat[iz][fT[it]] + 'Warp.nii.gz') # apply transformation sct_apply_transfo.main(args=[ '-i', file_data_splitZ_splitT[fT[it]], '-d', file_target, '-w', file_mat[iz][fT[it]] + 'Warp.nii.gz', '-o', file_data_splitZ_splitT_moco[fT[it]], '-x', param.interp ]) else: # exit program if no transformation exists. sct.printv( '\nERROR in ' + os.path.basename(__file__) + ': No good transformation exist. Exit program.\n', verbose, 'error') sys.exit(2) # Merge data along T file_data_splitZ_moco.append(sct.add_suffix(file, suffix)) if todo != 'estimate': im_out = concat_data(file_data_splitZ_splitT_moco, 3) im_out.save(file_data_splitZ_moco[iz]) # If sagittal, merge along Z if param.is_sagittal: im_out = concat_data(file_data_splitZ_moco, 2) dirname, basename, ext = sct.extract_fname(file_data) path_out = os.path.join(dirname, basename + suffix + ext) im_out.save(path_out) return file_mat
def check_and_correct_segmentation(fname_segmentation, fname_centerline, folder_output='', threshold_distance=5.0, remove_temp_files=1, verbose=0): """ This function takes the outputs of isct_propseg (centerline and segmentation) and check if the centerline of the segmentation is coherent with the centerline provided by the isct_propseg, especially on the edges (related to issue #1074). Args: fname_segmentation: filename of binary segmentation fname_centerline: filename of binary centerline threshold_distance: threshold, in mm, beyond which centerlines are not coherent verbose: Returns: None """ sct.printv('\nCheck consistency of segmentation...', verbose) # creating a temporary folder in which all temporary files will be placed and deleted afterwards path_tmp = sct.tmp_create(basename="propseg", verbose=verbose) from sct_convert import convert convert(fname_segmentation, os.path.join(path_tmp, "tmp.segmentation.nii.gz"), verbose=0) convert(fname_centerline, os.path.join(path_tmp, "tmp.centerline.nii.gz"), verbose=0) fname_seg_absolute = os.path.abspath(fname_segmentation) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # convert segmentation image to RPI im_input = Image('tmp.segmentation.nii.gz') image_input_orientation = im_input.orientation sct_image.main("-i tmp.segmentation.nii.gz -setorient RPI -o tmp.segmentation_RPI.nii.gz -v 0".split()) sct_image.main("-i tmp.centerline.nii.gz -setorient RPI -o tmp.centerline_RPI.nii.gz -v 0".split()) # go through segmentation image, and compare with centerline from propseg im_seg = Image('tmp.segmentation_RPI.nii.gz') im_centerline = Image('tmp.centerline_RPI.nii.gz') # Get size of data sct.printv('\nGet data dimensions...', verbose) nx, ny, nz, nt, px, py, pz, pt = im_seg.dim # extraction of centerline provided by isct_propseg and computation of center of mass for each slice # the centerline is defined as the center of the tubular mesh outputed by propseg. centerline, key_centerline = {}, [] for i in range(nz): slice = im_centerline.data[:, :, i] if np.any(slice): x_centerline, y_centerline = ndi.measurements.center_of_mass(slice) centerline[str(i)] = [x_centerline, y_centerline] key_centerline.append(i) minz_centerline = np.min(key_centerline) maxz_centerline = np.max(key_centerline) mid_slice = int((maxz_centerline - minz_centerline) / 2) # for each slice of the segmentation, check if only one object is present. If not, remove the slice from segmentation. # If only one object (the spinal cord) is present in the slice, check if its center of mass is close to the centerline of isct_propseg. slices_to_remove = [False] * nz # flag that decides if the slice must be removed for i in range(minz_centerline, maxz_centerline + 1): # extraction of slice slice = im_seg.data[:, :, i] distance = -1 label_objects, nb_labels = ndi.label(slice) # count binary objects in the slice if nb_labels > 1: # if there is more that one object in the slice, the slice is removed from the segmentation slices_to_remove[i] = True elif nb_labels == 1: # check if the centerline is coherent with the one from isct_propseg x_centerline, y_centerline = ndi.measurements.center_of_mass(slice) slice_nearest_coord = min(key_centerline, key=lambda x: abs(x - i)) coord_nearest_coord = centerline[str(slice_nearest_coord)] distance = np.sqrt(((x_centerline - coord_nearest_coord[0]) * px) ** 2 + ((y_centerline - coord_nearest_coord[1]) * py) ** 2 + ((i - slice_nearest_coord) * pz) ** 2) if distance >= threshold_distance: # threshold must be adjusted, default is 5 mm slices_to_remove[i] = True # Check list of removal and keep one continuous centerline (improve this comment) # Method: # starting from mid-centerline (in both directions), the first True encountered is applied to all following slices slice_to_change = False for i in range(mid_slice, nz): if slice_to_change: slices_to_remove[i] = True elif slices_to_remove[i]: slice_to_change = True slice_to_change = False for i in range(mid_slice, 0, -1): if slice_to_change: slices_to_remove[i] = True elif slices_to_remove[i]: slice_to_change = True for i in range(0, nz): # remove the slice if slices_to_remove[i]: im_seg.data[:, :, i] *= 0 # saving the image im_seg.save('tmp.segmentation_RPI_c.nii.gz') # replacing old segmentation with the corrected one sct_image.main('-i tmp.segmentation_RPI_c.nii.gz -setorient {} -o {} -v 0'. format(image_input_orientation, fname_seg_absolute).split()) os.chdir(curdir) # display information about how much of the segmentation has been corrected # remove temporary files if remove_temp_files: # sct.printv("\nRemove temporary files...", verbose) sct.rmtree(path_tmp)
def register(self): # accentuate separation WM/GM self.im_gm = thr_im(self.im_gm, 0.01, self.param.thr) self.im_wm = thr_im(self.im_wm, 0.01, self.param.thr) self.im_template_gm = thr_im(self.im_template_gm, 0.01, self.param.thr) self.im_template_wm = thr_im(self.im_template_wm, 0.01, self.param.thr) ## create multilabel images: # copy GM images to keep header information im_automatic_ml = self.im_gm.copy() im_template_ml = self.im_template_gm.copy() # create multi-label segmentation with GM*200 + WM*100 (100 and 200 encoded in self.param.gap) im_automatic_ml.data = self.param.gap[1] * self.im_gm.data + self.param.gap[0] * self.im_wm.data im_template_ml.data = ( self.param.gap[1] * self.im_template_gm.data + self.param.gap[0] * self.im_template_wm.data ) # set new names fname_automatic_ml = "multilabel_automatic_seg.nii.gz" fname_template_ml = "multilabel_template_seg.nii.gz" im_automatic_ml.setFileName(fname_automatic_ml) im_template_ml.setFileName(fname_template_ml) # Create temporary folder and put files in it tmp_dir = sct.tmp_create() path_gm, file_gm, ext_gm = sct.extract_fname(fname_gm) path_warp_template2target, file_warp_template2target, ext_warp_template2target = sct.extract_fname( self.fname_warp_template2target ) convert(fname_gm, tmp_dir + file_gm + ext_gm) convert(fname_warp_template, tmp_dir + file_warp_template2target + ext_warp_template2target, squeeze_data=0) if self.fname_warp_target2template is not None: path_warp_target2template, file_warp_target2template, ext_warp_target2template = sct.extract_fname( self.fname_warp_target2template ) convert( self.fname_warp_target2template, tmp_dir + file_warp_target2template + ext_warp_target2template, squeeze_data=0, ) os.chdir(tmp_dir) # save images im_automatic_ml.save() im_template_ml.save() # apply template2image warping field if self.apply_warp_template == 1: fname_template_ml_new = sct.add_suffix(fname_template_ml, "_r") sct.run( "sct_apply_transfo -i " + fname_template_ml + " -d " + fname_automatic_ml + " -w " + file_warp_template2target + ext_warp_template2target + " -o " + fname_template_ml_new ) fname_template_ml = fname_template_ml_new nx, ny, nz, nt, px, py, pz, pt = im_automatic_ml.dim size_mask = int(22.5 / px) fname_mask = "square_mask.nii.gz" sct.run( "sct_create_mask -i " + fname_automatic_ml + " -p centerline," + fname_automatic_ml + " -f box -size " + str(size_mask) + " -o " + fname_mask ) fname_automatic_ml, xi, xf, yi, yf, zi, zf = crop_im(fname_automatic_ml, fname_mask) fname_template_ml, xi, xf, yi, yf, zi, zf = crop_im(fname_template_ml, fname_mask) # fname_automatic_ml_smooth = sct.add_suffix(fname_automatic_ml, '_smooth') # sct.run('sct_maths -i '+fname_automatic_ml+' -smooth '+str(self.param.smooth)+','+str(self.param.smooth)+',0 -o '+fname_automatic_ml_smooth) # fname_automatic_ml = fname_automatic_ml_smooth path_automatic_ml, file_automatic_ml, ext_automatic_ml = sct.extract_fname(fname_automatic_ml) path_template_ml, file_template_ml, ext_template_ml = sct.extract_fname(fname_template_ml) # Register multilabel images together cmd_reg = ( "sct_register_multimodal -i " + fname_template_ml + " -d " + fname_automatic_ml + " -param " + self.param.param_reg ) if "centermass" in self.param.param_reg: fname_template_ml_seg = sct.add_suffix(fname_template_ml, "_bin") sct.run("sct_maths -i " + fname_template_ml + " -bin 0 -o " + fname_template_ml_seg) fname_automatic_ml_seg = sct.add_suffix(fname_automatic_ml, "_bin") # sct.run('sct_maths -i '+fname_automatic_ml+' -thr 50 -o '+fname_automatic_ml_seg) sct.run("sct_maths -i " + fname_automatic_ml + " -bin 50 -o " + fname_automatic_ml_seg) cmd_reg += " -iseg " + fname_template_ml_seg + " -dseg " + fname_automatic_ml_seg sct.run(cmd_reg) fname_warp_multilabel_template2auto = "warp_" + file_template_ml + "2" + file_automatic_ml + ".nii.gz" fname_warp_multilabel_auto2template = "warp_" + file_automatic_ml + "2" + file_template_ml + ".nii.gz" self.fname_warp_template2gm = "warp_template2" + file_gm + ".nii.gz" # fname_warp_multilabel_template2auto = pad_im(fname_warp_multilabel_template2auto, nx, ny, nz, xi, xf, yi, yf, zi, zf) # fname_warp_multilabel_auto2template = pad_im(fname_warp_multilabel_auto2template, nx, ny, nz, xi, xf, yi, yf, zi, zf) sct.run( "sct_concat_transfo -w " + file_warp_template2target + ext_warp_template2target + "," + fname_warp_multilabel_template2auto + " -d " + file_gm + ext_gm + " -o " + self.fname_warp_template2gm ) if self.fname_warp_target2template is not None: path_script = os.path.dirname(__file__) path_sct = os.path.dirname(path_script) if self.template == "MNI-Poly-AMU": fname_dest = path_sct + "/data/MNI-Poly-AMU/template/MNI-Poly-AMU_T2.nii.gz" elif self.template == "PAM50": fname_dest = path_sct + "/data/PAM50/template/PAM50_t2.nii.gz" self.fname_warp_gm2template = "warp_" + file_gm + "_gm2template.nii.gz" sct.run( "sct_concat_transfo -w " + fname_warp_multilabel_auto2template + "," + file_warp_target2template + ext_warp_target2template + " -d " + fname_dest + " -o " + self.fname_warp_gm2template ) os.chdir("..") # sct.generate_output_file(tmp_dir+fname_warp_multilabel_template2auto, self.param.output_folder+'warp_template_multilabel2automatic_seg_multilabel.nii.gz') # sct.generate_output_file(tmp_dir+fname_warp_multilabel_auto2template, self.param.output_folder+'warp_automatic_seg_multilabel2template_multilabel.nii.gz') sct.generate_output_file( tmp_dir + self.fname_warp_template2gm, self.param.output_folder + self.fname_warp_template2gm ) if self.fname_warp_target2template is not None: sct.generate_output_file( tmp_dir + self.fname_warp_gm2template, self.param.output_folder + self.fname_warp_gm2template ) if self.param.qc: fname_grid_warped = visualize_warp( tmp_dir + fname_warp_multilabel_template2auto, rm_tmp=self.param.remove_tmp ) path_grid_warped, file_grid_warped, ext_grid_warped = sct.extract_fname(fname_grid_warped) sct.generate_output_file(fname_grid_warped, self.param.output_folder + file_grid_warped + ext_grid_warped) if self.param.remove_tmp: sct.run("rm -rf " + tmp_dir, error_exit="warning")
def apply(self): # Initialization fname_src = self.input_filename # source image (moving) fname_warp_list = self.warp_input # list of warping fields fname_out = self.output_filename # output fname_dest = self.fname_dest # destination image (fix) verbose = self.verbose remove_temp_files = self.remove_temp_files crop_reference = self.crop # if = 1, put 0 everywhere around warping field, if = 2, real crop interp = sct.get_interpolation('isct_antsApplyTransforms', self.interp) # Parse list of warping fields sct.printv('\nParse list of warping fields...', verbose) use_inverse = [] fname_warp_list_invert = [] # fname_warp_list = fname_warp_list.replace(' ', '') # remove spaces # fname_warp_list = fname_warp_list.split(",") # parse with comma for i in range(len(fname_warp_list)): # Check if inverse matrix is specified with '-' at the beginning of file name if fname_warp_list[i].find('-') == 0: use_inverse.append('-i ') fname_warp_list[i] = fname_warp_list[i][1:] # remove '-' else: use_inverse.append('') sct.printv( ' Transfo #' + str(i) + ': ' + use_inverse[i] + fname_warp_list[i], verbose) fname_warp_list_invert.append(use_inverse[i] + fname_warp_list[i]) # need to check if last warping field is an affine transfo isLastAffine = False path_fname, file_fname, ext_fname = sct.extract_fname( fname_warp_list_invert[-1]) if ext_fname in ['.txt', '.mat']: isLastAffine = True # check if destination file is 3d if not sct.check_if_3d(fname_dest): sct.printv('ERROR: Destination data must be 3d') # N.B. Here we take the inverse of the warp list, because sct_WarpImageMultiTransform concatenates in the reverse order fname_warp_list_invert.reverse() # Extract path, file and extension path_src, file_src, ext_src = sct.extract_fname(fname_src) path_dest, file_dest, ext_dest = sct.extract_fname(fname_dest) # Get output folder and file name if fname_out == '': path_out = '' # output in user's current directory file_out = file_src + '_reg' ext_out = ext_src fname_out = path_out + file_out + ext_out # Get dimensions of data sct.printv('\nGet dimensions of data...', verbose) from msct_image import Image nx, ny, nz, nt, px, py, pz, pt = Image(fname_src).dim # nx, ny, nz, nt, px, py, pz, pt = sct.get_dimension(fname_src) sct.printv( ' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt), verbose) # if 3d if nt == 1: # Apply transformation sct.printv('\nApply transformation...', verbose) if nz in [0, 1]: dim = '2' else: dim = '3' sct.run( 'isct_antsApplyTransforms -d ' + dim + ' -i ' + fname_src + ' -o ' + fname_out + ' -t ' + ' '.join(fname_warp_list_invert) + ' -r ' + fname_dest + interp, verbose) # if 4d, loop across the T dimension else: # create temporary folder sct.printv('\nCreate temporary folder...', verbose) path_tmp = sct.slash_at_the_end( 'tmp.' + time.strftime("%y%m%d%H%M%S"), 1) # sct.run('mkdir '+path_tmp, verbose) sct.run('mkdir ' + path_tmp, verbose) # convert to nifti into temp folder sct.printv( '\nCopying input data to tmp folder and convert to nii...', verbose) from sct_convert import convert convert(fname_src, path_tmp + 'data.nii', squeeze_data=False) sct.run('cp ' + fname_dest + ' ' + path_tmp + file_dest + ext_dest) fname_warp_list_tmp = [] for fname_warp in fname_warp_list: path_warp, file_warp, ext_warp = sct.extract_fname(fname_warp) sct.run('cp ' + fname_warp + ' ' + path_tmp + file_warp + ext_warp) fname_warp_list_tmp.append(file_warp + ext_warp) fname_warp_list_invert_tmp = fname_warp_list_tmp[::-1] os.chdir(path_tmp) # split along T dimension sct.printv('\nSplit along T dimension...', verbose) from sct_image import split_data im_dat = Image('data.nii') im_header = im_dat.hdr data_split_list = split_data(im_dat, 3) for im in data_split_list: im.save() # apply transfo sct.printv('\nApply transformation to each 3D volume...', verbose) for it in range(nt): file_data_split = 'data_T' + str(it).zfill(4) + '.nii' file_data_split_reg = 'data_reg_T' + str(it).zfill(4) + '.nii' status, output = sct.run( 'isct_antsApplyTransforms -d 3 -i ' + file_data_split + ' -o ' + file_data_split_reg + ' -t ' + ' '.join(fname_warp_list_invert_tmp) + ' -r ' + file_dest + ext_dest + interp, verbose) # Merge files back sct.printv('\nMerge file back...', verbose) from sct_image import concat_data import glob path_out, name_out, ext_out = sct.extract_fname(fname_out) # im_list = [Image(file_name) for file_name in glob.glob('data_reg_T*.nii')] # concat_data use to take a list of image in input, now takes a list of file names to open the files one by one (see issue #715) fname_list = glob.glob('data_reg_T*.nii') im_out = concat_data(fname_list, 3, im_header['pixdim']) im_out.setFileName(name_out + ext_out) im_out.save(squeeze_data=False) os.chdir('..') sct.generate_output_file(path_tmp + name_out + ext_out, fname_out) # Delete temporary folder if specified if int(remove_temp_files): sct.printv('\nRemove temporary files...', verbose) sct.run('rm -rf ' + path_tmp, verbose, error_exit='warning') # 2. crop the resulting image using dimensions from the warping field warping_field = fname_warp_list_invert[-1] # if last warping field is an affine transfo, we need to compute the space of the concatenate warping field: if isLastAffine: sct.printv( 'WARNING: the resulting image could have wrong apparent results. You should use an affine transformation as last transformation...', verbose, 'warning') elif crop_reference == 1: ImageCropper(input_file=fname_out, output_file=fname_out, ref=warping_field, background=0).crop() # sct.run('sct_crop_image -i '+fname_out+' -o '+fname_out+' -ref '+warping_field+' -b 0') elif crop_reference == 2: ImageCropper(input_file=fname_out, output_file=fname_out, ref=warping_field).crop() # sct.run('sct_crop_image -i '+fname_out+' -o '+fname_out+' -ref '+warping_field) # display elapsed time sct.printv('\nDone! To view results, type:', verbose) sct.printv('fslview ' + fname_dest + ' ' + fname_out + ' &\n', verbose, 'info')
def main(): # Initialization fname_anat = '' fname_point = '' slice_gap = param.gap remove_tmp_files = param.remove_tmp_files gaussian_kernel = param.gaussian_kernel start_time = time.time() verbose = 1 # get path of the toolbox status, path_sct = commands.getstatusoutput('echo $SCT_DIR') path_sct = sct.slash_at_the_end(path_sct, 1) # Parameters for debug mode if param.debug == 1: sct.printv('\n*** WARNING: DEBUG MODE ON ***\n\t\t\tCurrent working directory: '+os.getcwd(), 'warning') status, path_sct_testing_data = commands.getstatusoutput('echo $SCT_TESTING_DATA_DIR') fname_anat = path_sct_testing_data+'/t2/t2.nii.gz' fname_point = path_sct_testing_data+'/t2/t2_centerline_init.nii.gz' slice_gap = 5 else: # Check input param try: opts, args = getopt.getopt(sys.argv[1:],'hi:p:g:r:k:') except getopt.GetoptError as err: print str(err) usage() if not opts: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ('-i'): fname_anat = arg elif opt in ('-p'): fname_point = arg elif opt in ('-g'): slice_gap = int(arg) elif opt in ('-r'): remove_tmp_files = int(arg) elif opt in ('-k'): gaussian_kernel = int(arg) # display usage if a mandatory argument is not provided if fname_anat == '' or fname_point == '': usage() # check existence of input files sct.check_file_exist(fname_anat) sct.check_file_exist(fname_point) # extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) path_point, file_point, ext_point = sct.extract_fname(fname_point) # extract path of schedule file # TODO: include schedule file in sct # TODO: check existence of schedule file file_schedule = path_sct + param.schedule_file # Get input image orientation input_image_orientation = get_orientation(fname_anat) # Display arguments print '\nCheck input arguments...' print ' Anatomical image: '+fname_anat print ' Orientation: '+input_image_orientation print ' Point in spinal cord: '+fname_point print ' Slice gap: '+str(slice_gap) print ' Gaussian kernel: '+str(gaussian_kernel) print ' Degree of polynomial: '+str(param.deg_poly) # create temporary folder print('\nCreate temporary folder...') path_tmp = 'tmp.'+time.strftime("%y%m%d%H%M%S") sct.create_folder(path_tmp) print '\nCopy input data...' sct.run('cp '+fname_anat+ ' '+path_tmp+'/tmp.anat'+ext_anat) sct.run('cp '+fname_point+ ' '+path_tmp+'/tmp.point'+ext_point) # go to temporary folder os.chdir(path_tmp) # convert to nii convert('tmp.anat'+ext_anat, 'tmp.anat.nii') convert('tmp.point'+ext_point, 'tmp.point.nii') # Reorient input anatomical volume into RL PA IS orientation print '\nReorient input volume to RL PA IS orientation...' #sct.run(sct.fsloutput + 'fslswapdim tmp.anat RL PA IS tmp.anat_orient') set_orientation('tmp.anat.nii', 'RPI', 'tmp.anat_orient.nii') # Reorient binary point into RL PA IS orientation print '\nReorient binary point into RL PA IS orientation...' # sct.run(sct.fsloutput + 'fslswapdim tmp.point RL PA IS tmp.point_orient') set_orientation('tmp.point.nii', 'RPI', 'tmp.point_orient.nii') # Get image dimensions print '\nGet image dimensions...' nx, ny, nz, nt, px, py, pz, pt = Image('tmp.anat_orient.nii').dim print '.. matrix size: '+str(nx)+' x '+str(ny)+' x '+str(nz) print '.. voxel size: '+str(px)+'mm x '+str(py)+'mm x '+str(pz)+'mm' # Split input volume print '\nSplit input volume...' split_data('tmp.anat_orient.nii', 2, '_z') file_anat_split = ['tmp.anat_orient_z'+str(z).zfill(4) for z in range(0, nz, 1)] split_data('tmp.point_orient.nii', 2, '_z') file_point_split = ['tmp.point_orient_z'+str(z).zfill(4) for z in range(0, nz, 1)] # Extract coordinates of input point # sct.printv('\nExtract the slice corresponding to z='+str(z_init)+'...', verbose) # data_point = Image('tmp.point_orient.nii').data x_init, y_init, z_init = unravel_index(data_point.argmax(), data_point.shape) sct.printv('Coordinates of input point: ('+str(x_init)+', '+str(y_init)+', '+str(z_init)+')', verbose) # Create 2D gaussian mask sct.printv('\nCreate gaussian mask from point...', verbose) xx, yy = mgrid[:nx, :ny] mask2d = zeros((nx, ny)) radius = round(float(gaussian_kernel+1)/2) # add 1 because the radius includes the center. sigma = float(radius) mask2d = exp(-(((xx-x_init)**2)/(2*(sigma**2)) + ((yy-y_init)**2)/(2*(sigma**2)))) # Save mask to 2d file file_mask_split = ['tmp.mask_orient_z'+str(z).zfill(4) for z in range(0,nz,1)] nii_mask2d = Image('tmp.anat_orient_z0000.nii') nii_mask2d.data = mask2d nii_mask2d.setFileName(file_mask_split[z_init]+'.nii') nii_mask2d.save() # # # Get the coordinates of the input point # print '\nGet the coordinates of the input point...' # data_point = Image('tmp.point_orient.nii').data # x_init, y_init, z_init = unravel_index(data_point.argmax(), data_point.shape) # print '('+str(x_init)+', '+str(y_init)+', '+str(z_init)+')' # x_init, y_init, z_init = (data > 0).nonzero() # x_init = x_init[0] # y_init = y_init[0] # z_init = z_init[0] # print '('+str(x_init)+', '+str(y_init)+', '+str(z_init)+')' # # numpy.unravel_index(a.argmax(), a.shape) # # file = nibabel.load('tmp.point_orient.nii') # data = file.get_data() # x_init, y_init, z_init = (data > 0).nonzero() # x_init = x_init[0] # y_init = y_init[0] # z_init = z_init[0] # print '('+str(x_init)+', '+str(y_init)+', '+str(z_init)+')' # # # Extract the slice corresponding to z=z_init # print '\nExtract the slice corresponding to z='+str(z_init)+'...' # file_point_split = ['tmp.point_orient_z'+str(z).zfill(4) for z in range(0,nz,1)] # nii = Image('tmp.point_orient.nii') # data_crop = nii.data[:, :, z_init:z_init+1] # nii.data = data_crop # nii.setFileName(file_point_split[z_init]+'.nii') # nii.save() # # # Create gaussian mask from point # print '\nCreate gaussian mask from point...' # file_mask_split = ['tmp.mask_orient_z'+str(z).zfill(4) for z in range(0,nz,1)] # sct.run(sct.fsloutput+'fslmaths '+file_point_split[z_init]+' -s '+str(gaussian_kernel)+' '+file_mask_split[z_init]) # # # Obtain max value from mask # print '\nFind maximum value from mask...' # file = nibabel.load(file_mask_split[z_init]+'.nii') # data = file.get_data() # max_value_mask = numpy.max(data) # print '..'+str(max_value_mask) # # # Normalize mask beween 0 and 1 # print '\nNormalize mask beween 0 and 1...' # sct.run(sct.fsloutput+'fslmaths '+file_mask_split[z_init]+' -div '+str(max_value_mask)+' '+file_mask_split[z_init]) ## Take the square of the mask #print '\nCalculate the square of the mask...' #sct.run(sct.fsloutput+'fslmaths '+file_mask_split[z_init]+' -mul '+file_mask_split[z_init]+' '+file_mask_split[z_init]) # initialize variables file_mat = ['tmp.mat_z'+str(z).zfill(4) for z in range(0,nz,1)] file_mat_inv = ['tmp.mat_inv_z'+str(z).zfill(4) for z in range(0,nz,1)] file_mat_inv_cumul = ['tmp.mat_inv_cumul_z'+str(z).zfill(4) for z in range(0,nz,1)] # create identity matrix for initial transformation matrix fid = open(file_mat_inv_cumul[z_init], 'w') fid.write('%i %i %i %i\n' %(1, 0, 0, 0) ) fid.write('%i %i %i %i\n' %(0, 1, 0, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 1, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 0, 1) ) fid.close() # initialize centerline: give value corresponding to initial point x_centerline = [x_init] y_centerline = [y_init] z_centerline = [z_init] warning_count = 0 # go up (1), then down (2) in reference to the binary point for iUpDown in range(1, 3): if iUpDown == 1: # z increases slice_gap_signed = slice_gap elif iUpDown == 2: # z decreases slice_gap_signed = -slice_gap # reverse centerline (because values will be appended at the end) x_centerline.reverse() y_centerline.reverse() z_centerline.reverse() # initialization before looping z_dest = z_init # point given by user z_src = z_dest + slice_gap_signed # continue looping if 0 < z < nz while 0 <= z_src and z_src <= nz-1: # print current z: print 'z='+str(z_src)+':' # estimate transformation sct.run(fsloutput+'flirt -in '+file_anat_split[z_src]+' -ref '+file_anat_split[z_dest]+' -schedule '+file_schedule+ ' -verbose 0 -omat '+file_mat[z_src]+' -cost normcorr -forcescaling -inweight '+file_mask_split[z_dest]+' -refweight '+file_mask_split[z_dest]) # display transfo status, output = sct.run('cat '+file_mat[z_src]) print output # check if transformation is bigger than 1.5x slice_gap tx = float(output.split()[3]) ty = float(output.split()[7]) norm_txy = linalg.norm([tx, ty],ord=2) if norm_txy > 1.5*slice_gap: print 'WARNING: Transformation is too large --> using previous one.' warning_count = warning_count + 1 # if previous transformation exists, replace current one with previous one if os.path.isfile(file_mat[z_dest]): sct.run('cp '+file_mat[z_dest]+' '+file_mat[z_src]) # estimate inverse transformation matrix sct.run('convert_xfm -omat '+file_mat_inv[z_src]+' -inverse '+file_mat[z_src]) # compute cumulative transformation sct.run('convert_xfm -omat '+file_mat_inv_cumul[z_src]+' -concat '+file_mat_inv[z_src]+' '+file_mat_inv_cumul[z_dest]) # apply inverse cumulative transformation to initial gaussian mask (to put it in src space) sct.run(fsloutput+'flirt -in '+file_mask_split[z_init]+' -ref '+file_mask_split[z_init]+' -applyxfm -init '+file_mat_inv_cumul[z_src]+' -out '+file_mask_split[z_src]) # open inverse cumulative transformation file and generate centerline fid = open(file_mat_inv_cumul[z_src]) mat = fid.read().split() x_centerline.append(x_init + float(mat[3])) y_centerline.append(y_init + float(mat[7])) z_centerline.append(z_src) #z_index = z_index+1 # define new z_dest (target slice) and new z_src (moving slice) z_dest = z_dest + slice_gap_signed z_src = z_src + slice_gap_signed # Reconstruct centerline # ==================================================================================================== # reverse back centerline (because it's been reversed once, so now all values are in the right order) x_centerline.reverse() y_centerline.reverse() z_centerline.reverse() # fit centerline in the Z-X plane using polynomial function print '\nFit centerline in the Z-X plane using polynomial function...' coeffsx = polyfit(z_centerline, x_centerline, deg=param.deg_poly) polyx = poly1d(coeffsx) x_centerline_fit = polyval(polyx, z_centerline) # calculate RMSE rmse = linalg.norm(x_centerline_fit-x_centerline)/sqrt( len(x_centerline) ) # calculate max absolute error max_abs = max( abs(x_centerline_fit-x_centerline) ) print '.. RMSE (in mm): '+str(rmse*px) print '.. Maximum absolute error (in mm): '+str(max_abs*px) # fit centerline in the Z-Y plane using polynomial function print '\nFit centerline in the Z-Y plane using polynomial function...' coeffsy = polyfit(z_centerline, y_centerline, deg=param.deg_poly) polyy = poly1d(coeffsy) y_centerline_fit = polyval(polyy, z_centerline) # calculate RMSE rmse = linalg.norm(y_centerline_fit-y_centerline)/sqrt( len(y_centerline) ) # calculate max absolute error max_abs = max( abs(y_centerline_fit-y_centerline) ) print '.. RMSE (in mm): '+str(rmse*py) print '.. Maximum absolute error (in mm): '+str(max_abs*py) # display if param.debug == 1: import matplotlib.pyplot as plt plt.figure() plt.plot(z_centerline,x_centerline,'.',z_centerline,x_centerline_fit,'r') plt.legend(['Data','Polynomial Fit']) plt.title('Z-X plane polynomial interpolation') plt.show() plt.figure() plt.plot(z_centerline,y_centerline,'.',z_centerline,y_centerline_fit,'r') plt.legend(['Data','Polynomial Fit']) plt.title('Z-Y plane polynomial interpolation') plt.show() # generate full range z-values for centerline z_centerline_full = [iz for iz in range(0, nz, 1)] # calculate X and Y values for the full centerline x_centerline_fit_full = polyval(polyx, z_centerline_full) y_centerline_fit_full = polyval(polyy, z_centerline_full) # Generate fitted transformation matrices and write centerline coordinates in text file print '\nGenerate fitted transformation matrices and write centerline coordinates in text file...' file_mat_inv_cumul_fit = ['tmp.mat_inv_cumul_fit_z'+str(z).zfill(4) for z in range(0,nz,1)] file_mat_cumul_fit = ['tmp.mat_cumul_fit_z'+str(z).zfill(4) for z in range(0,nz,1)] fid_centerline = open('tmp.centerline_coordinates.txt', 'w') for iz in range(0, nz, 1): # compute inverse cumulative fitted transformation matrix fid = open(file_mat_inv_cumul_fit[iz], 'w') fid.write('%i %i %i %f\n' %(1, 0, 0, x_centerline_fit_full[iz]-x_init) ) fid.write('%i %i %i %f\n' %(0, 1, 0, y_centerline_fit_full[iz]-y_init) ) fid.write('%i %i %i %i\n' %(0, 0, 1, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 0, 1) ) fid.close() # compute forward cumulative fitted transformation matrix sct.run('convert_xfm -omat '+file_mat_cumul_fit[iz]+' -inverse '+file_mat_inv_cumul_fit[iz]) # write centerline coordinates in x, y, z format fid_centerline.write('%f %f %f\n' %(x_centerline_fit_full[iz], y_centerline_fit_full[iz], z_centerline_full[iz]) ) fid_centerline.close() # Prepare output data # ==================================================================================================== # write centerline as text file for iz in range(0, nz, 1): # compute inverse cumulative fitted transformation matrix fid = open(file_mat_inv_cumul_fit[iz], 'w') fid.write('%i %i %i %f\n' %(1, 0, 0, x_centerline_fit_full[iz]-x_init) ) fid.write('%i %i %i %f\n' %(0, 1, 0, y_centerline_fit_full[iz]-y_init) ) fid.write('%i %i %i %i\n' %(0, 0, 1, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 0, 1) ) fid.close() # write polynomial coefficients savetxt('tmp.centerline_polycoeffs_x.txt',coeffsx) savetxt('tmp.centerline_polycoeffs_y.txt',coeffsy) # apply transformations to data print '\nApply fitted transformation matrices...' file_anat_split_fit = ['tmp.anat_orient_fit_z'+str(z).zfill(4) for z in range(0,nz,1)] file_mask_split_fit = ['tmp.mask_orient_fit_z'+str(z).zfill(4) for z in range(0,nz,1)] file_point_split_fit = ['tmp.point_orient_fit_z'+str(z).zfill(4) for z in range(0,nz,1)] for iz in range(0, nz, 1): # forward cumulative transformation to data sct.run(fsloutput+'flirt -in '+file_anat_split[iz]+' -ref '+file_anat_split[iz]+' -applyxfm -init '+file_mat_cumul_fit[iz]+' -out '+file_anat_split_fit[iz]) # inverse cumulative transformation to mask sct.run(fsloutput+'flirt -in '+file_mask_split[z_init]+' -ref '+file_mask_split[z_init]+' -applyxfm -init '+file_mat_inv_cumul_fit[iz]+' -out '+file_mask_split_fit[iz]) # inverse cumulative transformation to point sct.run(fsloutput+'flirt -in '+file_point_split[z_init]+' -ref '+file_point_split[z_init]+' -applyxfm -init '+file_mat_inv_cumul_fit[iz]+' -out '+file_point_split_fit[iz]+' -interp nearestneighbour') # Merge into 4D volume print '\nMerge into 4D volume...' # sct.run(fsloutput+'fslmerge -z tmp.anat_orient_fit tmp.anat_orient_fit_z*') # sct.run(fsloutput+'fslmerge -z tmp.mask_orient_fit tmp.mask_orient_fit_z*') # sct.run(fsloutput+'fslmerge -z tmp.point_orient_fit tmp.point_orient_fit_z*') concat_data(glob.glob('tmp.anat_orient_fit_z*.nii'), 'tmp.anat_orient_fit.nii', dim=2) concat_data(glob.glob('tmp.mask_orient_fit_z*.nii'), 'tmp.mask_orient_fit.nii', dim=2) concat_data(glob.glob('tmp.point_orient_fit_z*.nii'), 'tmp.point_orient_fit.nii', dim=2) # Copy header geometry from input data print '\nCopy header geometry from input data...' copy_header('tmp.anat_orient.nii', 'tmp.anat_orient_fit.nii') copy_header('tmp.anat_orient.nii', 'tmp.mask_orient_fit.nii') copy_header('tmp.anat_orient.nii', 'tmp.point_orient_fit.nii') # Reorient outputs into the initial orientation of the input image print '\nReorient the centerline into the initial orientation of the input image...' set_orientation('tmp.point_orient_fit.nii', input_image_orientation, 'tmp.point_orient_fit.nii') set_orientation('tmp.mask_orient_fit.nii', input_image_orientation, 'tmp.mask_orient_fit.nii') # Generate output file (in current folder) print '\nGenerate output file (in current folder)...' os.chdir('..') # come back to parent folder #sct.generate_output_file('tmp.centerline_polycoeffs_x.txt','./','centerline_polycoeffs_x','.txt') #sct.generate_output_file('tmp.centerline_polycoeffs_y.txt','./','centerline_polycoeffs_y','.txt') #sct.generate_output_file('tmp.centerline_coordinates.txt','./','centerline_coordinates','.txt') #sct.generate_output_file('tmp.anat_orient.nii','./',file_anat+'_rpi',ext_anat) #sct.generate_output_file('tmp.anat_orient_fit.nii', file_anat+'_rpi_align'+ext_anat) #sct.generate_output_file('tmp.mask_orient_fit.nii', file_anat+'_mask'+ext_anat) fname_output_centerline = sct.generate_output_file(path_tmp+'/tmp.point_orient_fit.nii', file_anat+'_centerline'+ext_anat) # Delete temporary files if remove_tmp_files == 1: print '\nRemove temporary files...' sct.run('rm -rf '+path_tmp) # print number of warnings print '\nNumber of warnings: '+str(warning_count)+' (if >10, you should probably reduce the gap and/or increase the kernel size' # display elapsed time elapsed_time = time.time() - start_time print '\nFinished! \n\tGenerated file: '+fname_output_centerline+'\n\tElapsed time: '+str(int(round(elapsed_time)))+'s\n'
def main(): # initialization start_time = time.time() path_out = '.' param_user = '' # reducing the number of CPU used for moco (see issue #201) os.environ["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = "1" # get path of the toolbox status, param.path_sct = commands.getstatusoutput('echo $SCT_DIR') # Parameters for debug mode if param.debug: # get path of the testing data status, path_sct_data = commands.getstatusoutput('echo $SCT_TESTING_DATA_DIR') param.fname_data = path_sct_data+'/dmri/dmri.nii.gz' param.fname_bvecs = path_sct_data+'/dmri/bvecs.txt' param.fname_mask = path_sct_data+'/dmri/dmri.nii.gz' param.remove_tmp_files = 0 param.verbose = 1 param.run_eddy = 0 param.otsu = 0 param.group_size = 5 param.iterative_averaging = 1 else: parser = get_parser() arguments = parser.parse(sys.argv[1:]) param.fname_data = arguments['-i'] param.fname_bvecs = arguments['-bvec'] if '-bval' in arguments: param.fname_bvals = arguments['-bval'] if '-g' in arguments: param.group_size = arguments['-g'] if 'm' in arguments: param.fname_mask = arguments['-m'] if '-param' in arguments: param.param = arguments['-param'] if '-thr' in arguments: param.otsu = arguments['-thr'] if '-x' in arguments: param.interp = arguments['-x'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-r' in arguments: param.remove_tmp_files = int(arguments['-r']) if '-v' in arguments: param.verbose = int(arguments['-v']) ''' # Some old options that wasn't in the doc ... elif opt in ('-e'): param.run_eddy = int(arg) elif opt in ('-f'): param.spline_fitting = int(arg) ''' # Get full path param.fname_data = os.path.abspath(param.fname_data) param.fname_bvecs = os.path.abspath(param.fname_bvecs) if param.fname_bvals != '': param.fname_bvals = os.path.abspath(param.fname_bvals) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) path_mask, file_mask, ext_mask = sct.extract_fname(param.fname_mask) # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+path_tmp, param.verbose) # names of files in temporary folder ext = '.nii' dmri_name = 'dmri' mask_name = 'mask' bvecs_fname = 'bvecs.txt' # Copying input data to tmp folder sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) sct.run('cp '+param.fname_data+' '+path_tmp+dmri_name+ext_data, param.verbose) sct.run('cp '+param.fname_bvecs+' '+path_tmp+bvecs_fname, param.verbose) if param.fname_mask != '': sct.run('cp '+param.fname_mask+' '+path_tmp+mask_name+ext_mask, param.verbose) # go to tmp folder os.chdir(path_tmp) # convert dmri to nii format convert(dmri_name+ext_data, dmri_name+ext) # update field in param (because used later). # TODO: make this cleaner... if param.fname_mask != '': param.fname_mask = mask_name+ext_mask # run moco dmri_moco(param) # come back to parent folder os.chdir('..') # Generate output files path_out = sct.slash_at_the_end(path_out, 1) sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(path_tmp+dmri_name+param.suffix+ext, path_out+file_data+param.suffix+ext_data, param.verbose) sct.generate_output_file(path_tmp+'b0_mean.nii', path_out+'b0'+param.suffix+'_mean'+ext_data, param.verbose) sct.generate_output_file(path_tmp+'dwi_mean.nii', path_out+'dwi'+param.suffix+'_mean'+ext_data, param.verbose) # Delete temporary files if param.remove_tmp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.run('rm -rf '+path_tmp, param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: '+str(int(round(elapsed_time)))+'s', param.verbose) #To view results sct.printv('\nTo view results, type:', param.verbose) sct.printv('fslview -m ortho,ortho '+param.path_out+file_data+param.suffix+' '+file_data+' &\n', param.verbose, 'info')
def main(args=None): import numpy as np import spinalcordtoolbox.image as msct_image # Initialization fname_mt0 = '' fname_mt1 = '' file_out = param.file_out # register = param.register # remove_temp_files = param.remove_temp_files # verbose = param.verbose # check user arguments if not args: args = sys.argv[1:] # Check input parameters parser = get_parser() arguments = parser.parse(args) fname_mt0 = arguments['-mt0'] fname_mt1 = arguments['-mt1'] remove_temp_files = int(arguments['-r']) verbose = int(arguments['-v']) # Extract path/file/extension path_mt0, file_mt0, ext_mt0 = sct.extract_fname(fname_mt0) path_out, file_out, ext_out = '', file_out, ext_mt0 # create temporary folder path_tmp = sct.tmp_create() # Copying input data to tmp folder and convert to nii sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) from sct_convert import convert convert(fname_mt0, os.path.join(path_tmp, "mt0.nii"), dtype=np.float32) convert(fname_mt1, os.path.join(path_tmp, "mt1.nii"), dtype=np.float32) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # compute MTR sct.printv('\nCompute MTR...', verbose) nii_mt1 = msct_image.Image('mt1.nii') data_mt1 = nii_mt1.data data_mt0 = msct_image.Image('mt0.nii').data data_mtr = 100 * (data_mt0 - data_mt1) / data_mt0 # save MTR file nii_mtr = nii_mt1 nii_mtr.data = data_mtr nii_mtr.save("mtr.nii") # sct.run(fsloutput+'fslmaths -dt double mt0.nii -sub mt1.nii -mul 100 -div mt0.nii -thr 0 -uthr 100 mtr.nii', verbose) # come back os.chdir(curdir) # Generate output files sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(os.path.join(path_tmp, "mtr.nii"), os.path.join(path_out, file_out + ext_out)) # Remove temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...') sct.rmtree(path_tmp) sct.display_viewer_syntax([fname_mt0, fname_mt1, file_out])
def moco(param): # retrieve parameters file_data = param.file_data file_target = param.file_target folder_mat = param.mat_moco # output folder of mat file todo = param.todo suffix = param.suffix verbose = param.verbose # other parameters file_mask = 'mask.nii' sct.printv('\nInput parameters:', param.verbose) sct.printv(' Input file ............' + file_data, param.verbose) sct.printv(' Reference file ........' + file_target, param.verbose) sct.printv(' Polynomial degree .....' + param.poly, param.verbose) sct.printv(' Smoothing kernel ......' + param.smooth, param.verbose) sct.printv(' Gradient step .........' + param.gradStep, param.verbose) sct.printv(' Metric ................' + param.metric, param.verbose) sct.printv(' Sampling ..............' + param.sampling, param.verbose) sct.printv(' Todo ..................' + todo, param.verbose) sct.printv(' Mask .................' + param.fname_mask, param.verbose) sct.printv(' Output mat folder .....' + folder_mat, param.verbose) # create folder for mat files sct.create_folder(folder_mat) # Get size of data sct.printv('\nData dimensions:', verbose) im_data = Image(param.file_data) nx, ny, nz, nt, px, py, pz, pt = im_data.dim sct.printv((' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt)), verbose) # copy file_target to a temporary file sct.printv('\nCopy file_target to a temporary file...', verbose) file_target = "target.nii.gz" convert(param.file_target, file_target) # If scan is sagittal, split src and target along Z (slice) if param.is_sagittal: dim_sag = 2 # TODO: find it # z-split data (time series) im_z_list = split_data(im_data, dim=dim_sag, squeeze_data=False) file_data_splitZ = [] for im_z in im_z_list: im_z.save() file_data_splitZ.append(im_z.absolutepath) # z-split target im_targetz_list = split_data(Image(file_target), dim=dim_sag, squeeze_data=False) file_target_splitZ = [] for im_targetz in im_targetz_list: im_targetz.save() file_target_splitZ.append(im_targetz.absolutepath) # z-split mask (if exists) if not param.fname_mask == '': im_maskz_list = split_data(Image(file_mask), dim=dim_sag, squeeze_data=False) file_mask_splitZ = [] for im_maskz in im_maskz_list: im_maskz.save() file_mask_splitZ.append(im_maskz.absolutepath) # initialize file list for output matrices file_mat = np.empty((nz, nt), dtype=object) # axial orientation else: file_data_splitZ = [file_data] # TODO: make it absolute like above file_target_splitZ = [file_target] # TODO: make it absolute like above # initialize file list for output matrices file_mat = np.empty((1, nt), dtype=object) # deal with mask if not param.fname_mask == '': convert(param.fname_mask, file_mask, squeeze_data=False) im_maskz_list = [Image(file_mask)] # use a list with single element # Loop across file list, where each file is either a 2D volume (if sagittal) or a 3D volume (otherwise) # file_mat = tuple([[[] for i in range(nt)] for i in range(nz)]) file_data_splitZ_moco = [] sct.printv('\nRegister. Loop across Z (note: there is only one Z if orientation is axial') for file in file_data_splitZ: iz = file_data_splitZ.index(file) # Split data along T dimension # sct.printv('\nSplit data along T dimension.', verbose) im_z = Image(file) list_im_zt = split_data(im_z, dim=3) file_data_splitZ_splitT = [] for im_zt in list_im_zt: im_zt.save(verbose=0) file_data_splitZ_splitT.append(im_zt.absolutepath) # file_data_splitT = file_data + '_T' # Motion correction: initialization index = np.arange(nt) file_data_splitT_num = [] file_data_splitZ_splitT_moco = [] failed_transfo = [0 for i in range(nt)] # Motion correction: Loop across T for indice_index in tqdm(range(nt), unit='iter', unit_scale=False, desc="Z=" + str(iz) + "/" + str(len(file_data_splitZ)-1), ascii=True, ncols=80): # create indices and display stuff it = index[indice_index] file_mat[iz][it] = os.path.join(folder_mat, "mat.Z") + str(iz).zfill(4) + 'T' + str(it).zfill(4) file_data_splitZ_splitT_moco.append(sct.add_suffix(file_data_splitZ_splitT[it], '_moco')) # deal with masking if not param.fname_mask == '': input_mask = im_maskz_list[iz] else: input_mask = None # run 3D registration failed_transfo[it] = register(param, file_data_splitZ_splitT[it], file_target_splitZ[iz], file_mat[iz][it], file_data_splitZ_splitT_moco[it], im_mask=input_mask) # average registered volume with target image # N.B. use weighted averaging: (target * nb_it + moco) / (nb_it + 1) if param.iterAvg and indice_index < 10 and failed_transfo[it] == 0 and not param.todo == 'apply': im_targetz = Image(file_target_splitZ[iz]) data_targetz = im_targetz.data data_mocoz = Image(file_data_splitZ_splitT_moco[it]).data data_targetz = (data_targetz * (indice_index + 1) + data_mocoz) / (indice_index + 2) im_targetz.data = data_targetz im_targetz.save(verbose=0) # Replace failed transformation with the closest good one fT = [i for i, j in enumerate(failed_transfo) if j == 1] gT = [i for i, j in enumerate(failed_transfo) if j == 0] for it in range(len(fT)): abs_dist = [np.abs(gT[i] - fT[it]) for i in range(len(gT))] if not abs_dist == []: index_good = abs_dist.index(min(abs_dist)) sct.printv(' transfo #' + str(fT[it]) + ' --> use transfo #' + str(gT[index_good]), verbose) # copy transformation sct.copy(file_mat[iz][gT[index_good]] + 'Warp.nii.gz', file_mat[iz][fT[it]] + 'Warp.nii.gz') # apply transformation sct_apply_transfo.main(args=['-i', file_data_splitZ_splitT[fT[it]], '-d', file_target, '-w', file_mat[iz][fT[it]] + 'Warp.nii.gz', '-o', file_data_splitZ_splitT_moco[fT[it]], '-x', param.interp]) else: # exit program if no transformation exists. sct.printv('\nERROR in ' + os.path.basename(__file__) + ': No good transformation exist. Exit program.\n', verbose, 'error') sys.exit(2) # Merge data along T file_data_splitZ_moco.append(sct.add_suffix(file, suffix)) if todo != 'estimate': im_out = concat_data(file_data_splitZ_splitT_moco, 3) im_out.save(file_data_splitZ_moco[iz]) # If sagittal, merge along Z if param.is_sagittal: im_out = concat_data(file_data_splitZ_moco, 2) dirname, basename, ext = sct.extract_fname(file_data) path_out = os.path.join(dirname, basename + suffix + ext) im_out.save(path_out) return file_mat
def register(self): # accentuate separation WM/GM self.im_gm = thr_im(self.im_gm, 0.01, self.param.thr) self.im_wm = thr_im(self.im_wm, 0.01, self.param.thr) self.im_template_gm = thr_im(self.im_template_gm, 0.01, self.param.thr) self.im_template_wm = thr_im(self.im_template_wm, 0.01, self.param.thr) # create multilabel images: # copy GM images to keep header information im_automatic_ml = self.im_gm.copy() im_template_ml = self.im_template_gm.copy() # create multi-label segmentation with GM*200 + WM*100 (100 and 200 encoded in self.param.gap) im_automatic_ml.data = self.param.gap[ 1] * self.im_gm.data + self.param.gap[0] * self.im_wm.data im_template_ml.data = self.param.gap[ 1] * self.im_template_gm.data + self.param.gap[ 0] * self.im_template_wm.data # set new names fname_automatic_ml = 'multilabel_automatic_seg.nii.gz' fname_template_ml = 'multilabel_template_seg.nii.gz' im_automatic_ml.setFileName(fname_automatic_ml) im_template_ml.setFileName(fname_template_ml) # Create temporary folder and put files in it tmp_dir = sct.tmp_create() path_gm, file_gm, ext_gm = sct.extract_fname(fname_gm) path_warp_template2target, file_warp_template2target, ext_warp_template2target = sct.extract_fname( self.fname_warp_template2target) convert(fname_gm, tmp_dir + file_gm + ext_gm) convert(fname_warp_template, tmp_dir + file_warp_template2target + ext_warp_template2target, squeeze_data=0) if self.fname_warp_target2template is not None: path_warp_target2template, file_warp_target2template, ext_warp_target2template = sct.extract_fname( self.fname_warp_target2template) convert(self.fname_warp_target2template, tmp_dir + file_warp_target2template + ext_warp_target2template, squeeze_data=0) os.chdir(tmp_dir) # save images im_automatic_ml.save() im_template_ml.save() # apply template2image warping field if self.apply_warp_template == 1: fname_template_ml_new = sct.add_suffix(fname_template_ml, '_r') sct.run('sct_apply_transfo -i ' + fname_template_ml + ' -d ' + fname_automatic_ml + ' -w ' + file_warp_template2target + ext_warp_template2target + ' -o ' + fname_template_ml_new) fname_template_ml = fname_template_ml_new nx, ny, nz, nt, px, py, pz, pt = im_automatic_ml.dim size_mask = int(22.5 / px) fname_mask = 'square_mask.nii.gz' sct.run('sct_create_mask -i ' + fname_automatic_ml + ' -p centerline,' + fname_automatic_ml + ' -f box -size ' + str(size_mask) + ' -o ' + fname_mask) fname_automatic_ml, xi, xf, yi, yf, zi, zf = crop_im( fname_automatic_ml, fname_mask) fname_template_ml, xi, xf, yi, yf, zi, zf = crop_im( fname_template_ml, fname_mask) # fname_automatic_ml_smooth = sct.add_suffix(fname_automatic_ml, '_smooth') # sct.run('sct_maths -i '+fname_automatic_ml+' -smooth '+str(self.param.smooth)+','+str(self.param.smooth)+',0 -o '+fname_automatic_ml_smooth) # fname_automatic_ml = fname_automatic_ml_smooth path_automatic_ml, file_automatic_ml, ext_automatic_ml = sct.extract_fname( fname_automatic_ml) path_template_ml, file_template_ml, ext_template_ml = sct.extract_fname( fname_template_ml) # Register multilabel images together cmd_reg = 'sct_register_multimodal -i ' + fname_template_ml + ' -d ' + fname_automatic_ml + ' -param ' + self.param.param_reg if 'centermass' in self.param.param_reg: fname_template_ml_seg = sct.add_suffix(fname_template_ml, '_bin') sct.run('sct_maths -i ' + fname_template_ml + ' -bin 0 -o ' + fname_template_ml_seg) fname_automatic_ml_seg = sct.add_suffix(fname_automatic_ml, '_bin') # sct.run('sct_maths -i '+fname_automatic_ml+' -thr 50 -o '+fname_automatic_ml_seg) sct.run('sct_maths -i ' + fname_automatic_ml + ' -bin 50 -o ' + fname_automatic_ml_seg) cmd_reg += ' -iseg ' + fname_template_ml_seg + ' -dseg ' + fname_automatic_ml_seg sct.run(cmd_reg) fname_warp_multilabel_template2auto = 'warp_' + file_template_ml + '2' + file_automatic_ml + '.nii.gz' fname_warp_multilabel_auto2template = 'warp_' + file_automatic_ml + '2' + file_template_ml + '.nii.gz' self.fname_warp_template2gm = sct.extract_fname( self.fname_warp_template2target )[1] + '_reg_gm' + sct.extract_fname( self.fname_warp_template2target)[2] # fname_warp_multilabel_template2auto = pad_im(fname_warp_multilabel_template2auto, nx, ny, nz, xi, xf, yi, yf, zi, zf) # fname_warp_multilabel_auto2template = pad_im(fname_warp_multilabel_auto2template, nx, ny, nz, xi, xf, yi, yf, zi, zf) sct.run('sct_concat_transfo -w ' + file_warp_template2target + ext_warp_template2target + ',' + fname_warp_multilabel_template2auto + ' -d ' + file_gm + ext_gm + ' -o ' + self.fname_warp_template2gm) if self.fname_warp_target2template is not None: if self.fname_template_dest is None: path_script = os.path.dirname(__file__) path_sct = os.path.dirname(path_script) if self.template == 'MNI-Poly-AMU': self.fname_template_dest = path_sct + '/data/MNI-Poly-AMU/template/MNI-Poly-AMU_T2.nii.gz' elif self.template == 'PAM50': self.fname_template_dest = path_sct + '/data/PAM50/template/PAM50_t2.nii.gz' self.fname_warp_gm2template = sct.extract_fname( self.fname_warp_target2template )[1] + '_reg_gm' + sct.extract_fname( self.fname_warp_target2template)[2] sct.run('sct_concat_transfo -w ' + fname_warp_multilabel_auto2template + ',' + file_warp_target2template + ext_warp_target2template + ' -d ' + self.fname_template_dest + ' -o ' + self.fname_warp_gm2template) os.chdir('..') # sct.generate_output_file(tmp_dir+fname_warp_multilabel_template2auto, self.param.output_folder+'warp_template_multilabel2automatic_seg_multilabel.nii.gz') # sct.generate_output_file(tmp_dir+fname_warp_multilabel_auto2template, self.param.output_folder+'warp_automatic_seg_multilabel2template_multilabel.nii.gz') sct.generate_output_file( tmp_dir + self.fname_warp_template2gm, self.param.output_folder + self.fname_warp_template2gm) if self.fname_warp_target2template is not None: sct.generate_output_file( tmp_dir + self.fname_warp_gm2template, self.param.output_folder + self.fname_warp_gm2template) if self.param.qc: fname_grid_warped = visualize_warp( tmp_dir + fname_warp_multilabel_template2auto, rm_tmp=self.param.remove_tmp) path_grid_warped, file_grid_warped, ext_grid_warped = sct.extract_fname( fname_grid_warped) sct.generate_output_file( fname_grid_warped, self.param.output_folder + file_grid_warped + ext_grid_warped) if self.param.remove_tmp: sct.run('rm -rf ' + tmp_dir, error_exit='warning')
def main(path_out, param_user): # initialization start_time = time.time() # reducing the number of CPU used for moco (see issue #201) os.environ["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = "1" # get path of the toolbox status, path_sct = commands.getstatusoutput('echo $SCT_DIR') # Parameters for debug mode if param.debug: # get path of the testing data status, path_sct_data = commands.getstatusoutput('echo $SCT_TESTING_DATA_DIR') param.fname_data = path_sct_data+'/fmri/fmri.nii.gz' #param.fname_mask = path_sct_data+'/fmri/fmri.nii.gz' param.verbose = 1 param.group_size = 3 #param_user = '******' sct.printv('\nInput parameters:', param.verbose) sct.printv(' input file ............'+param.fname_data, param.verbose) # Get full path param.fname_data = os.path.abspath(param.fname_data) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+path_tmp, param.verbose) # Copying input data to tmp folder and convert to nii sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, path_tmp+'fmri.nii') # sct.run('cp '+param.fname_data+' '+path_tmp+'fmri'+ext_data, param.verbose) # # go to tmp folder os.chdir(path_tmp) # # # convert fmri to nii format # convert('fmri'+ext_data, 'fmri.nii') # run moco fmri_moco(param) # come back to parent folder os.chdir('..') # Generate output files path_out = sct.slash_at_the_end(path_out, 1) sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) if os.path.isfile(path_tmp+'fmri'+param.suffix+'.nii'): print path_tmp+'fmri'+param.suffix+'.nii' print path_out+file_data+param.suffix+ext_data sct.generate_output_file(path_tmp+'fmri'+param.suffix+'.nii', path_out+file_data+param.suffix+ext_data, param.verbose) sct.generate_output_file(path_tmp+'fmri'+param.suffix+'_mean.nii', path_out+file_data+param.suffix+'_mean'+ext_data, param.verbose) # Delete temporary files if param.remove_tmp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.run('rm -rf '+path_tmp, param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: '+str(int(round(elapsed_time)))+'s', param.verbose) #To view results sct.printv('\nTo view results, type:', param.verbose) sct.printv('fslview -m ortho,ortho '+param.path_out+file_data+param.suffix+' '+file_data+' &\n', param.verbose, 'info')
def main(): # Initialization fname_data = '' interp_factor = param.interp_factor remove_temp_files = param.remove_temp_files verbose = param.verbose suffix = param.suffix smoothing_sigma = param.smoothing_sigma # start timer start_time = time.time() # get path of the toolbox path_sct = os.environ.get("SCT_DIR", os.path.dirname(os.path.dirname(__file__))) # Parameters for debug mode if param.debug: fname_data = os.path.join(path_sct, 'testing', 'data', 'errsm_23', 't2', 't2_manual_segmentation.nii.gz') remove_temp_files = 0 param.mask_size = 10 else: # Check input parameters try: opts, args = getopt.getopt(sys.argv[1:], 'hi:v:r:s:') except getopt.GetoptError: usage() if not opts: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ('-i'): fname_data = arg elif opt in ('-r'): remove_temp_files = int(arg) elif opt in ('-s'): smoothing_sigma = arg elif opt in ('-v'): verbose = int(arg) # display usage if a mandatory argument is not provided if fname_data == '': usage() # sct.printv(arguments) sct.printv('\nCheck parameters:') sct.printv(' segmentation ........... ' + fname_data) sct.printv(' interp factor .......... ' + str(interp_factor)) sct.printv(' smoothing sigma ........ ' + str(smoothing_sigma)) # check existence of input files sct.printv('\nCheck existence of input files...') sct.check_file_exist(fname_data, verbose) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(fname_data) path_tmp = sct.tmp_create(basename="binary_to_trilinear", verbose=verbose) from sct_convert import convert sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(fname_data, os.path.join(path_tmp, "data.nii")) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # Get dimensions of data sct.printv('\nGet dimensions of data...', verbose) nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim sct.printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), verbose) # upsample data sct.printv('\nUpsample data...', verbose) sct.run([ "sct_resample", "-i", "data.nii", "-x", "linear", "-vox", str(nx * interp_factor) + 'x' + str(ny * interp_factor) + 'x' + str(nz * interp_factor), "-o", "data_up.nii" ], verbose) # Smooth along centerline sct.printv('\nSmooth along centerline...', verbose) sct.run([ "sct_smooth_spinalcord", "-i", "data_up.nii", "-s", "data_up.nii", "-smooth", str(smoothing_sigma), "-r", str(remove_temp_files), "-v", str(verbose) ], verbose) # downsample data sct.printv('\nDownsample data...', verbose) sct.run([ "sct_resample", "-i", "data_up_smooth.nii", "-x", "linear", "-vox", str(nx) + 'x' + str(ny) + 'x' + str(nz), "-o", "data_up_smooth_down.nii" ], verbose) # come back os.chdir(curdir) # Generate output files sct.printv('\nGenerate output files...') fname_out = sct.generate_output_file( os.path.join(path_tmp, "data_up_smooth_down.nii"), '' + file_data + suffix + ext_data) # Delete temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...') sct.rmtree(path_tmp) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's') # to view results sct.printv('\nTo view results, type:') sct.printv('fslview ' + file_data + ' ' + file_data + suffix + ' &\n')
def get_centerline_from_point(input_image, point_file, gap=4, gaussian_kernel=4, remove_tmp_files=1): # Initialization fname_anat = input_image fname_point = point_file slice_gap = gap remove_tmp_files = remove_tmp_files gaussian_kernel = gaussian_kernel start_time = time() verbose = 1 # get path of the toolbox status, path_sct = commands.getstatusoutput("echo $SCT_DIR") path_sct = sct.slash_at_the_end(path_sct, 1) # Parameters for debug mode if param.debug == 1: sct.printv("\n*** WARNING: DEBUG MODE ON ***\n\t\t\tCurrent working directory: " + os.getcwd(), "warning") status, path_sct_testing_data = commands.getstatusoutput("echo $SCT_TESTING_DATA_DIR") fname_anat = path_sct_testing_data + "/t2/t2.nii.gz" fname_point = path_sct_testing_data + "/t2/t2_centerline_init.nii.gz" slice_gap = 5 # check existence of input files sct.check_file_exist(fname_anat) sct.check_file_exist(fname_point) # extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) path_point, file_point, ext_point = sct.extract_fname(fname_point) # extract path of schedule file # TODO: include schedule file in sct # TODO: check existence of schedule file file_schedule = path_sct + param.schedule_file # Get input image orientation input_image_orientation = get_orientation_3d(fname_anat, filename=True) # Display arguments print "\nCheck input arguments..." print " Anatomical image: " + fname_anat print " Orientation: " + input_image_orientation print " Point in spinal cord: " + fname_point print " Slice gap: " + str(slice_gap) print " Gaussian kernel: " + str(gaussian_kernel) print " Degree of polynomial: " + str(param.deg_poly) # create temporary folder print ("\nCreate temporary folder...") path_tmp = "tmp." + strftime("%y%m%d%H%M%S") sct.create_folder(path_tmp) print "\nCopy input data..." sct.run("cp " + fname_anat + " " + path_tmp + "/tmp.anat" + ext_anat) sct.run("cp " + fname_point + " " + path_tmp + "/tmp.point" + ext_point) # go to temporary folder os.chdir(path_tmp) # convert to nii im_anat = convert("tmp.anat" + ext_anat, "tmp.anat.nii") im_point = convert("tmp.point" + ext_point, "tmp.point.nii") # Reorient input anatomical volume into RL PA IS orientation print "\nReorient input volume to RL PA IS orientation..." set_orientation(im_anat, "RPI") im_anat.setFileName("tmp.anat_orient.nii") # Reorient binary point into RL PA IS orientation print "\nReorient binary point into RL PA IS orientation..." # sct.run(sct.fsloutput + 'fslswapdim tmp.point RL PA IS tmp.point_orient') set_orientation(im_point, "RPI") im_point.setFileName("tmp.point_orient.nii") # Get image dimensions print "\nGet image dimensions..." nx, ny, nz, nt, px, py, pz, pt = Image("tmp.anat_orient.nii").dim print ".. matrix size: " + str(nx) + " x " + str(ny) + " x " + str(nz) print ".. voxel size: " + str(px) + "mm x " + str(py) + "mm x " + str(pz) + "mm" # Split input volume print "\nSplit input volume..." im_anat_split_list = split_data(im_anat, 2) file_anat_split = [] for im in im_anat_split_list: file_anat_split.append(im.absolutepath) im.save() im_point_split_list = split_data(im_point, 2) file_point_split = [] for im in im_point_split_list: file_point_split.append(im.absolutepath) im.save() # Extract coordinates of input point data_point = Image("tmp.point_orient.nii").data x_init, y_init, z_init = unravel_index(data_point.argmax(), data_point.shape) sct.printv("Coordinates of input point: (" + str(x_init) + ", " + str(y_init) + ", " + str(z_init) + ")", verbose) # Create 2D gaussian mask sct.printv("\nCreate gaussian mask from point...", verbose) xx, yy = mgrid[:nx, :ny] mask2d = zeros((nx, ny)) radius = round(float(gaussian_kernel + 1) / 2) # add 1 because the radius includes the center. sigma = float(radius) mask2d = exp(-(((xx - x_init) ** 2) / (2 * (sigma ** 2)) + ((yy - y_init) ** 2) / (2 * (sigma ** 2)))) # Save mask to 2d file file_mask_split = ["tmp.mask_orient_Z" + str(z).zfill(4) for z in range(0, nz, 1)] nii_mask2d = Image("tmp.anat_orient_Z0000.nii") nii_mask2d.data = mask2d nii_mask2d.setFileName(file_mask_split[z_init] + ".nii") nii_mask2d.save() # initialize variables file_mat = ["tmp.mat_Z" + str(z).zfill(4) for z in range(0, nz, 1)] file_mat_inv = ["tmp.mat_inv_Z" + str(z).zfill(4) for z in range(0, nz, 1)] file_mat_inv_cumul = ["tmp.mat_inv_cumul_Z" + str(z).zfill(4) for z in range(0, nz, 1)] # create identity matrix for initial transformation matrix fid = open(file_mat_inv_cumul[z_init], "w") fid.write("%i %i %i %i\n" % (1, 0, 0, 0)) fid.write("%i %i %i %i\n" % (0, 1, 0, 0)) fid.write("%i %i %i %i\n" % (0, 0, 1, 0)) fid.write("%i %i %i %i\n" % (0, 0, 0, 1)) fid.close() # initialize centerline: give value corresponding to initial point x_centerline = [x_init] y_centerline = [y_init] z_centerline = [z_init] warning_count = 0 # go up (1), then down (2) in reference to the binary point for iUpDown in range(1, 3): if iUpDown == 1: # z increases slice_gap_signed = slice_gap elif iUpDown == 2: # z decreases slice_gap_signed = -slice_gap # reverse centerline (because values will be appended at the end) x_centerline.reverse() y_centerline.reverse() z_centerline.reverse() # initialization before looping z_dest = z_init # point given by user z_src = z_dest + slice_gap_signed # continue looping if 0 <= z < nz while 0 <= z_src < nz: # print current z: print "z=" + str(z_src) + ":" # estimate transformation sct.run( fsloutput + "flirt -in " + file_anat_split[z_src] + " -ref " + file_anat_split[z_dest] + " -schedule " + file_schedule + " -verbose 0 -omat " + file_mat[z_src] + " -cost normcorr -forcescaling -inweight " + file_mask_split[z_dest] + " -refweight " + file_mask_split[z_dest] ) # display transfo status, output = sct.run("cat " + file_mat[z_src]) print output # check if transformation is bigger than 1.5x slice_gap tx = float(output.split()[3]) ty = float(output.split()[7]) norm_txy = linalg.norm([tx, ty], ord=2) if norm_txy > 1.5 * slice_gap: print "WARNING: Transformation is too large --> using previous one." warning_count = warning_count + 1 # if previous transformation exists, replace current one with previous one if os.path.isfile(file_mat[z_dest]): sct.run("cp " + file_mat[z_dest] + " " + file_mat[z_src]) # estimate inverse transformation matrix sct.run("convert_xfm -omat " + file_mat_inv[z_src] + " -inverse " + file_mat[z_src]) # compute cumulative transformation sct.run( "convert_xfm -omat " + file_mat_inv_cumul[z_src] + " -concat " + file_mat_inv[z_src] + " " + file_mat_inv_cumul[z_dest] ) # apply inverse cumulative transformation to initial gaussian mask (to put it in src space) sct.run( fsloutput + "flirt -in " + file_mask_split[z_init] + " -ref " + file_mask_split[z_init] + " -applyxfm -init " + file_mat_inv_cumul[z_src] + " -out " + file_mask_split[z_src] ) # open inverse cumulative transformation file and generate centerline fid = open(file_mat_inv_cumul[z_src]) mat = fid.read().split() x_centerline.append(x_init + float(mat[3])) y_centerline.append(y_init + float(mat[7])) z_centerline.append(z_src) # z_index = z_index+1 # define new z_dest (target slice) and new z_src (moving slice) z_dest = z_dest + slice_gap_signed z_src = z_src + slice_gap_signed # Reconstruct centerline # ==================================================================================================== # reverse back centerline (because it's been reversed once, so now all values are in the right order) x_centerline.reverse() y_centerline.reverse() z_centerline.reverse() # fit centerline in the Z-X plane using polynomial function print "\nFit centerline in the Z-X plane using polynomial function..." coeffsx = polyfit(z_centerline, x_centerline, deg=param.deg_poly) polyx = poly1d(coeffsx) x_centerline_fit = polyval(polyx, z_centerline) # calculate RMSE rmse = linalg.norm(x_centerline_fit - x_centerline) / sqrt(len(x_centerline)) # calculate max absolute error max_abs = max(abs(x_centerline_fit - x_centerline)) print ".. RMSE (in mm): " + str(rmse * px) print ".. Maximum absolute error (in mm): " + str(max_abs * px) # fit centerline in the Z-Y plane using polynomial function print "\nFit centerline in the Z-Y plane using polynomial function..." coeffsy = polyfit(z_centerline, y_centerline, deg=param.deg_poly) polyy = poly1d(coeffsy) y_centerline_fit = polyval(polyy, z_centerline) # calculate RMSE rmse = linalg.norm(y_centerline_fit - y_centerline) / sqrt(len(y_centerline)) # calculate max absolute error max_abs = max(abs(y_centerline_fit - y_centerline)) print ".. RMSE (in mm): " + str(rmse * py) print ".. Maximum absolute error (in mm): " + str(max_abs * py) # display if param.debug == 1: import matplotlib.pyplot as plt plt.figure() plt.plot(z_centerline, x_centerline, ".", z_centerline, x_centerline_fit, "r") plt.legend(["Data", "Polynomial Fit"]) plt.title("Z-X plane polynomial interpolation") plt.show() plt.figure() plt.plot(z_centerline, y_centerline, ".", z_centerline, y_centerline_fit, "r") plt.legend(["Data", "Polynomial Fit"]) plt.title("Z-Y plane polynomial interpolation") plt.show() # generate full range z-values for centerline z_centerline_full = [iz for iz in range(0, nz, 1)] # calculate X and Y values for the full centerline x_centerline_fit_full = polyval(polyx, z_centerline_full) y_centerline_fit_full = polyval(polyy, z_centerline_full) # Generate fitted transformation matrices and write centerline coordinates in text file print "\nGenerate fitted transformation matrices and write centerline coordinates in text file..." file_mat_inv_cumul_fit = ["tmp.mat_inv_cumul_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] file_mat_cumul_fit = ["tmp.mat_cumul_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] fid_centerline = open("tmp.centerline_coordinates.txt", "w") for iz in range(0, nz, 1): # compute inverse cumulative fitted transformation matrix fid = open(file_mat_inv_cumul_fit[iz], "w") fid.write("%i %i %i %f\n" % (1, 0, 0, x_centerline_fit_full[iz] - x_init)) fid.write("%i %i %i %f\n" % (0, 1, 0, y_centerline_fit_full[iz] - y_init)) fid.write("%i %i %i %i\n" % (0, 0, 1, 0)) fid.write("%i %i %i %i\n" % (0, 0, 0, 1)) fid.close() # compute forward cumulative fitted transformation matrix sct.run("convert_xfm -omat " + file_mat_cumul_fit[iz] + " -inverse " + file_mat_inv_cumul_fit[iz]) # write centerline coordinates in x, y, z format fid_centerline.write( "%f %f %f\n" % (x_centerline_fit_full[iz], y_centerline_fit_full[iz], z_centerline_full[iz]) ) fid_centerline.close() # Prepare output data # ==================================================================================================== # write centerline as text file for iz in range(0, nz, 1): # compute inverse cumulative fitted transformation matrix fid = open(file_mat_inv_cumul_fit[iz], "w") fid.write("%i %i %i %f\n" % (1, 0, 0, x_centerline_fit_full[iz] - x_init)) fid.write("%i %i %i %f\n" % (0, 1, 0, y_centerline_fit_full[iz] - y_init)) fid.write("%i %i %i %i\n" % (0, 0, 1, 0)) fid.write("%i %i %i %i\n" % (0, 0, 0, 1)) fid.close() # write polynomial coefficients savetxt("tmp.centerline_polycoeffs_x.txt", coeffsx) savetxt("tmp.centerline_polycoeffs_y.txt", coeffsy) # apply transformations to data print "\nApply fitted transformation matrices..." file_anat_split_fit = ["tmp.anat_orient_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] file_mask_split_fit = ["tmp.mask_orient_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] file_point_split_fit = ["tmp.point_orient_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] for iz in range(0, nz, 1): # forward cumulative transformation to data sct.run( fsloutput + "flirt -in " + file_anat_split[iz] + " -ref " + file_anat_split[iz] + " -applyxfm -init " + file_mat_cumul_fit[iz] + " -out " + file_anat_split_fit[iz] ) # inverse cumulative transformation to mask sct.run( fsloutput + "flirt -in " + file_mask_split[z_init] + " -ref " + file_mask_split[z_init] + " -applyxfm -init " + file_mat_inv_cumul_fit[iz] + " -out " + file_mask_split_fit[iz] ) # inverse cumulative transformation to point sct.run( fsloutput + "flirt -in " + file_point_split[z_init] + " -ref " + file_point_split[z_init] + " -applyxfm -init " + file_mat_inv_cumul_fit[iz] + " -out " + file_point_split_fit[iz] + " -interp nearestneighbour" ) # Merge into 4D volume print "\nMerge into 4D volume..." # im_anat_list = [Image(fname) for fname in glob.glob('tmp.anat_orient_fit_z*.nii')] fname_anat_list = glob.glob("tmp.anat_orient_fit_z*.nii") im_anat_concat = concat_data(fname_anat_list, 2) im_anat_concat.setFileName("tmp.anat_orient_fit.nii") im_anat_concat.save() # im_mask_list = [Image(fname) for fname in glob.glob('tmp.mask_orient_fit_z*.nii')] fname_mask_list = glob.glob("tmp.mask_orient_fit_z*.nii") im_mask_concat = concat_data(fname_mask_list, 2) im_mask_concat.setFileName("tmp.mask_orient_fit.nii") im_mask_concat.save() # im_point_list = [Image(fname) for fname in glob.glob('tmp.point_orient_fit_z*.nii')] fname_point_list = glob.glob("tmp.point_orient_fit_z*.nii") im_point_concat = concat_data(fname_point_list, 2) im_point_concat.setFileName("tmp.point_orient_fit.nii") im_point_concat.save() # Copy header geometry from input data print "\nCopy header geometry from input data..." im_anat = Image("tmp.anat_orient.nii") im_anat_orient_fit = Image("tmp.anat_orient_fit.nii") im_mask_orient_fit = Image("tmp.mask_orient_fit.nii") im_point_orient_fit = Image("tmp.point_orient_fit.nii") im_anat_orient_fit = copy_header(im_anat, im_anat_orient_fit) im_mask_orient_fit = copy_header(im_anat, im_mask_orient_fit) im_point_orient_fit = copy_header(im_anat, im_point_orient_fit) for im in [im_anat_orient_fit, im_mask_orient_fit, im_point_orient_fit]: im.save() # Reorient outputs into the initial orientation of the input image print "\nReorient the centerline into the initial orientation of the input image..." set_orientation("tmp.point_orient_fit.nii", input_image_orientation, "tmp.point_orient_fit.nii") set_orientation("tmp.mask_orient_fit.nii", input_image_orientation, "tmp.mask_orient_fit.nii") # Generate output file (in current folder) print "\nGenerate output file (in current folder)..." os.chdir("..") # come back to parent folder fname_output_centerline = sct.generate_output_file( path_tmp + "/tmp.point_orient_fit.nii", file_anat + "_centerline" + ext_anat ) # Delete temporary files if remove_tmp_files == 1: print "\nRemove temporary files..." sct.run("rm -rf " + path_tmp, error_exit="warning") # print number of warnings print "\nNumber of warnings: " + str( warning_count ) + " (if >10, you should probably reduce the gap and/or increase the kernel size" # display elapsed time elapsed_time = time() - start_time print "\nFinished! \n\tGenerated file: " + fname_output_centerline + "\n\tElapsed time: " + str( int(round(elapsed_time)) ) + "s\n"
def main(args=None): # Initialization # fname_anat = '' # fname_centerline = '' sigma = 3 # default value of the standard deviation for the Gaussian smoothing (in terms of number of voxels) # remove_temp_files = param.remove_temp_files # verbose = param.verbose start_time = time.time() parser = get_parser() arguments = parser.parse(sys.argv[1:]) fname_anat = arguments['-i'] fname_centerline = arguments['-s'] if '-smooth' in arguments: sigma = arguments['-smooth'] if '-r' in arguments: remove_temp_files = int(arguments['-r']) if '-v' in arguments: verbose = int(arguments['-v']) # Display arguments print '\nCheck input arguments...' print ' Volume to smooth .................. ' + fname_anat print ' Centerline ........................ ' + fname_centerline print ' Sigma (mm) ........................ '+str(sigma) print ' Verbose ........................... '+str(verbose) # Check that input is 3D: from msct_image import Image nx, ny, nz, nt, px, py, pz, pt = Image(fname_anat).dim dim = 4 # by default, will be adjusted later if nt == 1: dim = 3 if nz == 1: dim = 2 if dim == 4: sct.printv('WARNING: the input image is 4D, please split your image to 3D before smoothing spinalcord using :\n' 'sct_image -i '+fname_anat+' -split t -o '+fname_anat, verbose, 'warning') sct.printv('4D images not supported, aborting ...', verbose, 'error') # Extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) path_centerline, file_centerline, ext_centerline = sct.extract_fname(fname_centerline) # create temporary folder sct.printv('\nCreate temporary folder...', verbose) path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+path_tmp, verbose) # Copying input data to tmp folder sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) sct.run('cp '+fname_anat+' '+path_tmp+'anat'+ext_anat, verbose) sct.run('cp '+fname_centerline+' '+path_tmp+'centerline'+ext_centerline, verbose) # go to tmp folder os.chdir(path_tmp) # convert to nii format convert('anat'+ext_anat, 'anat.nii') convert('centerline'+ext_centerline, 'centerline.nii') # Change orientation of the input image into RPI print '\nOrient input volume to RPI orientation...' fname_anat_rpi = set_orientation('anat.nii', 'RPI', filename=True) move(fname_anat_rpi, 'anat_rpi.nii') # Change orientation of the input image into RPI print '\nOrient centerline to RPI orientation...' fname_centerline_rpi = set_orientation('centerline.nii', 'RPI', filename=True) move(fname_centerline_rpi, 'centerline_rpi.nii') # Straighten the spinal cord # straighten segmentation sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose) # check if warp_curve2straight and warp_straight2curve already exist (i.e. no need to do it another time) if os.path.isfile('../warp_curve2straight.nii.gz') and os.path.isfile('../warp_straight2curve.nii.gz') and os.path.isfile('../straight_ref.nii.gz'): # if they exist, copy them into current folder sct.printv('WARNING: Straightening was already run previously. Copying warping fields...', verbose, 'warning') shutil.copy('../warp_curve2straight.nii.gz', 'warp_curve2straight.nii.gz') shutil.copy('../warp_straight2curve.nii.gz', 'warp_straight2curve.nii.gz') shutil.copy('../straight_ref.nii.gz', 'straight_ref.nii.gz') # apply straightening sct.run('sct_apply_transfo -i anat_rpi.nii -w warp_curve2straight.nii.gz -d straight_ref.nii.gz -o anat_rpi_straight.nii -x spline', verbose) else: sct.run('sct_straighten_spinalcord -i anat_rpi.nii -s centerline_rpi.nii -qc 0 -x spline', verbose) # Smooth the straightened image along z print '\nSmooth the straightened image along z...' sct.run('sct_maths -i anat_rpi_straight.nii -smooth 0,0,'+str(sigma)+' -o anat_rpi_straight_smooth.nii', verbose) # Apply the reversed warping field to get back the curved spinal cord print '\nApply the reversed warping field to get back the curved spinal cord...' sct.run('sct_apply_transfo -i anat_rpi_straight_smooth.nii -o anat_rpi_straight_smooth_curved.nii -d anat.nii -w warp_straight2curve.nii.gz -x spline', verbose) # replace zeroed voxels by original image (issue #937) sct.printv('\nReplace zeroed voxels by original image...', verbose) nii_smooth = Image('anat_rpi_straight_smooth_curved.nii') data_smooth = nii_smooth.data data_input = Image('anat.nii').data indzero = np.where(data_smooth == 0) data_smooth[indzero] = data_input[indzero] nii_smooth.data = data_smooth nii_smooth.setFileName('anat_rpi_straight_smooth_curved_nonzero.nii') nii_smooth.save() # come back to parent folder os.chdir('..') # Generate output file print '\nGenerate output file...' sct.generate_output_file(path_tmp+'/anat_rpi_straight_smooth_curved_nonzero.nii', file_anat+'_smooth'+ext_anat) # Remove temporary files if remove_temp_files == 1: print('\nRemove temporary files...') sct.run('rm -rf '+path_tmp) # Display elapsed time elapsed_time = time.time() - start_time print '\nFinished! Elapsed time: '+str(int(round(elapsed_time)))+'s\n' # to view results sct.printv('Done! To view results, type:', verbose) sct.printv('fslview '+file_anat+' '+file_anat+'_smooth &\n', verbose, 'info')
def create_mask(): fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI # display usage if a mandatory argument is not provided if param.fname_data == '' or param.method == '': sct.printv('\nERROR: All mandatory arguments are not provided. See usage (add -h).\n', 1, 'error') # parse argument for method method_list = param.method.replace(' ', '').split(',') # remove spaces and parse with comma # method_list = param.method.split(',') # parse with comma method_type = method_list[0] # check existence of method type if not method_type in param.method_list: sct.printv('\nERROR in '+os.path.basename(__file__)+': Method "'+method_type+'" is not recognized. See usage (add -h).\n', 1, 'error') # check method val if not method_type == 'center': method_val = method_list[1] del method_list # check existence of shape if not param.shape in param.shape_list: sct.printv('\nERROR in '+os.path.basename(__file__)+': Shape "'+param.shape+'" is not recognized. See usage (add -h).\n', 1, 'error') # check existence of input files sct.printv('\ncheck existence of input files...', param.verbose) sct.check_file_exist(param.fname_data, param.verbose) if method_type == 'centerline': sct.check_file_exist(method_val, param.verbose) # check if orientation is RPI sct.printv('\nCheck if orientation is RPI...', param.verbose) status, output = sct.run('sct_orientation -i '+param.fname_data) if not output == 'RPI': sct.printv('\nERROR in '+os.path.basename(__file__)+': Orientation of input image should be RPI. Use sct_orientation to put your image in RPI.\n', 1, 'error') # display input parameters sct.printv('\nInput parameters:', param.verbose) sct.printv(' data ..................'+param.fname_data, param.verbose) sct.printv(' method ................'+method_type, param.verbose) # Extract path/file/extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) # Get output folder and file name if param.fname_out == '': param.fname_out = param.file_prefix+file_data+ext_data #fname_out = os.path.abspath(path_out+file_out+ext_out) # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+path_tmp, param.verbose) # Copying input data to tmp folder and convert to nii # NB: cannot use c3d here because c3d cannot convert 4D data. sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, path_tmp+'data.nii') # sct.run('cp '+param.fname_data+' '+path_tmp+'data'+ext_data, param.verbose) if method_type == 'centerline': convert(method_val, path_tmp+'centerline.nii.gz') # sct.run('isct_c3d '+method_val+' -o '+path_tmp+'/centerline.nii.gz') # go to tmp folder os.chdir(path_tmp) # Get dimensions of data sct.printv('\nGet dimensions of data...', param.verbose) nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim sct.printv(' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz)+ ' x ' + str(nt), param.verbose) # in case user input 4d data if nt != 1: sct.printv('WARNING in '+os.path.basename(__file__)+': Input image is 4d but output mask will 3D.', param.verbose, 'warning') # extract first volume to have 3d reference nii = Image('data.nii') data3d = nii.data[:,:,:,0] nii.data = data3d nii.save() if method_type == 'coord': # parse to get coordinate coord = map(int, method_val.split('x')) if method_type == 'point': # get file name fname_point = method_val # extract coordinate of point sct.printv('\nExtract coordinate of point...', param.verbose) status, output = sct.run('sct_label_utils -i '+fname_point+' -t display-voxel', param.verbose) # parse to get coordinate coord = output[output.find('Position=')+10:-17].split(',') if method_type == 'center': # set coordinate at center of FOV coord = round(float(nx)/2), round(float(ny)/2) if method_type == 'centerline': # get name of centerline from user argument fname_centerline = 'centerline.nii.gz' else: # generate volume with line along Z at coordinates 'coord' sct.printv('\nCreate line...', param.verbose) fname_centerline = create_line('data.nii', coord, nz) # create mask sct.printv('\nCreate mask...', param.verbose) centerline = nibabel.load(fname_centerline) # open centerline hdr = centerline.get_header() # get header hdr.set_data_dtype('uint8') # set imagetype to uint8 data_centerline = centerline.get_data() # get centerline z_centerline = [iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any()] nz = len(z_centerline) # get center of mass of the centerline cx = [0] * nz cy = [0] * nz for iz in range(0, nz, 1): cx[iz], cy[iz] = ndimage.measurements.center_of_mass(numpy.array(data_centerline[:, :, z_centerline[iz]])) # create 2d masks file_mask = 'data_mask' for iz in range(nz): center = numpy.array([cx[iz], cy[iz]]) mask2d = create_mask2d(center, param.shape, param.size, nx, ny) # Write NIFTI volumes img = nibabel.Nifti1Image(mask2d, None, hdr) nibabel.save(img, (file_mask+str(iz)+'.nii')) # merge along Z # cmd = 'fslmerge -z mask ' cmd = 'sct_concat_data -dim z -o mask.nii.gz -i ' for iz in range(nz): cmd = cmd + file_mask+str(iz)+'.nii,' # remove ',' at the end of the string cmd = cmd[:-1] status, output = sct.run(cmd, param.verbose) # copy geometry copy_header('data.nii', 'mask.nii.gz') # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(path_tmp+'mask.nii.gz', param.fname_out) # Remove temporary files if param.remove_tmp_files == 1: sct.printv('\nRemove temporary files...', param.verbose) sct.run('rm -rf '+path_tmp, param.verbose) # to view results sct.printv('\nDone! To view results, type:', param.verbose) sct.printv('fslview '+param.fname_data+' '+param.fname_out+' -l Red -t 0.5 &', param.verbose, 'info') print
def fmri_moco(param): file_data = "fmri.nii" mat_final = 'mat_final/' ext_mat = 'Warp.nii.gz' # warping field # Get dimensions of data sct.printv('\nGet dimensions of data...', param.verbose) im_data = Image(param.fname_data) nx, ny, nz, nt, px, py, pz, pt = im_data.dim sct.printv( ' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt), param.verbose) # Get orientation sct.printv('\nData orientation: ' + im_data.orientation, param.verbose) if im_data.orientation[2] in 'LR': param.is_sagittal = True sct.printv(' Treated as sagittal') elif im_data.orientation[2] in 'IS': param.is_sagittal = False sct.printv(' Treated as axial') else: param.is_sagittal = False sct.printv( 'WARNING: Orientation seems to be neither axial nor sagittal.') # Adjust group size in case of sagittal scan if param.is_sagittal and param.group_size != 1: sct.printv( 'For sagittal data group_size should be one for more robustness. Forcing group_size=1.', 1, 'warning') param.group_size = 1 # Split into T dimension sct.printv('\nSplit along T dimension...', param.verbose) im_data_split_list = split_data(im_data, 3) for im in im_data_split_list: x_dirname, x_basename, x_ext = sct.extract_fname(im.absolutepath) # Make further steps slurp the data to avoid too many open files (#2149) im.absolutepath = os.path.join(x_dirname, x_basename + ".nii.gz") im.save() # assign an index to each volume index_fmri = list(range(0, nt)) # Number of groups nb_groups = int(math.floor(nt / param.group_size)) # Generate groups indexes group_indexes = [] for iGroup in range(nb_groups): group_indexes.append(index_fmri[(iGroup * param.group_size):((iGroup + 1) * param.group_size)]) # add the remaining images to the last fMRI group nb_remaining = nt % param.group_size # number of remaining images if nb_remaining > 0: nb_groups += 1 group_indexes.append(index_fmri[len(index_fmri) - nb_remaining:len(index_fmri)]) # groups for iGroup in tqdm(range(nb_groups), unit='iter', unit_scale=False, desc="Merge within groups", ascii=True, ncols=80): # get index index_fmri_i = group_indexes[iGroup] nt_i = len(index_fmri_i) # Merge Images file_data_merge_i = sct.add_suffix(file_data, '_' + str(iGroup)) # cmd = fsloutput + 'fslmerge -t ' + file_data_merge_i # for it in range(nt_i): # cmd = cmd + ' ' + file_data + '_T' + str(index_fmri_i[it]).zfill(4) im_fmri_list = [] for it in range(nt_i): im_fmri_list.append(im_data_split_list[index_fmri_i[it]]) im_fmri_concat = concat_data(im_fmri_list, 3, squeeze_data=True).save(file_data_merge_i) file_data_mean = sct.add_suffix(file_data, '_mean_' + str(iGroup)) if file_data_mean.endswith(".nii"): file_data_mean += ".gz" # #2149 if param.group_size == 1: # copy to new file name instead of averaging (faster) # note: this is a bandage. Ideally we should skip this entire for loop if g=1 convert(file_data_merge_i, file_data_mean) else: # Average Images sct.run([ 'sct_maths', '-i', file_data_merge_i, '-o', file_data_mean, '-mean', 't' ], verbose=0) # if not average_data_across_dimension(file_data_merge_i+'.nii', file_data_mean+'.nii', 3): # sct.printv('ERROR in average_data_across_dimension', 1, 'error') # cmd = fsloutput + 'fslmaths ' + file_data_merge_i + ' -Tmean ' + file_data_mean # sct.run(cmd, param.verbose) # Merge groups means. The output 4D volume will be used for motion correction. sct.printv('\nMerging volumes...', param.verbose) file_data_groups_means_merge = 'fmri_averaged_groups.nii' im_mean_list = [] for iGroup in range(nb_groups): file_data_mean = sct.add_suffix(file_data, '_mean_' + str(iGroup)) if file_data_mean.endswith(".nii"): file_data_mean += ".gz" # #2149 im_mean_list.append(Image(file_data_mean)) im_mean_concat = concat_data(im_mean_list, 3).save(file_data_groups_means_merge) # Estimate moco sct.printv( '\n-------------------------------------------------------------------------------', param.verbose) sct.printv(' Estimating motion...', param.verbose) sct.printv( '-------------------------------------------------------------------------------', param.verbose) param_moco = param param_moco.file_data = 'fmri_averaged_groups.nii' param_moco.file_target = sct.add_suffix(file_data, '_mean_' + param.num_target) if param_moco.file_target.endswith(".nii"): param_moco.file_target += ".gz" # #2149 param_moco.path_out = '' param_moco.todo = 'estimate_and_apply' param_moco.mat_moco = 'mat_groups' file_mat = moco.moco(param_moco) # TODO: if g=1, no need to run the block below (already applied) if param.group_size == 1: # if flag g=1, it means that all images have already been corrected, so we just need to rename the file sct.mv('fmri_averaged_groups_moco.nii', 'fmri_moco.nii') else: # create final mat folder sct.create_folder(mat_final) # Copy registration matrices sct.printv('\nCopy transformations...', param.verbose) for iGroup in range(nb_groups): for data in range( len(group_indexes[iGroup]) ): # we cannot use enumerate because group_indexes has 2 dim. # fetch all file_mat_z for given t-group list_file_mat_z = file_mat[:, iGroup] # loop across file_mat_z and copy to mat_final folder for file_mat_z in list_file_mat_z: # we want to copy 'mat_groups/mat.ZXXXXTYYYYWarp.nii.gz' --> 'mat_final/mat.ZXXXXTYYYZWarp.nii.gz' # Notice the Y->Z in the under the T index: the idea here is to use the single matrix from each group, # and apply it to all images belonging to the same group. sct.copy( file_mat_z + ext_mat, mat_final + file_mat_z[11:20] + 'T' + str(group_indexes[iGroup][data]).zfill(4) + ext_mat) # Apply moco on all fmri data sct.printv( '\n-------------------------------------------------------------------------------', param.verbose) sct.printv(' Apply moco', param.verbose) sct.printv( '-------------------------------------------------------------------------------', param.verbose) param_moco.file_data = 'fmri.nii' param_moco.file_target = sct.add_suffix(file_data, '_mean_' + str(0)) if param_moco.file_target.endswith(".nii"): param_moco.file_target += ".gz" param_moco.path_out = '' param_moco.mat_moco = mat_final param_moco.todo = 'apply' file_mat = moco.moco(param_moco) # copy geometric information from header # NB: this is required because WarpImageMultiTransform in 2D mode wrongly sets pixdim(3) to "1". im_fmri = Image('fmri.nii') im_fmri_moco = Image('fmri_moco.nii') im_fmri_moco.header = im_fmri.header im_fmri_moco.save() # Extract and output the motion parameters if param.output_motion_param: from sct_image import multicomponent_split import csv #files_warp = [] files_warp_X, files_warp_Y = [], [] moco_param = [] for fname_warp in file_mat[0]: # Cropping the image to keep only one voxel in the XY plane im_warp = Image(fname_warp + ext_mat) im_warp.data = np.expand_dims(np.expand_dims( im_warp.data[0, 0, :, :, :], axis=0), axis=0) # These three lines allow to generate one file instead of two, containing X, Y and Z moco parameters #fname_warp_crop = fname_warp + '_crop_' + ext_mat #files_warp.append(fname_warp_crop) #im_warp.save(fname_warp_crop) # Separating the three components and saving X and Y only (Z is equal to 0 by default). im_warp_XYZ = multicomponent_split(im_warp) fname_warp_crop_X = fname_warp + '_crop_X_' + ext_mat im_warp_XYZ[0].save(fname_warp_crop_X) files_warp_X.append(fname_warp_crop_X) fname_warp_crop_Y = fname_warp + '_crop_Y_' + ext_mat im_warp_XYZ[1].save(fname_warp_crop_Y) files_warp_Y.append(fname_warp_crop_Y) # Calculating the slice-wise average moco estimate to provide a QC file moco_param.append([ np.mean(np.ravel(im_warp_XYZ[0].data)), np.mean(np.ravel(im_warp_XYZ[1].data)) ]) # These two lines allow to generate one file instead of two, containing X, Y and Z moco parameters #im_warp_concat = concat_data(files_warp, dim=3) #im_warp_concat.save('fmri_moco_params.nii') # Concatenating the moco parameters into a time series for X and Y components. im_warp_concat = concat_data(files_warp_X, dim=3) im_warp_concat.save('fmri_moco_params_X.nii') im_warp_concat = concat_data(files_warp_Y, dim=3) im_warp_concat.save('fmri_moco_params_Y.nii') # Writing a TSV file with the slicewise average estimate of the moco parameters, as it is a useful QC file. with open('fmri_moco_params.tsv', 'wt') as out_file: tsv_writer = csv.writer(out_file, delimiter='\t') tsv_writer.writerow(['X', 'Y']) for mocop in moco_param: tsv_writer.writerow([mocop[0], mocop[1]]) # Average volumes sct.printv('\nAveraging data...', param.verbose) sct_maths.main(args=[ '-i', 'fmri_moco.nii', '-o', 'fmri_moco_mean.nii', '-mean', 't', '-v', '0' ])
def main(args=None): # initialization start_time = time.time() path_out = '.' param = Param() # reducing the number of CPU used for moco (see issue #201) os.environ["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = "1" # get path of the toolbox # status, param.path_sct = commands.getstatusoutput('echo $SCT_DIR') # check user arguments if not args: args = sys.argv[1:] # Get parser info parser = get_parser() arguments = parser.parse(sys.argv[1:]) param.fname_data = arguments['-i'] param.fname_bvecs = arguments['-bvec'] if '-bval' in arguments: param.fname_bvals = arguments['-bval'] if '-bvalmin' in arguments: param.bval_min = arguments['-bvalmin'] if '-g' in arguments: param.group_size = arguments['-g'] if '-m' in arguments: param.fname_mask = arguments['-m'] if '-param' in arguments: param.update(arguments['-param']) if '-thr' in arguments: param.otsu = arguments['-thr'] if '-x' in arguments: param.interp = arguments['-x'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-r' in arguments: param.remove_tmp_files = int(arguments['-r']) if '-v' in arguments: param.verbose = int(arguments['-v']) # Get full path param.fname_data = os.path.abspath(param.fname_data) param.fname_bvecs = os.path.abspath(param.fname_bvecs) if param.fname_bvals != '': param.fname_bvals = os.path.abspath(param.fname_bvals) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) path_mask, file_mask, ext_mask = sct.extract_fname(param.fname_mask) # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.slash_at_the_end('tmp.' + time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir ' + path_tmp, param.verbose) # names of files in temporary folder ext = '.nii' dmri_name = 'dmri' mask_name = 'mask' bvecs_fname = 'bvecs.txt' # Copying input data to tmp folder sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, path_tmp + dmri_name + ext) sct.run('cp ' + param.fname_bvecs + ' ' + path_tmp + bvecs_fname, param.verbose) if param.fname_mask != '': sct.run( 'cp ' + param.fname_mask + ' ' + path_tmp + mask_name + ext_mask, param.verbose) # go to tmp folder os.chdir(path_tmp) # update field in param (because used later). # TODO: make this cleaner... if param.fname_mask != '': param.fname_mask = mask_name + ext_mask # run moco dmri_moco(param) # come back to parent folder os.chdir('..') # Generate output files path_out = sct.slash_at_the_end(path_out, 1) sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(path_tmp + dmri_name + param.suffix + ext, path_out + file_data + param.suffix + ext_data, param.verbose) sct.generate_output_file( path_tmp + 'b0_mean.nii', path_out + 'b0' + param.suffix + '_mean' + ext_data, param.verbose) sct.generate_output_file( path_tmp + 'dwi_mean.nii', path_out + 'dwi' + param.suffix + '_mean' + ext_data, param.verbose) # Delete temporary files if param.remove_tmp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.run('rm -rf ' + path_tmp, param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv( '\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's', param.verbose) # To view results sct.printv('\nTo view results, type:', param.verbose) sct.printv( 'fslview -m ortho,ortho ' + param.path_out + file_data + param.suffix + ' ' + file_data + ' &\n', param.verbose, 'info')
def create_mask(): fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI # parse argument for method method_type = param.process[0] # check method val if not method_type == 'center': method_val = param.process[1] # check existence of input files if method_type == 'centerline': sct.check_file_exist(method_val, param.verbose) # Extract path/file/extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) # Get output folder and file name if param.fname_out == '': param.fname_out = param.file_prefix+file_data+ext_data # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.tmp_create(param.verbose) # )sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) # sct.run('mkdir '+path_tmp, param.verbose) sct.printv('\nCheck orientation...', param.verbose) orientation_input = get_orientation(Image(param.fname_data)) sct.printv('.. '+orientation_input, param.verbose) reorient_coordinates = False # copy input data to tmp folder convert(param.fname_data, path_tmp+'data.nii') if method_type == 'centerline': convert(method_val, path_tmp+'centerline.nii.gz') if method_type == 'point': convert(method_val, path_tmp+'point.nii.gz') # go to tmp folder os.chdir(path_tmp) # reorient to RPI sct.printv('\nReorient to RPI...', param.verbose) # if not orientation_input == 'RPI': sct.run('sct_image -i data.nii -o data_RPI.nii -setorient RPI -v 0', verbose=False) if method_type == 'centerline': sct.run('sct_image -i centerline.nii.gz -o centerline_RPI.nii.gz -setorient RPI -v 0', verbose=False) if method_type == 'point': sct.run('sct_image -i point.nii.gz -o point_RPI.nii.gz -setorient RPI -v 0', verbose=False) # # if method_type == 'centerline': # orientation_centerline = get_orientation_3d(method_val, filename=True) # if not orientation_centerline == 'RPI': # sct.run('sct_image -i ' + method_val + ' -o ' + path_tmp + 'centerline.nii.gz' + ' -setorient RPI -v 0', verbose=False) # else: # convert(method_val, path_tmp+'centerline.nii.gz') # Get dimensions of data sct.printv('\nGet dimensions of data...', param.verbose) nx, ny, nz, nt, px, py, pz, pt = Image('data_RPI.nii').dim sct.printv(' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz)+ ' x ' + str(nt), param.verbose) # in case user input 4d data if nt != 1: sct.printv('WARNING in '+os.path.basename(__file__)+': Input image is 4d but output mask will 3D.', param.verbose, 'warning') # extract first volume to have 3d reference nii = Image('data_RPI.nii') data3d = nii.data[:,:,:,0] nii.data = data3d nii.save() if method_type == 'coord': # parse to get coordinate coord = map(int, method_val.split('x')) if method_type == 'point': # get file name fname_point = method_val # extract coordinate of point sct.printv('\nExtract coordinate of point...', param.verbose) # TODO: change this way to remove dependence to sct.run. ProcessLabels.display_voxel returns list of coordinates status, output = sct.run('sct_label_utils -i point_RPI.nii.gz -display', param.verbose) # parse to get coordinate coord = output[output.find('Position=')+10:-17].split(',') if method_type == 'center': # set coordinate at center of FOV coord = round(float(nx)/2), round(float(ny)/2) if method_type == 'centerline': # get name of centerline from user argument fname_centerline = 'centerline_RPI.nii.gz' else: # generate volume with line along Z at coordinates 'coord' sct.printv('\nCreate line...', param.verbose) fname_centerline = create_line('data_RPI.nii', coord, nz) # create mask sct.printv('\nCreate mask...', param.verbose) centerline = nibabel.load(fname_centerline) # open centerline hdr = centerline.get_header() # get header hdr.set_data_dtype('uint8') # set imagetype to uint8 spacing = hdr.structarr['pixdim'] data_centerline = centerline.get_data() # get centerline z_centerline_not_null = [iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any()] # get center of mass of the centerline cx = [0] * nz cy = [0] * nz for iz in range(0, nz, 1): if iz in z_centerline_not_null: cx[iz], cy[iz] = ndimage.measurements.center_of_mass(numpy.array(data_centerline[:, :, iz])) # create 2d masks file_mask = 'data_mask' for iz in range(nz): if iz not in z_centerline_not_null: # write an empty nifty volume img = nibabel.Nifti1Image(data_centerline[:, :, iz], None, hdr) nibabel.save(img, (file_mask + str(iz) + '.nii')) else: center = numpy.array([cx[iz], cy[iz]]) mask2d = create_mask2d(center, param.shape, param.size, nx, ny, even=param.even, spacing=spacing) # Write NIFTI volumes img = nibabel.Nifti1Image(mask2d, None, hdr) nibabel.save(img, (file_mask+str(iz)+'.nii')) # merge along Z # cmd = 'fslmerge -z mask ' # CHANGE THAT CAN IMPACT SPEED: # related to issue #755, we cannot open more than 256 files at one time. # to solve this issue, we do not open more than 100 files ''' im_list = [] im_temp = [] for iz in range(nz_not_null): if iz != 0 and iz % 100 == 0: im_temp.append(concat_data(im_list, 2)) im_list = [Image(file_mask + str(iz) + '.nii')] else: im_list.append(Image(file_mask+str(iz)+'.nii')) if im_temp: im_temp.append(concat_data(im_list, 2)) im_out = concat_data(im_temp, 2, no_expand=True) else: im_out = concat_data(im_list, 2) ''' fname_list = [file_mask + str(iz) + '.nii' for iz in range(nz)] im_out = concat_data(fname_list, dim=2) im_out.setFileName('mask_RPI.nii.gz') im_out.save() # reorient if necessary # if not orientation_input == 'RPI': sct.run('sct_image -i mask_RPI.nii.gz -o mask.nii.gz -setorient ' + orientation_input, param.verbose) # copy header input --> mask im_dat = Image('data.nii') im_mask = Image('mask.nii.gz') im_mask = copy_header(im_dat, im_mask) im_mask.save() # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(path_tmp+'mask.nii.gz', param.fname_out) # Remove temporary files if param.remove_tmp_files == 1: sct.printv('\nRemove temporary files...', param.verbose) sct.run('rm -rf '+path_tmp, param.verbose, error_exit='warning') # to view results sct.printv('\nDone! To view results, type:', param.verbose) sct.printv('fslview '+param.fname_data+' '+param.fname_out+' -l Red -t 0.5 &', param.verbose, 'info') print
def fmri_moco(param): file_data = "fmri.nii" mat_final = 'mat_final/' ext_mat = 'Warp.nii.gz' # warping field # Get dimensions of data sct.printv('\nGet dimensions of data...', param.verbose) im_data = Image(param.fname_data) nx, ny, nz, nt, px, py, pz, pt = im_data.dim sct.printv(' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt), param.verbose) # Get orientation sct.printv('\nData orientation: ' + im_data.orientation, param.verbose) if im_data.orientation[2] in 'LR': param.is_sagittal = True sct.printv(' Treated as sagittal') elif im_data.orientation[2] in 'IS': param.is_sagittal = False sct.printv(' Treated as axial') else: param.is_sagittal = False sct.printv('WARNING: Orientation seems to be neither axial nor sagittal.') # Adjust group size in case of sagittal scan if param.is_sagittal and param.group_size != 1: sct.printv('For sagittal data group_size should be one for more robustness. Forcing group_size=1.', 1, 'warning') param.group_size = 1 # Split into T dimension sct.printv('\nSplit along T dimension...', param.verbose) im_data_split_list = split_data(im_data, 3) for im in im_data_split_list: x_dirname, x_basename, x_ext = sct.extract_fname(im.absolutepath) # Make further steps slurp the data to avoid too many open files (#2149) im.absolutepath = os.path.join(x_dirname, x_basename + ".nii.gz") im.save() # assign an index to each volume index_fmri = list(range(0, nt)) # Number of groups nb_groups = int(math.floor(nt / param.group_size)) # Generate groups indexes group_indexes = [] for iGroup in range(nb_groups): group_indexes.append(index_fmri[(iGroup * param.group_size):((iGroup + 1) * param.group_size)]) # add the remaining images to the last fMRI group nb_remaining = nt%param.group_size # number of remaining images if nb_remaining > 0: nb_groups += 1 group_indexes.append(index_fmri[len(index_fmri) - nb_remaining:len(index_fmri)]) # groups for iGroup in tqdm(range(nb_groups), unit='iter', unit_scale=False, desc="Merge within groups", ascii=True, ncols=80): # get index index_fmri_i = group_indexes[iGroup] nt_i = len(index_fmri_i) # Merge Images file_data_merge_i = sct.add_suffix(file_data, '_' + str(iGroup)) # cmd = fsloutput + 'fslmerge -t ' + file_data_merge_i # for it in range(nt_i): # cmd = cmd + ' ' + file_data + '_T' + str(index_fmri_i[it]).zfill(4) im_fmri_list = [] for it in range(nt_i): im_fmri_list.append(im_data_split_list[index_fmri_i[it]]) im_fmri_concat = concat_data(im_fmri_list, 3, squeeze_data=True).save(file_data_merge_i) file_data_mean = sct.add_suffix(file_data, '_mean_' + str(iGroup)) if file_data_mean.endswith(".nii"): file_data_mean += ".gz" # #2149 if param.group_size == 1: # copy to new file name instead of averaging (faster) # note: this is a bandage. Ideally we should skip this entire for loop if g=1 convert(file_data_merge_i, file_data_mean) else: # Average Images sct.run(['sct_maths', '-i', file_data_merge_i, '-o', file_data_mean, '-mean', 't'], verbose=0) # if not average_data_across_dimension(file_data_merge_i+'.nii', file_data_mean+'.nii', 3): # sct.printv('ERROR in average_data_across_dimension', 1, 'error') # cmd = fsloutput + 'fslmaths ' + file_data_merge_i + ' -Tmean ' + file_data_mean # sct.run(cmd, param.verbose) # Merge groups means. The output 4D volume will be used for motion correction. sct.printv('\nMerging volumes...', param.verbose) file_data_groups_means_merge = 'fmri_averaged_groups.nii' im_mean_list = [] for iGroup in range(nb_groups): file_data_mean = sct.add_suffix(file_data, '_mean_' + str(iGroup)) if file_data_mean.endswith(".nii"): file_data_mean += ".gz" # #2149 im_mean_list.append(Image(file_data_mean)) im_mean_concat = concat_data(im_mean_list, 3).save(file_data_groups_means_merge) # Estimate moco sct.printv('\n-------------------------------------------------------------------------------', param.verbose) sct.printv(' Estimating motion...', param.verbose) sct.printv('-------------------------------------------------------------------------------', param.verbose) param_moco = param param_moco.file_data = 'fmri_averaged_groups.nii' param_moco.file_target = sct.add_suffix(file_data, '_mean_' + param.num_target) if param_moco.file_target.endswith(".nii"): param_moco.file_target += ".gz" # #2149 param_moco.path_out = '' param_moco.todo = 'estimate_and_apply' param_moco.mat_moco = 'mat_groups' file_mat = moco.moco(param_moco) # TODO: if g=1, no need to run the block below (already applied) if param.group_size == 1: # if flag g=1, it means that all images have already been corrected, so we just need to rename the file sct.mv('fmri_averaged_groups_moco.nii', 'fmri_moco.nii') else: # create final mat folder sct.create_folder(mat_final) # Copy registration matrices sct.printv('\nCopy transformations...', param.verbose) for iGroup in range(nb_groups): for data in range(len(group_indexes[iGroup])): # we cannot use enumerate because group_indexes has 2 dim. # fetch all file_mat_z for given t-group list_file_mat_z = file_mat[:, iGroup] # loop across file_mat_z and copy to mat_final folder for file_mat_z in list_file_mat_z: # we want to copy 'mat_groups/mat.ZXXXXTYYYYWarp.nii.gz' --> 'mat_final/mat.ZXXXXTYYYZWarp.nii.gz' # Notice the Y->Z in the under the T index: the idea here is to use the single matrix from each group, # and apply it to all images belonging to the same group. sct.copy(file_mat_z + ext_mat, mat_final + file_mat_z[11:20] + 'T' + str(group_indexes[iGroup][data]).zfill(4) + ext_mat) # Apply moco on all fmri data sct.printv('\n-------------------------------------------------------------------------------', param.verbose) sct.printv(' Apply moco', param.verbose) sct.printv('-------------------------------------------------------------------------------', param.verbose) param_moco.file_data = 'fmri.nii' param_moco.file_target = sct.add_suffix(file_data, '_mean_' + str(0)) if param_moco.file_target.endswith(".nii"): param_moco.file_target += ".gz" param_moco.path_out = '' param_moco.mat_moco = mat_final param_moco.todo = 'apply' moco.moco(param_moco) # copy geometric information from header # NB: this is required because WarpImageMultiTransform in 2D mode wrongly sets pixdim(3) to "1". im_fmri = Image('fmri.nii') im_fmri_moco = Image('fmri_moco.nii') im_fmri_moco.header = im_fmri.header im_fmri_moco.save() # Average volumes sct.printv('\nAveraging data...', param.verbose) sct_maths.main(args=['-i', 'fmri_moco.nii', '-o', 'fmri_moco_mean.nii', '-mean', 't', '-v', '0'])
def main(): # initialization start_time = time.time() path_out = '.' param_user = '' # reducing the number of CPU used for moco (see issue #201) os.environ["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = "1" # get path of the toolbox status, param.path_sct = commands.getstatusoutput('echo $SCT_DIR') # Parameters for debug mode if param.debug: # get path of the testing data status, path_sct_data = commands.getstatusoutput('echo $SCT_TESTING_DATA_DIR') param.fname_data = path_sct_data+'/dmri/dmri.nii.gz' param.fname_bvecs = path_sct_data+'/dmri/bvecs.txt' param.fname_mask = path_sct_data+'/dmri/dmri.nii.gz' param.remove_tmp_files = 0 param.verbose = 1 param.run_eddy = 0 param.otsu = 0 param.group_size = 5 param.iterative_averaging = 1 else: # Check input parameters try: opts, args = getopt.getopt(sys.argv[1:], 'hi:a:b:e:f:g:m:o:p:r:t:v:x:') except getopt.GetoptError: usage() if not opts: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ('-a'): param.fname_bvals = arg elif opt in ('-b'): param.fname_bvecs = arg elif opt in ('-e'): param.run_eddy = int(arg) elif opt in ('-f'): param.spline_fitting = int(arg) elif opt in ('-g'): param.group_size = int(arg) elif opt in ('-i'): param.fname_data = arg elif opt in ('-m'): param.fname_mask = arg elif opt in ('-o'): path_out = arg elif opt in ('-p'): param_user = arg elif opt in ('-r'): param.remove_tmp_files = int(arg) elif opt in ('-t'): param.otsu = int(arg) elif opt in ('-v'): param.verbose = int(arg) elif opt in ('-x'): param.interp = arg # display usage if a mandatory argument is not provided if param.fname_data == '' or param.fname_bvecs == '': sct.printv('ERROR: All mandatory arguments are not provided. See usage.', 1, 'error') usage() # parse argument for param if not param_user == '': param.param = param_user.replace(' ', '').split(',') # remove spaces and parse with comma # TODO: check integrity of input # param.param = [i for i in range(len(param_user))] del param_user sct.printv('\nInput parameters:', param.verbose) sct.printv(' input file ............'+param.fname_data, param.verbose) sct.printv(' bvecs file ............'+param.fname_bvecs, param.verbose) sct.printv(' bvals file ............'+param.fname_bvals, param.verbose) sct.printv(' mask file .............'+param.fname_mask, param.verbose) # check existence of input files sct.printv('\nCheck file existence...', param.verbose) sct.check_file_exist(param.fname_data, param.verbose) sct.check_file_exist(param.fname_bvecs, param.verbose) if not param.fname_bvals == '': sct.check_file_exist(param.fname_bvals, param.verbose) if not param.fname_mask == '': sct.check_file_exist(param.fname_mask, param.verbose) # Get full path param.fname_data = os.path.abspath(param.fname_data) param.fname_bvecs = os.path.abspath(param.fname_bvecs) if param.fname_bvals != '': param.fname_bvals = os.path.abspath(param.fname_bvals) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) path_mask, file_mask, ext_mask = sct.extract_fname(param.fname_mask) # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+path_tmp, param.verbose) # Copying input data to tmp folder # NB: cannot use c3d here because c3d cannot convert 4D data. sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) sct.run('cp '+param.fname_data+' '+path_tmp+'dmri'+ext_data, param.verbose) sct.run('cp '+param.fname_bvecs+' '+path_tmp+'bvecs.txt', param.verbose) if param.fname_mask != '': sct.run('cp '+param.fname_mask+' '+path_tmp+'mask'+ext_mask, param.verbose) # go to tmp folder os.chdir(path_tmp) # convert dmri to nii format convert('dmri'+ext_data, 'dmri.nii') # update field in param (because used later). # TODO: make this cleaner... if param.fname_mask != '': param.fname_mask = 'mask'+ext_mask # run moco dmri_moco(param) # come back to parent folder os.chdir('..') # Generate output files path_out = sct.slash_at_the_end(path_out, 1) sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(path_tmp+'dmri'+param.suffix+'.nii', path_out+file_data+param.suffix+ext_data, param.verbose) sct.generate_output_file(path_tmp+'b0_mean.nii', path_out+'b0'+param.suffix+'_mean'+ext_data, param.verbose) sct.generate_output_file(path_tmp+'dwi_mean.nii', path_out+'dwi'+param.suffix+'_mean'+ext_data, param.verbose) # Delete temporary files if param.remove_tmp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.run('rm -rf '+path_tmp, param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: '+str(int(round(elapsed_time)))+'s', param.verbose) #To view results sct.printv('\nTo view results, type:', param.verbose) sct.printv('fslview -m ortho,ortho '+param.path_out+file_data+param.suffix+' '+file_data+' &\n', param.verbose, 'info')
def moco(param): """ Main function that performs motion correction. :param param: :return: """ # retrieve parameters file_data = param.file_data file_target = param.file_target folder_mat = param.mat_moco # output folder of mat file todo = param.todo suffix = param.suffix verbose = param.verbose # other parameters file_mask = 'mask.nii' printv('\nInput parameters:', param.verbose) printv(' Input file ............ ' + file_data, param.verbose) printv(' Reference file ........ ' + file_target, param.verbose) printv(' Polynomial degree ..... ' + param.poly, param.verbose) printv(' Smoothing kernel ...... ' + param.smooth, param.verbose) printv(' Gradient step ......... ' + param.gradStep, param.verbose) printv(' Metric ................ ' + param.metric, param.verbose) printv(' Sampling .............. ' + param.sampling, param.verbose) printv(' Todo .................. ' + todo, param.verbose) printv(' Mask ................. ' + param.fname_mask, param.verbose) printv(' Output mat folder ..... ' + folder_mat, param.verbose) try: os.makedirs(folder_mat) except FileExistsError: pass # Get size of data printv('\nData dimensions:', verbose) im_data = Image(param.file_data) nx, ny, nz, nt, px, py, pz, pt = im_data.dim printv( (' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt)), verbose) # copy file_target to a temporary file printv('\nCopy file_target to a temporary file...', verbose) file_target = "target.nii.gz" convert(param.file_target, file_target, verbose=0) # Check if user specified a mask if not param.fname_mask == '': # Check if this mask is soft (i.e., non-binary, such as a Gaussian mask) im_mask = Image(param.fname_mask) if not np.array_equal(im_mask.data, im_mask.data.astype(bool)): # If it is a soft mask, multiply the target by the soft mask. im = Image(file_target) im_masked = im.copy() im_masked.data = im.data * im_mask.data im_masked.save( verbose=0) # silence warning about file overwritting # If scan is sagittal, split src and target along Z (slice) if param.is_sagittal: dim_sag = 2 # TODO: find it # z-split data (time series) im_z_list = split_data(im_data, dim=dim_sag, squeeze_data=False) file_data_splitZ = [] for im_z in im_z_list: im_z.save(verbose=0) file_data_splitZ.append(im_z.absolutepath) # z-split target im_targetz_list = split_data(Image(file_target), dim=dim_sag, squeeze_data=False) file_target_splitZ = [] for im_targetz in im_targetz_list: im_targetz.save(verbose=0) file_target_splitZ.append(im_targetz.absolutepath) # z-split mask (if exists) if not param.fname_mask == '': im_maskz_list = split_data(Image(file_mask), dim=dim_sag, squeeze_data=False) file_mask_splitZ = [] for im_maskz in im_maskz_list: im_maskz.save(verbose=0) file_mask_splitZ.append(im_maskz.absolutepath) # initialize file list for output matrices file_mat = np.empty((nz, nt), dtype=object) # axial orientation else: file_data_splitZ = [file_data] # TODO: make it absolute like above file_target_splitZ = [file_target] # TODO: make it absolute like above # initialize file list for output matrices file_mat = np.empty((1, nt), dtype=object) # deal with mask if not param.fname_mask == '': convert(param.fname_mask, file_mask, squeeze_data=False, verbose=0) im_maskz_list = [Image(file_mask) ] # use a list with single element # Loop across file list, where each file is either a 2D volume (if sagittal) or a 3D volume (otherwise) # file_mat = tuple([[[] for i in range(nt)] for i in range(nz)]) file_data_splitZ_moco = [] printv( '\nRegister. Loop across Z (note: there is only one Z if orientation is axial)' ) for file in file_data_splitZ: iz = file_data_splitZ.index(file) # Split data along T dimension # printv('\nSplit data along T dimension.', verbose) im_z = Image(file) list_im_zt = split_data(im_z, dim=3) file_data_splitZ_splitT = [] for im_zt in list_im_zt: im_zt.save(verbose=0) file_data_splitZ_splitT.append(im_zt.absolutepath) # file_data_splitT = file_data + '_T' # Motion correction: initialization index = np.arange(nt) file_data_splitT_num = [] file_data_splitZ_splitT_moco = [] failed_transfo = [0 for i in range(nt)] # Motion correction: Loop across T for indice_index in sct_progress_bar(range(nt), unit='iter', unit_scale=False, desc="Z=" + str(iz) + "/" + str(len(file_data_splitZ) - 1), ascii=False, ncols=80): # create indices and display stuff it = index[indice_index] file_mat[iz][it] = os.path.join( folder_mat, "mat.Z") + str(iz).zfill(4) + 'T' + str(it).zfill(4) file_data_splitZ_splitT_moco.append( add_suffix(file_data_splitZ_splitT[it], '_moco')) # deal with masking (except in the 'apply' case, where masking is irrelevant) input_mask = None if not param.fname_mask == '' and not param.todo == 'apply': # Check if mask is binary if np.array_equal(im_maskz_list[iz].data, im_maskz_list[iz].data.astype(bool)): # If it is, pass this mask into register() to be used input_mask = im_maskz_list[iz] else: # If not, do not pass this mask into register() because ANTs cannot handle non-binary masks. # Instead, multiply the input data by the Gaussian mask. im = Image(file_data_splitZ_splitT[it]) im_masked = im.copy() im_masked.data = im.data * im_maskz_list[iz].data im_masked.save( verbose=0) # silence warning about file overwritting # run 3D registration failed_transfo[it] = register(param, file_data_splitZ_splitT[it], file_target_splitZ[iz], file_mat[iz][it], file_data_splitZ_splitT_moco[it], im_mask=input_mask) # average registered volume with target image # N.B. use weighted averaging: (target * nb_it + moco) / (nb_it + 1) if param.iterAvg and indice_index < 10 and failed_transfo[ it] == 0 and not param.todo == 'apply': im_targetz = Image(file_target_splitZ[iz]) data_targetz = im_targetz.data data_mocoz = Image(file_data_splitZ_splitT_moco[it]).data data_targetz = (data_targetz * (indice_index + 1) + data_mocoz) / (indice_index + 2) im_targetz.data = data_targetz im_targetz.save(verbose=0) # Replace failed transformation with the closest good one fT = [i for i, j in enumerate(failed_transfo) if j == 1] gT = [i for i, j in enumerate(failed_transfo) if j == 0] for it in range(len(fT)): abs_dist = [np.abs(gT[i] - fT[it]) for i in range(len(gT))] if not abs_dist == []: index_good = abs_dist.index(min(abs_dist)) printv( ' transfo #' + str(fT[it]) + ' --> use transfo #' + str(gT[index_good]), verbose) # copy transformation copy(file_mat[iz][gT[index_good]] + 'Warp.nii.gz', file_mat[iz][fT[it]] + 'Warp.nii.gz') # apply transformation sct_apply_transfo.main(args=[ '-i', file_data_splitZ_splitT[fT[it]], '-d', file_target, '-w', file_mat[iz][fT[it]] + 'Warp.nii.gz', '-o', file_data_splitZ_splitT_moco[fT[it]], '-x', param.interp ]) else: # exit program if no transformation exists. printv( '\nERROR in ' + os.path.basename(__file__) + ': No good transformation exist. Exit program.\n', verbose, 'error') sys.exit(2) # Merge data along T file_data_splitZ_moco.append(add_suffix(file, suffix)) if todo != 'estimate': im_out = concat_data(file_data_splitZ_splitT_moco, 3) im_out.absolutepath = file_data_splitZ_moco[iz] im_out.save(verbose=0) # If sagittal, merge along Z if param.is_sagittal: # TODO: im_out.dim is incorrect: Z value is one im_out = concat_data(file_data_splitZ_moco, 2) dirname, basename, ext = extract_fname(file_data) path_out = os.path.join(dirname, basename + suffix + ext) im_out.absolutepath = path_out im_out.save(verbose=0) return file_mat, im_out
def main(args=None): # initialization start_time = time.time() param = Param() # check user arguments if not args: args = sys.argv[1:] # Get parser info parser = get_parser() arguments = parser.parse(sys.argv[1:]) param.fname_data = arguments['-i'] if '-g' in arguments: param.group_size = arguments['-g'] if '-m' in arguments: param.fname_mask = arguments['-m'] if '-param' in arguments: param.update(arguments['-param']) if '-x' in arguments: param.interp = arguments['-x'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-r' in arguments: param.remove_temp_files = int(arguments['-r']) param.verbose = int(arguments.get('-v')) sct.init_sct(log_level=param.verbose, update=True) # Update log level sct.printv('\nInput parameters:', param.verbose) sct.printv(' input file ............' + param.fname_data, param.verbose) # Get full path param.fname_data = os.path.abspath(param.fname_data) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) path_tmp = sct.tmp_create(basename="fmri_moco", verbose=param.verbose) # Copying input data to tmp folder and convert to nii # TODO: no need to do that (takes time for nothing) sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, os.path.join(path_tmp, "fmri.nii"), squeeze_data=False) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # run moco fmri_moco(param) # come back os.chdir(curdir) # Generate output files fname_fmri_moco = os.path.join(path_out, file_data + param.suffix + ext_data) sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(os.path.join(path_tmp, "fmri" + param.suffix + '.nii'), fname_fmri_moco, param.verbose) sct.generate_output_file(os.path.join(path_tmp, "fmri" + param.suffix + '_mean.nii'), os.path.join(path_out, file_data + param.suffix + '_mean' + ext_data), param.verbose) # Delete temporary files if param.remove_temp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.rmtree(path_tmp, verbose=param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's', param.verbose) sct.display_viewer_syntax([fname_fmri_moco, file_data], mode='ortho,ortho')
def main(): # Initialization fname_data = '' interp_factor = param.interp_factor remove_temp_files = param.remove_temp_files verbose = param.verbose suffix = param.suffix smoothing_sigma = param.smoothing_sigma # start timer start_time = time.time() # get path of the toolbox status, path_sct = commands.getstatusoutput('echo $SCT_DIR') # Parameters for debug mode if param.debug: fname_data = path_sct + '/testing/data/errsm_23/t2/t2_manual_segmentation.nii.gz' remove_temp_files = 0 param.mask_size = 10 else: # Check input parameters try: opts, args = getopt.getopt(sys.argv[1:], 'hi:v:r:s:') except getopt.GetoptError: usage() if not opts: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ('-i'): fname_data = arg elif opt in ('-r'): remove_temp_files = int(arg) elif opt in ('-s'): smoothing_sigma = arg elif opt in ('-v'): verbose = int(arg) # display usage if a mandatory argument is not provided if fname_data == '': usage() # sct.printv(arguments) sct.printv('\nCheck parameters:') sct.printv(' segmentation ........... ' + fname_data) sct.printv(' interp factor .......... ' + str(interp_factor)) sct.printv(' smoothing sigma ........ ' + str(smoothing_sigma)) # check existence of input files sct.printv('\nCheck existence of input files...') sct.check_file_exist(fname_data, verbose) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(fname_data) # create temporary folder sct.printv('\nCreate temporary folder...') path_tmp = 'tmp.' + time.strftime("%y%m%d%H%M%S") sct.run('mkdir ' + path_tmp) from sct_convert import convert sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(fname_data, path_tmp + '/data.nii') # go to tmp folder os.chdir(path_tmp) # Get dimensions of data sct.printv('\nGet dimensions of data...', verbose) nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim sct.printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), verbose) # upsample data sct.printv('\nUpsample data...', verbose) sct.run( 'sct_resample -i data.nii -x linear -vox ' + str(nx * interp_factor) + 'x' + str(ny * interp_factor) + 'x' + str(nz * interp_factor) + ' -o data_up.nii', verbose) # Smooth along centerline sct.printv('\nSmooth along centerline...', verbose) sct.run( 'sct_smooth_spinalcord -i data_up.nii -s data_up.nii' + ' -smooth ' + str(smoothing_sigma) + ' -r ' + str(remove_temp_files) + ' -v ' + str(verbose), verbose) # downsample data sct.printv('\nDownsample data...', verbose) sct.run( 'sct_resample -i data_up_smooth.nii -x linear -vox ' + str(nx) + 'x' + str(ny) + 'x' + str(nz) + ' -o data_up_smooth_down.nii', verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...') fname_out = sct.generate_output_file(path_tmp + '/data_up_smooth_down.nii', '' + file_data + suffix + ext_data) # Delete temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...') sct.run('rm -rf ' + path_tmp) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's') # to view results sct.printv('\nTo view results, type:') sct.printv('fslview ' + file_data + ' ' + file_data + suffix + ' &\n')
def moco_wrapper(param): """ Wrapper that performs motion correction. :param param: ParamMoco class :return: None """ file_data = 'data.nii' # corresponds to the full input data (e.g. dmri or fmri) file_data_dirname, file_data_basename, file_data_ext = extract_fname( file_data) file_b0 = 'b0.nii' file_datasub = 'datasub.nii' # corresponds to the full input data minus the b=0 scans (if param.is_diffusion=True) file_datasubgroup = 'datasub-groups.nii' # concatenation of the average of each file_datasub file_mask = 'mask.nii' file_moco_params_csv = 'moco_params.tsv' file_moco_params_x = 'moco_params_x.nii.gz' file_moco_params_y = 'moco_params_y.nii.gz' ext_data = '.nii.gz' # workaround "too many open files" by slurping the data # TODO: check if .nii can be used mat_final = 'mat_final/' # ext_mat = 'Warp.nii.gz' # warping field # Start timer start_time = time.time() printv('\nInput parameters:', param.verbose) printv(' Input file ............ ' + param.fname_data, param.verbose) printv(' Group size ............ {}'.format(param.group_size), param.verbose) # Get full path # param.fname_data = os.path.abspath(param.fname_data) # param.fname_bvecs = os.path.abspath(param.fname_bvecs) # if param.fname_bvals != '': # param.fname_bvals = os.path.abspath(param.fname_bvals) # Extract path, file and extension # path_data, file_data, ext_data = extract_fname(param.fname_data) # path_mask, file_mask, ext_mask = extract_fname(param.fname_mask) path_tmp = tmp_create(basename="moco") # Copying input data to tmp folder printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, os.path.join(path_tmp, file_data)) if param.fname_mask != '': convert(param.fname_mask, os.path.join(path_tmp, file_mask), verbose=param.verbose) # Update field in param (because used later in another function, and param class will be passed) param.fname_mask = file_mask # Build absolute output path and go to tmp folder curdir = os.getcwd() path_out_abs = os.path.abspath(param.path_out) os.chdir(path_tmp) # Get dimensions of data printv('\nGet dimensions of data...', param.verbose) im_data = Image(file_data) nx, ny, nz, nt, px, py, pz, pt = im_data.dim printv(' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), param.verbose) # Get orientation printv('\nData orientation: ' + im_data.orientation, param.verbose) if im_data.orientation[2] in 'LR': param.is_sagittal = True printv(' Treated as sagittal') elif im_data.orientation[2] in 'IS': param.is_sagittal = False printv(' Treated as axial') else: param.is_sagittal = False printv( 'WARNING: Orientation seems to be neither axial nor sagittal. Treated as axial.' ) printv( "\nSet suffix of transformation file name, which depends on the orientation:" ) if param.is_sagittal: param.suffix_mat = '0GenericAffine.mat' printv( "Orientation is sagittal, suffix is '{}'. The image is split across the R-L direction, and the " "estimated transformation is a 2D affine transfo.".format( param.suffix_mat)) else: param.suffix_mat = 'Warp.nii.gz' printv( "Orientation is axial, suffix is '{}'. The estimated transformation is a 3D warping field, which is " "composed of a stack of 2D Tx-Ty transformations".format( param.suffix_mat)) # Adjust group size in case of sagittal scan if param.is_sagittal and param.group_size != 1: printv( 'For sagittal data group_size should be one for more robustness. Forcing group_size=1.', 1, 'warning') param.group_size = 1 if param.is_diffusion: # Identify b=0 and DWI images index_b0, index_dwi, nb_b0, nb_dwi = \ sct_dmri_separate_b0_and_dwi.identify_b0(param.fname_bvecs, param.fname_bvals, param.bval_min, param.verbose) # check if dmri and bvecs are the same size if not nb_b0 + nb_dwi == nt: printv( '\nERROR in ' + os.path.basename(__file__) + ': Size of data (' + str(nt) + ') and size of bvecs (' + str(nb_b0 + nb_dwi) + ') are not the same. Check your bvecs file.\n', 1, 'error') sys.exit(2) # ================================================================================================================== # Prepare data (mean/groups...) # ================================================================================================================== # Split into T dimension printv('\nSplit along T dimension...', param.verbose) im_data_split_list = split_data(im_data, 3) for im in im_data_split_list: x_dirname, x_basename, x_ext = extract_fname(im.absolutepath) im.absolutepath = os.path.join(x_dirname, x_basename + ".nii.gz") im.save() if param.is_diffusion: # Merge and average b=0 images printv('\nMerge and average b=0 data...', param.verbose) im_b0_list = [] for it in range(nb_b0): im_b0_list.append(im_data_split_list[index_b0[it]]) im_b0 = concat_data(im_b0_list, 3).save(file_b0, verbose=0) # Average across time im_b0.mean(dim=3).save(add_suffix(file_b0, '_mean')) n_moco = nb_dwi # set number of data to perform moco on (using grouping) index_moco = index_dwi # If not a diffusion scan, we will motion-correct all volumes else: n_moco = nt index_moco = list(range(0, nt)) nb_groups = int(math.floor(n_moco / param.group_size)) # Generate groups indexes group_indexes = [] for iGroup in range(nb_groups): group_indexes.append(index_moco[(iGroup * param.group_size):((iGroup + 1) * param.group_size)]) # add the remaining images to a new last group (in case the total number of image is not divisible by group_size) nb_remaining = n_moco % param.group_size # number of remaining images if nb_remaining > 0: nb_groups += 1 group_indexes.append(index_moco[len(index_moco) - nb_remaining:len(index_moco)]) _, file_dwi_basename, file_dwi_ext = extract_fname(file_datasub) # Group data list_file_group = [] for iGroup in sct_progress_bar(range(nb_groups), unit='iter', unit_scale=False, desc="Merge within groups", ascii=False, ncols=80): # get index index_moco_i = group_indexes[iGroup] n_moco_i = len(index_moco_i) # concatenate images across time, within this group file_dwi_merge_i = os.path.join(file_dwi_basename + '_' + str(iGroup) + ext_data) im_dwi_list = [] for it in range(n_moco_i): im_dwi_list.append(im_data_split_list[index_moco_i[it]]) im_dwi_out = concat_data(im_dwi_list, 3).save(file_dwi_merge_i, verbose=0) # Average across time list_file_group.append( os.path.join(file_dwi_basename + '_' + str(iGroup) + '_mean' + ext_data)) im_dwi_out.mean(dim=3).save(list_file_group[-1]) # Merge across groups printv('\nMerge across groups...', param.verbose) # file_dwi_groups_means_merge = 'dwi_averaged_groups' im_dw_list = [] for iGroup in range(nb_groups): im_dw_list.append(list_file_group[iGroup]) concat_data(im_dw_list, 3).save(file_datasubgroup, verbose=0) # Cleanup del im, im_data_split_list # ================================================================================================================== # Estimate moco # ================================================================================================================== # Initialize another class instance that will be passed on to the moco() function param_moco = deepcopy(param) if param.is_diffusion: # Estimate moco on b0 groups printv( '\n-------------------------------------------------------------------------------', param.verbose) printv(' Estimating motion on b=0 images...', param.verbose) printv( '-------------------------------------------------------------------------------', param.verbose) param_moco.file_data = 'b0.nii' # Identify target image if index_moco[0] != 0: # If first DWI is not the first volume (most common), then there is a least one b=0 image before. In that # case select it as the target image for registration of all b=0 param_moco.file_target = os.path.join( file_data_dirname, file_data_basename + '_T' + str(index_b0[index_moco[0] - 1]).zfill(4) + ext_data) else: # If first DWI is the first volume, then the target b=0 is the first b=0 from the index_b0. param_moco.file_target = os.path.join( file_data_dirname, file_data_basename + '_T' + str(index_b0[0]).zfill(4) + ext_data) # Run moco param_moco.path_out = '' param_moco.todo = 'estimate_and_apply' param_moco.mat_moco = 'mat_b0groups' file_mat_b0, _ = moco(param_moco) # Estimate moco across groups printv( '\n-------------------------------------------------------------------------------', param.verbose) printv(' Estimating motion across groups...', param.verbose) printv( '-------------------------------------------------------------------------------', param.verbose) param_moco.file_data = file_datasubgroup param_moco.file_target = list_file_group[ 0] # target is the first volume (closest to the first b=0 if DWI scan) param_moco.path_out = '' param_moco.todo = 'estimate_and_apply' param_moco.mat_moco = 'mat_groups' file_mat_datasub_group, _ = moco(param_moco) # Spline Regularization along T if param.spline_fitting: # TODO: fix this scenario (haven't touched that code for a while-- it is probably buggy) raise NotImplementedError() # spline(mat_final, nt, nz, param.verbose, np.array(index_b0), param.plot_graph) # ================================================================================================================== # Apply moco # ================================================================================================================== # If group_size>1, assign transformation to each individual ungrouped 3d volume if param.group_size > 1: file_mat_datasub = [] for iz in range(len(file_mat_datasub_group)): # duplicate by factor group_size the transformation file for each it # example: [mat.Z0000T0001Warp.nii] --> [mat.Z0000T0001Warp.nii, mat.Z0000T0001Warp.nii] for group_size=2 file_mat_datasub.append( functools.reduce(operator.iconcat, [[i] * param.group_size for i in file_mat_datasub_group[iz]], [])) else: file_mat_datasub = file_mat_datasub_group # Copy transformations to mat_final folder and rename them appropriately copy_mat_files(nt, file_mat_datasub, index_moco, mat_final, param) if param.is_diffusion: copy_mat_files(nt, file_mat_b0, index_b0, mat_final, param) # Apply moco on all dmri data printv( '\n-------------------------------------------------------------------------------', param.verbose) printv(' Apply moco', param.verbose) printv( '-------------------------------------------------------------------------------', param.verbose) param_moco.file_data = file_data param_moco.file_target = list_file_group[ 0] # reference for reslicing into proper coordinate system param_moco.path_out = '' # TODO not used in moco() param_moco.mat_moco = mat_final param_moco.todo = 'apply' file_mat_data, im_moco = moco(param_moco) # copy geometric information from header # NB: this is required because WarpImageMultiTransform in 2D mode wrongly sets pixdim(3) to "1". im_moco.header = im_data.header im_moco.save(verbose=0) # Average across time if param.is_diffusion: # generate b0_moco_mean and dwi_moco_mean args = [ '-i', im_moco.absolutepath, '-bvec', param.fname_bvecs, '-a', '1', '-v', '0' ] if not param.fname_bvals == '': # if bvals file is provided args += ['-bval', param.fname_bvals] fname_b0, fname_b0_mean, fname_dwi, fname_dwi_mean = sct_dmri_separate_b0_and_dwi.main( args=args) else: fname_moco_mean = add_suffix(im_moco.absolutepath, '_mean') im_moco.mean(dim=3).save(fname_moco_mean) # Extract and output the motion parameters (doesn't work for sagittal orientation) printv('Extract motion parameters...') if param.output_motion_param: if param.is_sagittal: printv( 'Motion parameters cannot be generated for sagittal images.', 1, 'warning') else: files_warp_X, files_warp_Y = [], [] moco_param = [] for fname_warp in file_mat_data[0]: # Cropping the image to keep only one voxel in the XY plane im_warp = Image(fname_warp + param.suffix_mat) im_warp.data = np.expand_dims(np.expand_dims( im_warp.data[0, 0, :, :, :], axis=0), axis=0) # These three lines allow to generate one file instead of two, containing X, Y and Z moco parameters #fname_warp_crop = fname_warp + '_crop_' + ext_mat # files_warp.append(fname_warp_crop) # im_warp.save(fname_warp_crop) # Separating the three components and saving X and Y only (Z is equal to 0 by default). im_warp_XYZ = multicomponent_split(im_warp) fname_warp_crop_X = fname_warp + '_crop_X_' + param.suffix_mat im_warp_XYZ[0].save(fname_warp_crop_X) files_warp_X.append(fname_warp_crop_X) fname_warp_crop_Y = fname_warp + '_crop_Y_' + param.suffix_mat im_warp_XYZ[1].save(fname_warp_crop_Y) files_warp_Y.append(fname_warp_crop_Y) # Calculating the slice-wise average moco estimate to provide a QC file moco_param.append([ np.mean(np.ravel(im_warp_XYZ[0].data)), np.mean(np.ravel(im_warp_XYZ[1].data)) ]) # These two lines allow to generate one file instead of two, containing X, Y and Z moco parameters #im_warp_concat = concat_data(files_warp, dim=3) # im_warp_concat.save('fmri_moco_params.nii') # Concatenating the moco parameters into a time series for X and Y components. im_warp_concat = concat_data(files_warp_X, dim=3) im_warp_concat.save(file_moco_params_x) im_warp_concat = concat_data(files_warp_Y, dim=3) im_warp_concat.save(file_moco_params_y) # Writing a TSV file with the slicewise average estimate of the moco parameters. Useful for QC with open(file_moco_params_csv, 'wt') as out_file: tsv_writer = csv.writer(out_file, delimiter='\t') tsv_writer.writerow(['X', 'Y']) for mocop in moco_param: tsv_writer.writerow([mocop[0], mocop[1]]) # Generate output files printv('\nGenerate output files...', param.verbose) fname_moco = os.path.join( path_out_abs, add_suffix(os.path.basename(param.fname_data), param.suffix)) generate_output_file(im_moco.absolutepath, fname_moco) if param.is_diffusion: generate_output_file(fname_b0_mean, add_suffix(fname_moco, '_b0_mean')) generate_output_file(fname_dwi_mean, add_suffix(fname_moco, '_dwi_mean')) else: generate_output_file(fname_moco_mean, add_suffix(fname_moco, '_mean')) if os.path.exists(file_moco_params_csv): generate_output_file(file_moco_params_x, os.path.join(path_out_abs, file_moco_params_x), squeeze_data=False) generate_output_file(file_moco_params_y, os.path.join(path_out_abs, file_moco_params_y), squeeze_data=False) generate_output_file(file_moco_params_csv, os.path.join(path_out_abs, file_moco_params_csv)) # Delete temporary files if param.remove_temp_files == 1: printv('\nDelete temporary files...', param.verbose) rmtree(path_tmp, verbose=param.verbose) # come back to working directory os.chdir(curdir) # display elapsed time elapsed_time = time.time() - start_time printv( '\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's', param.verbose) display_viewer_syntax([ os.path.join( param.path_out, add_suffix(os.path.basename(param.fname_data), param.suffix)), param.fname_data ], mode='ortho,ortho')
def execute(self): print 'Execution of the SCAD algorithm in '+str(os.getcwd()) original_name = self.input_image.file_name vesselness_file_name = "imageVesselNessFilter.nii.gz" raw_file_name = "raw.nii" self.setup_debug_folder() if self.debug: import matplotlib.pyplot as plt # import for debug purposes # create tmp and copy input path_tmp = self.create_temporary_path() conv.convert(self.input_image.absolutepath, path_tmp+raw_file_name) if self.vesselness_provided: sct.run('cp '+vesselness_file_name+' '+path_tmp+vesselness_file_name) os.chdir(path_tmp) # get input image information img = Image(raw_file_name) # save original orientation and change image to RPI self.raw_orientation = img.change_orientation() # get body symmetry if self.enable_symmetry: from msct_image import change_data_orientation sym = SymmetryDetector(raw_file_name, self.contrast, crop_xy=0) self.raw_symmetry = sym.execute() img.change_orientation(self.raw_orientation) self.output_debug_file(img, self.raw_symmetry, "body_symmetry") img.change_orientation() # vesselness filter if not self.vesselness_provided: sct.run('sct_vesselness -i '+raw_file_name+' -t ' + self._contrast+" -radius "+str(self.spinalcord_radius)) # load vesselness filter data and perform minimum path on it img = Image(vesselness_file_name) img.change_orientation() self.minimum_path_data, self.J1_min_path, self.J2_min_path = get_minimum_path(img.data, invert=1, debug=1) self.output_debug_file(img, self.minimum_path_data, "minimal_path") self.output_debug_file(img, self.J1_min_path, "J1_minimal_path") self.output_debug_file(img, self.J2_min_path, "J2_minimal_path") # Apply an exponent to the minimum path self.minimum_path_powered = np.power(self.minimum_path_data, self.minimum_path_exponent) self.output_debug_file(img, self.minimum_path_powered, "minimal_path_power_"+str(self.minimum_path_exponent)) # Saving in Image since smooth_minimal_path needs pixel dimensions img.data = self.minimum_path_powered # smooth resulting minimal path self.smoothed_min_path = smooth_minimal_path(img) self.output_debug_file(img, self.smoothed_min_path.data, "minimal_path_smooth") # normalise symmetry values between 0 and 1 if self.enable_symmetry: normalised_symmetry = normalize_array_histogram(self.raw_symmetry) self.output_debug_file(img, self.smoothed_min_path.data, "minimal_path_smooth") # multiply normalised symmetry data with the minimum path result from msct_image import change_data_orientation self.spine_detect_data = np.multiply(self.smoothed_min_path.data, change_data_orientation(np.power(normalised_symmetry, self.symmetry_exponent), self.raw_orientation, "RPI")) self.output_debug_file(img, self.spine_detect_data, "symmetry_x_min_path") # extract the centerline from the minimal path image self.centerline_with_outliers = get_centerline(self.spine_detect_data, self.spine_detect_data.shape) else: # extract the centerline from the minimal path image self.centerline_with_outliers = get_centerline(self.smoothed_min_path.data, self.smoothed_min_path.data.shape) self.output_debug_file(img, self.centerline_with_outliers, "centerline_with_outliers") # saving centerline with outliers to have img.data = self.centerline_with_outliers img.change_orientation() img.file_name = "centerline_with_outliers" img.save() # use a b-spline to smooth out the centerline x, y, z, dx, dy, dz = smooth_centerline("centerline_with_outliers.nii.gz") # save the centerline nx, ny, nz, nt, px, py, pz, pt = img.dim img.data = np.zeros((nx, ny, nz)) for i in range(0, np.size(x)-1): img.data[int(x[i]), int(y[i]), int(z[i])] = 1 self.output_debug_file(img, img.data, "centerline") img.change_orientation(self.raw_orientation) img.file_name = "centerline" img.save() # copy back centerline os.chdir('../') conv.convert(path_tmp+img.file_name+img.ext, self.output_filename) if self.rm_tmp_file == 1: import shutil shutil.rmtree(path_tmp)
def generate_output_file(fname_in, fname_out, squeeze_data=True, verbose=1): """ Copy fname_in to fname_out with a few convenient checks: make sure input file exists, if fname_out exists send a warning, if input and output NIFTI format are different (nii vs. nii.gz) convert by unzipping or zipping, and display nice message at the end. :param fname_in: :param fname_out: :param verbose: :return: fname_out """ from sct_convert import convert path_in, file_in, ext_in = extract_fname(fname_in) path_out, file_out, ext_out = extract_fname(fname_out) # create output path (ignore if it already exists) pathlib.Path(path_out).mkdir(parents=True, exist_ok=True) # if input image does not exist, give error if not os.path.isfile(fname_in): printv( ' ERROR: File ' + fname_in + ' is not a regular file. Exit program.', 1, 'error') sys.exit(2) # if input and output fnames are the same, do nothing and exit function if fname_in == fname_out: printv(' WARNING: fname_in and fname_out are the same. Do nothing.', verbose, 'warning') printv(' File created: ' + os.path.join(path_out, file_out + ext_out)) return os.path.join(path_out, file_out + ext_out) # if fname_out already exists in nii or nii.gz format if os.path.isfile(os.path.join(path_out, file_out + ext_out)): printv( ' WARNING: File ' + os.path.join(path_out, file_out + ext_out) + ' already exists. Deleting it...', 1, 'warning') os.remove(os.path.join(path_out, file_out + ext_out)) if ext_in != ext_out: # Generate output file ''' # TRY TO UNCOMMENT THIS LINES AND RUN IT IN AN OTHER STATION THAN EVANS (testing of sct_label_vertebrae and sct_smooth_spinalcord never stops with this lines on evans) if ext_in == '.nii.gz' and ext_out == '.nii': # added to resolve issue #728 run('gunzip -f ' + fname_in) os.rename(os.path.join(path_in, file_in + '.nii'), fname_out) else: ''' convert(fname_in, fname_out, squeeze_data=squeeze_data, verbose=0) else: # Generate output file without changing the extension shutil.move(fname_in, fname_out) # # Move file to output folder (keep the same extension as input) # shutil.move(fname_in, path_out+file_out+ext_in) # # convert to nii (only if necessary) # if ext_out == '.nii' and ext_in != '.nii': # convert(os.path.join(path_out, file_out+ext_in), os.path.join(path_out, file_out+ext_out)) # os.remove(os.path.join(path_out, file_out+ext_in)) # remove nii.gz file # # convert to nii.gz (only if necessary) # if ext_out == '.nii.gz' and ext_in != '.nii.gz': # convert(os.path.join(path_out, file_out+ext_in), os.path.join(path_out, file_out+ext_out)) # os.remove(os.path.join(path_out, file_out+ext_in)) # remove nii file # display message printv(' File created: ' + os.path.join(path_out, file_out + ext_out), verbose) # if verbose: # printv(' File created: '+ os.path.join(path_out, file_out+ext_out)) return os.path.join(path_out, file_out + ext_out)
def create_mask(): fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI # parse argument for method method_type = param.process[0] # check method val if not method_type == 'center': method_val = param.process[1] # check existence of input files if method_type == 'centerline': sct.check_file_exist(method_val, param.verbose) # check if orientation is RPI sct.printv('\nCheck if orientation is RPI...', param.verbose) ori = get_orientation(param.fname_data, filename=True) if not ori == 'RPI': sct.printv('\nERROR in '+os.path.basename(__file__)+': Orientation of input image should be RPI. Use sct_image -setorient to put your image in RPI.\n', 1, 'error') # Extract path/file/extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) # Get output folder and file name if param.fname_out == '': param.fname_out = param.file_prefix+file_data+ext_data #fname_out = os.path.abspath(path_out+file_out+ext_out) # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+path_tmp, param.verbose) # Copying input data to tmp folder and convert to nii sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, path_tmp+'data.nii') # sct.run('cp '+param.fname_data+' '+path_tmp+'data'+ext_data, param.verbose) if method_type == 'centerline': convert(method_val, path_tmp+'centerline.nii.gz') # go to tmp folder os.chdir(path_tmp) # Get dimensions of data sct.printv('\nGet dimensions of data...', param.verbose) nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim sct.printv(' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz)+ ' x ' + str(nt), param.verbose) # in case user input 4d data if nt != 1: sct.printv('WARNING in '+os.path.basename(__file__)+': Input image is 4d but output mask will 3D.', param.verbose, 'warning') # extract first volume to have 3d reference nii = Image('data.nii') data3d = nii.data[:,:,:,0] nii.data = data3d nii.save() if method_type == 'coord': # parse to get coordinate coord = map(int, method_val.split('x')) if method_type == 'point': # get file name fname_point = method_val # extract coordinate of point sct.printv('\nExtract coordinate of point...', param.verbose) status, output = sct.run('sct_label_utils -i '+fname_point+' -p display-voxel', param.verbose) # parse to get coordinate coord = output[output.find('Position=')+10:-17].split(',') if method_type == 'center': # set coordinate at center of FOV coord = round(float(nx)/2), round(float(ny)/2) if method_type == 'centerline': # get name of centerline from user argument fname_centerline = 'centerline.nii.gz' else: # generate volume with line along Z at coordinates 'coord' sct.printv('\nCreate line...', param.verbose) fname_centerline = create_line('data.nii', coord, nz) # create mask sct.printv('\nCreate mask...', param.verbose) centerline = nibabel.load(fname_centerline) # open centerline hdr = centerline.get_header() # get header hdr.set_data_dtype('uint8') # set imagetype to uint8 data_centerline = centerline.get_data() # get centerline z_centerline = [iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any()] nz = len(z_centerline) # get center of mass of the centerline cx = [0] * nz cy = [0] * nz for iz in range(0, nz, 1): cx[iz], cy[iz] = ndimage.measurements.center_of_mass(numpy.array(data_centerline[:, :, z_centerline[iz]])) # create 2d masks file_mask = 'data_mask' for iz in range(nz): center = numpy.array([cx[iz], cy[iz]]) mask2d = create_mask2d(center, param.shape, param.size, nx, ny, param.even) # Write NIFTI volumes img = nibabel.Nifti1Image(mask2d, None, hdr) nibabel.save(img, (file_mask+str(iz)+'.nii')) # merge along Z # cmd = 'fslmerge -z mask ' im_list = [] for iz in range(nz): im_list.append(Image(file_mask+str(iz)+'.nii')) im_out = concat_data(im_list, 2) im_out.setFileName('mask.nii.gz') im_out.save() # copy geometry im_dat = Image('data.nii') im_mask = Image('mask.nii.gz') im_mask = copy_header(im_dat, im_mask) im_mask.save() # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(path_tmp+'mask.nii.gz', param.fname_out) # Remove temporary files if param.remove_tmp_files == 1: sct.printv('\nRemove temporary files...', param.verbose) sct.run('rm -rf '+path_tmp, param.verbose, error_exit='warning') # to view results sct.printv('\nDone! To view results, type:', param.verbose) sct.printv('fslview '+param.fname_data+' '+param.fname_out+' -l Red -t 0.5 &', param.verbose, 'info') print
def main(args=None): if args is None: args = sys.argv[1:] # initialize parameters param = Param() # Initialization fname_output = '' path_out = '' fname_src_seg = '' fname_dest_seg = '' fname_src_label = '' fname_dest_label = '' generate_warpinv = 1 start_time = time.time() # get path of the toolbox status, path_sct = commands.getstatusoutput('echo $SCT_DIR') # get default registration parameters # step1 = Paramreg(step='1', type='im', algo='syn', metric='MI', iter='5', shrink='1', smooth='0', gradStep='0.5') step0 = Paramreg(step='0', type='im', algo='syn', metric='MI', iter='0', shrink='1', smooth='0', gradStep='0.5', slicewise='0', dof='Tx_Ty_Tz_Rx_Ry_Rz') # only used to put src into dest space step1 = Paramreg(step='1', type='im') paramreg = ParamregMultiStep([step0, step1]) parser = get_parser(paramreg=paramreg) arguments = parser.parse(args) # get arguments fname_src = arguments['-i'] fname_dest = arguments['-d'] if '-iseg' in arguments: fname_src_seg = arguments['-iseg'] if '-dseg' in arguments: fname_dest_seg = arguments['-dseg'] if '-ilabel' in arguments: fname_src_label = arguments['-ilabel'] if '-dlabel' in arguments: fname_dest_label = arguments['-dlabel'] if '-o' in arguments: fname_output = arguments['-o'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-owarp' in arguments: fname_output_warp = arguments['-owarp'] else: fname_output_warp = '' if '-initwarp' in arguments: fname_initwarp = os.path.abspath(arguments['-initwarp']) else: fname_initwarp = '' if '-initwarpinv' in arguments: fname_initwarpinv = os.path.abspath(arguments['-initwarpinv']) else: fname_initwarpinv = '' if '-m' in arguments: fname_mask = arguments['-m'] else: fname_mask = '' padding = arguments['-z'] if "-param" in arguments: paramreg_user = arguments['-param'] # update registration parameters for paramStep in paramreg_user: paramreg.addStep(paramStep) identity = int(arguments['-identity']) interp = arguments['-x'] remove_temp_files = int(arguments['-r']) verbose = int(arguments['-v']) # print arguments print '\nInput parameters:' print ' Source .............. '+fname_src print ' Destination ......... '+fname_dest print ' Init transfo ........ '+fname_initwarp print ' Mask ................ '+fname_mask print ' Output name ......... '+fname_output # print ' Algorithm ........... '+paramreg.algo # print ' Number of iterations '+paramreg.iter # print ' Metric .............. '+paramreg.metric print ' Remove temp files ... '+str(remove_temp_files) print ' Verbose ............. '+str(verbose) # update param param.verbose = verbose param.padding = padding param.fname_mask = fname_mask param.remove_temp_files = remove_temp_files # Get if input is 3D sct.printv('\nCheck if input data are 3D...', verbose) sct.check_if_3d(fname_src) sct.check_if_3d(fname_dest) # Check if user selected type=seg, but did not input segmentation data if 'paramreg_user' in locals(): if True in ['type=seg' in paramreg_user[i] for i in range(len(paramreg_user))]: if fname_src_seg == '' or fname_dest_seg == '': sct.printv('\nERROR: if you select type=seg you must specify -iseg and -dseg flags.\n', 1, 'error') # Extract path, file and extension path_src, file_src, ext_src = sct.extract_fname(fname_src) path_dest, file_dest, ext_dest = sct.extract_fname(fname_dest) # check if source and destination images have the same name (related to issue #373) # If so, change names to avoid conflict of result files and warns the user suffix_src, suffix_dest = '_reg', '_reg' if file_src == file_dest: suffix_src, suffix_dest = '_src_reg', '_dest_reg' # define output folder and file name if fname_output == '': path_out = '' if not path_out else path_out # output in user's current directory file_out = file_src + suffix_src file_out_inv = file_dest + suffix_dest ext_out = ext_src else: path, file_out, ext_out = sct.extract_fname(fname_output) path_out = path if not path_out else path_out file_out_inv = file_out + '_inv' # create QC folder sct.create_folder(param.path_qc) # create temporary folder path_tmp = sct.tmp_create() # copy files to temporary folder from sct_convert import convert sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) convert(fname_src, path_tmp+'src.nii') convert(fname_dest, path_tmp+'dest.nii') if fname_src_seg: convert(fname_src_seg, path_tmp+'src_seg.nii') convert(fname_dest_seg, path_tmp+'dest_seg.nii') if fname_src_label: convert(fname_src_label, path_tmp+'src_label.nii') convert(fname_dest_label, path_tmp+'dest_label.nii') if fname_mask != '': convert(fname_mask, path_tmp+'mask.nii.gz') # go to tmp folder os.chdir(path_tmp) # reorient destination to RPI sct.run('sct_image -i dest.nii -setorient RPI -o dest_RPI.nii') if fname_dest_seg: sct.run('sct_image -i dest_seg.nii -setorient RPI -o dest_seg_RPI.nii') if fname_dest_label: sct.run('sct_image -i dest_label.nii -setorient RPI -o dest_label_RPI.nii') if identity: # overwrite paramreg and only do one identity transformation step0 = Paramreg(step='0', type='im', algo='syn', metric='MI', iter='0', shrink='1', smooth='0', gradStep='0.5') paramreg = ParamregMultiStep([step0]) # Put source into destination space using header (no estimation -- purely based on header) # TODO: Check if necessary to do that # TODO: use that as step=0 # sct.printv('\nPut source into destination space using header...', verbose) # sct.run('isct_antsRegistration -d 3 -t Translation[0] -m MI[dest_pad.nii,src.nii,1,16] -c 0 -f 1 -s 0 -o [regAffine,src_regAffine.nii] -n BSpline[3]', verbose) # if segmentation, also do it for seg # initialize list of warping fields warp_forward = [] warp_inverse = [] # initial warping is specified, update list of warping fields and skip step=0 if fname_initwarp: sct.printv('\nSkip step=0 and replace with initial transformations: ', param.verbose) sct.printv(' '+fname_initwarp, param.verbose) # sct.run('cp '+fname_initwarp+' warp_forward_0.nii.gz', verbose) warp_forward = [fname_initwarp] start_step = 1 if fname_initwarpinv: warp_inverse = [fname_initwarpinv] else: sct.printv('\nWARNING: No initial inverse warping field was specified, therefore the inverse warping field will NOT be generated.', param.verbose, 'warning') generate_warpinv = 0 else: start_step = 0 # loop across registration steps for i_step in range(start_step, len(paramreg.steps)): sct.printv('\n--\nESTIMATE TRANSFORMATION FOR STEP #'+str(i_step), param.verbose) # identify which is the src and dest if paramreg.steps[str(i_step)].type == 'im': src = 'src.nii' dest = 'dest_RPI.nii' interp_step = 'spline' elif paramreg.steps[str(i_step)].type == 'seg': src = 'src_seg.nii' dest = 'dest_seg_RPI.nii' interp_step = 'nn' elif paramreg.steps[str(i_step)].type == 'label': src = 'src_label.nii' dest = 'dest_label_RPI.nii' interp_step = 'nn' else: # src = dest = interp_step = None sct.printv('ERROR: Wrong image type.', 1, 'error') # if step>0, apply warp_forward_concat to the src image to be used if i_step > 0: sct.printv('\nApply transformation from previous step', param.verbose) sct.run('sct_apply_transfo -i '+src+' -d '+dest+' -w '+','.join(warp_forward)+' -o '+sct.add_suffix(src, '_reg')+' -x '+interp_step, verbose) src = sct.add_suffix(src, '_reg') # register src --> dest warp_forward_out, warp_inverse_out = register(src, dest, paramreg, param, str(i_step)) warp_forward.append(warp_forward_out) warp_inverse.insert(0, warp_inverse_out) # Concatenate transformations sct.printv('\nConcatenate transformations...', verbose) sct.run('sct_concat_transfo -w '+','.join(warp_forward)+' -d dest.nii -o warp_src2dest.nii.gz', verbose) sct.run('sct_concat_transfo -w '+','.join(warp_inverse)+' -d dest.nii -o warp_dest2src.nii.gz', verbose) # Apply warping field to src data sct.printv('\nApply transfo source --> dest...', verbose) sct.run('sct_apply_transfo -i src.nii -o src_reg.nii -d dest.nii -w warp_src2dest.nii.gz -x '+interp, verbose) sct.printv('\nApply transfo dest --> source...', verbose) sct.run('sct_apply_transfo -i dest.nii -o dest_reg.nii -d src.nii -w warp_dest2src.nii.gz -x '+interp, verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', verbose) # generate: src_reg fname_src2dest = sct.generate_output_file(path_tmp+'src_reg.nii', path_out+file_out+ext_out, verbose) # generate: forward warping field if fname_output_warp == '': fname_output_warp = path_out+'warp_'+file_src+'2'+file_dest+'.nii.gz' sct.generate_output_file(path_tmp+'warp_src2dest.nii.gz', fname_output_warp, verbose) if generate_warpinv: # generate: dest_reg fname_dest2src = sct.generate_output_file(path_tmp+'dest_reg.nii', path_out+file_out_inv+ext_dest, verbose) # generate: inverse warping field sct.generate_output_file(path_tmp+'warp_dest2src.nii.gz', path_out+'warp_'+file_dest+'2'+file_src+'.nii.gz', verbose) # Delete temporary files if remove_temp_files: sct.printv('\nRemove temporary files...', verbose) sct.run('rm -rf '+path_tmp, verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: '+str(int(round(elapsed_time)))+'s', verbose) sct.printv('\nTo view results, type:', verbose) sct.printv('fslview '+fname_dest+' '+fname_src2dest+' &', verbose, 'info') if generate_warpinv: sct.printv('fslview '+fname_src+' '+fname_dest2src+' &\n', verbose, 'info')
def main(): # initialization start_time = time.time() path_out = '.' param_user = '' # reducing the number of CPU used for moco (see issue #201) os.environ["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = "1" # get path of the toolbox status, param.path_sct = commands.getstatusoutput('echo $SCT_DIR') # Parameters for debug mode if param.debug: # get path of the testing data status, path_sct_data = commands.getstatusoutput( 'echo $SCT_TESTING_DATA_DIR') param.fname_data = path_sct_data + '/dmri/dmri.nii.gz' param.fname_bvecs = path_sct_data + '/dmri/bvecs.txt' param.fname_mask = path_sct_data + '/dmri/dmri.nii.gz' param.remove_tmp_files = 0 param.verbose = 1 param.run_eddy = 0 param.otsu = 0 param.group_size = 5 param.iterative_averaging = 1 else: # Check input parameters try: opts, args = getopt.getopt(sys.argv[1:], 'hi:a:b:e:f:g:m:o:p:r:t:v:x:') except getopt.GetoptError: usage() if not opts: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ('-a'): param.fname_bvals = arg elif opt in ('-b'): param.fname_bvecs = arg elif opt in ('-e'): param.run_eddy = int(arg) elif opt in ('-f'): param.spline_fitting = int(arg) elif opt in ('-g'): param.group_size = int(arg) elif opt in ('-i'): param.fname_data = arg elif opt in ('-m'): param.fname_mask = arg elif opt in ('-o'): path_out = arg elif opt in ('-p'): param_user = arg elif opt in ('-r'): param.remove_tmp_files = int(arg) elif opt in ('-t'): param.otsu = int(arg) elif opt in ('-v'): param.verbose = int(arg) elif opt in ('-x'): param.interp = arg # display usage if a mandatory argument is not provided if param.fname_data == '' or param.fname_bvecs == '': sct.printv( 'ERROR: All mandatory arguments are not provided. See usage.', 1, 'error') usage() # parse argument for param if not param_user == '': param.param = param_user.replace(' ', '').split( ',') # remove spaces and parse with comma # TODO: check integrity of input # param.param = [i for i in range(len(param_user))] del param_user sct.printv('\nInput parameters:', param.verbose) sct.printv(' input file ............' + param.fname_data, param.verbose) sct.printv(' bvecs file ............' + param.fname_bvecs, param.verbose) sct.printv(' bvals file ............' + param.fname_bvals, param.verbose) sct.printv(' mask file .............' + param.fname_mask, param.verbose) # check existence of input files sct.printv('\nCheck file existence...', param.verbose) sct.check_file_exist(param.fname_data, param.verbose) sct.check_file_exist(param.fname_bvecs, param.verbose) if not param.fname_bvals == '': sct.check_file_exist(param.fname_bvals, param.verbose) if not param.fname_mask == '': sct.check_file_exist(param.fname_mask, param.verbose) # Get full path param.fname_data = os.path.abspath(param.fname_data) param.fname_bvecs = os.path.abspath(param.fname_bvecs) if param.fname_bvals != '': param.fname_bvals = os.path.abspath(param.fname_bvals) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) path_mask, file_mask, ext_mask = sct.extract_fname(param.fname_mask) # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.slash_at_the_end('tmp.' + time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir ' + path_tmp, param.verbose) # Copying input data to tmp folder # NB: cannot use c3d here because c3d cannot convert 4D data. sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) sct.run('cp ' + param.fname_data + ' ' + path_tmp + 'dmri' + ext_data, param.verbose) sct.run('cp ' + param.fname_bvecs + ' ' + path_tmp + 'bvecs.txt', param.verbose) if param.fname_mask != '': sct.run('cp ' + param.fname_mask + ' ' + path_tmp + 'mask' + ext_mask, param.verbose) # go to tmp folder os.chdir(path_tmp) # convert dmri to nii format convert('dmri' + ext_data, 'dmri.nii') # update field in param (because used later). # TODO: make this cleaner... if param.fname_mask != '': param.fname_mask = 'mask' + ext_mask # run moco dmri_moco(param) # come back to parent folder os.chdir('..') # Generate output files path_out = sct.slash_at_the_end(path_out, 1) sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(path_tmp + 'dmri' + param.suffix + '.nii', path_out + file_data + param.suffix + ext_data, param.verbose) sct.generate_output_file( path_tmp + 'b0_mean.nii', path_out + 'b0' + param.suffix + '_mean' + ext_data, param.verbose) sct.generate_output_file( path_tmp + 'dwi_mean.nii', path_out + 'dwi' + param.suffix + '_mean' + ext_data, param.verbose) # Delete temporary files if param.remove_tmp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.run('rm -rf ' + path_tmp, param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv( '\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's', param.verbose) #To view results sct.printv('\nTo view results, type:', param.verbose) sct.printv( 'fslview -m ortho,ortho ' + param.path_out + file_data + param.suffix + ' ' + file_data + ' &\n', param.verbose, 'info')
def main(args=None): # initialization start_time = time.time() param = Param() # reducing the number of CPU used for moco (see issue #201) os.environ["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = "1" # check user arguments if not args: args = sys.argv[1:] # Get parser info parser = get_parser() arguments = parser.parse(sys.argv[1:]) param.fname_data = arguments['-i'] if '-g' in arguments: param.group_size = arguments['-g'] if '-m' in arguments: param.fname_mask = arguments['-m'] if '-param' in arguments: param.update(arguments['-param']) if '-x' in arguments: param.interp = arguments['-x'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-r' in arguments: param.remove_tmp_files = int(arguments['-r']) if '-v' in arguments: param.verbose = int(arguments['-v']) sct.printv('\nInput parameters:', param.verbose) sct.printv(' input file ............' + param.fname_data, param.verbose) # Get full path param.fname_data = os.path.abspath(param.fname_data) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) # create temporary folder sct.printv('\nCreate temporary folder...', param.verbose) path_tmp = sct.slash_at_the_end('tmp.' + time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir ' + path_tmp, param.verbose) # Copying input data to tmp folder and convert to nii sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, path_tmp + 'fmri.nii') # go to tmp folder os.chdir(path_tmp) # run moco fmri_moco(param) # come back to parent folder os.chdir('..') # Generate output files path_out = sct.slash_at_the_end(path_out, 1) sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) if os.path.isfile(path_tmp + 'fmri' + param.suffix + '.nii'): sct.printv(path_tmp + 'fmri' + param.suffix + '.nii') sct.printv(path_out + file_data + param.suffix + ext_data) sct.generate_output_file(path_tmp + 'fmri' + param.suffix + '.nii', path_out + file_data + param.suffix + ext_data, param.verbose) sct.generate_output_file( path_tmp + 'fmri' + param.suffix + '_mean.nii', path_out + file_data + param.suffix + '_mean' + ext_data, param.verbose) # Delete temporary files if param.remove_tmp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.run('rm -rf ' + path_tmp, param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv( '\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's', param.verbose) # To view results sct.printv('\nTo view results, type:', param.verbose) sct.printv( 'fslview -m ortho,ortho ' + param.path_out + file_data + param.suffix + ' ' + file_data + ' &\n', param.verbose, 'info')
def main(): # Initialization fname_mt0 = '' fname_mt1 = '' file_out = param.file_out # register = param.register # remove_tmp_files = param.remove_tmp_files # verbose = param.verbose # get path of the toolbox # status, path_sct = commands.getstatusoutput('echo $SCT_DIR') # Check input parameters parser = get_parser() arguments = parser.parse(sys.argv[1:]) fname_mt0 = arguments['-mt0'] fname_mt1 = arguments['-mt1'] remove_tmp_files = int(arguments['-r']) verbose = int(arguments['-v']) # Extract path/file/extension path_mt0, file_mt0, ext_mt0 = sct.extract_fname(fname_mt0) path_out, file_out, ext_out = '', file_out, ext_mt0 # create temporary folder path_tmp = sct.tmp_create() # Copying input data to tmp folder and convert to nii sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) from sct_convert import convert convert(fname_mt0, path_tmp+'mt0.nii', type='float32') convert(fname_mt1, path_tmp+'mt1.nii', type='float32') # go to tmp folder os.chdir(path_tmp) # compute MTR sct.printv('\nCompute MTR...', verbose) from msct_image import Image nii_mt1 = Image('mt1.nii') data_mt1 = nii_mt1.data data_mt0 = Image('mt0.nii').data data_mtr = 100 * (data_mt0 - data_mt1) / data_mt0 # save MTR file nii_mtr = nii_mt1 nii_mtr.data = data_mtr nii_mtr.setFileName('mtr.nii') nii_mtr.save() # sct.run(fsloutput+'fslmaths -dt double mt0.nii -sub mt1.nii -mul 100 -div mt0.nii -thr 0 -uthr 100 mtr.nii', verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(path_tmp+'mtr.nii', path_out+file_out+ext_out) # Remove temporary files if remove_tmp_files == 1: print('\nRemove temporary files...') sct.run('rm -rf '+path_tmp) # to view results sct.printv('\nDone! To view results, type:', verbose) sct.printv('fslview '+fname_mt0+' '+fname_mt1+' '+file_out+' &\n', verbose, 'info')
def main(args=None): if not args: args = sys.argv[1:] # initialize parameters param = Param() # call main function parser = get_parser() arguments = parser.parse(args) fname_data = arguments['-i'] fname_bvecs = arguments['-bvec'] average = arguments['-a'] verbose = int(arguments['-v']) remove_temp_files = int(arguments['-r']) path_out = arguments['-ofolder'] if '-bval' in arguments: fname_bvals = arguments['-bval'] else: fname_bvals = '' if '-bvalmin' in arguments: param.bval_min = arguments['-bvalmin'] # Initialization start_time = time.time() # sct.printv(arguments) sct.printv('\nInput parameters:', verbose) sct.printv(' input file ............' + fname_data, verbose) sct.printv(' bvecs file ............' + fname_bvecs, verbose) sct.printv(' bvals file ............' + fname_bvals, verbose) sct.printv(' average ...............' + str(average), verbose) # Get full path fname_data = os.path.abspath(fname_data) fname_bvecs = os.path.abspath(fname_bvecs) if fname_bvals: fname_bvals = os.path.abspath(fname_bvals) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(fname_data) # # get output folder # if path_out == '': # path_out = '' # create temporary folder path_tmp = sct.tmp_create(basename="dmri_separate", verbose=verbose) # copy files into tmp folder and convert to nifti sct.printv('\nCopy files into temporary folder...', verbose) ext = '.nii' dmri_name = 'dmri' b0_name = 'b0' b0_mean_name = b0_name + '_mean' dwi_name = 'dwi' dwi_mean_name = dwi_name + '_mean' from sct_convert import convert if not convert(fname_data, os.path.join(path_tmp, dmri_name + ext)): sct.printv('ERROR in convert.', 1, 'error') sct.copy(fname_bvecs, os.path.join(path_tmp, "bvecs"), verbose=verbose) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # Get size of data im_dmri = Image(dmri_name + ext) sct.printv('\nGet dimensions data...', verbose) nx, ny, nz, nt, px, py, pz, pt = im_dmri.dim sct.printv( '.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt), verbose) # Identify b=0 and DWI images sct.printv(fname_bvals) index_b0, index_dwi, nb_b0, nb_dwi = identify_b0(fname_bvecs, fname_bvals, param.bval_min, verbose) # Split into T dimension sct.printv('\nSplit along T dimension...', verbose) im_dmri_split_list = split_data(im_dmri, 3) for im_d in im_dmri_split_list: im_d.save() # Merge b=0 images sct.printv('\nMerge b=0...', verbose) from sct_image import concat_data l = [] for it in range(nb_b0): l.append(dmri_name + '_T' + str(index_b0[it]).zfill(4) + ext) im_out = concat_data(l, 3).save(b0_name + ext) # Average b=0 images if average: sct.printv('\nAverage b=0...', verbose) sct.run([ 'sct_maths', '-i', b0_name + ext, '-o', b0_mean_name + ext, '-mean', 't' ], verbose) # Merge DWI l = [] for it in range(nb_dwi): l.append(dmri_name + '_T' + str(index_dwi[it]).zfill(4) + ext) im_out = concat_data(l, 3).save(dwi_name + ext) # Average DWI images if average: sct.printv('\nAverage DWI...', verbose) sct.run([ 'sct_maths', '-i', dwi_name + ext, '-o', dwi_mean_name + ext, '-mean', 't' ], verbose) # if not average_data_across_dimension('dwi.nii', 'dwi_mean.nii', 3): # sct.printv('ERROR in average_data_across_dimension', 1, 'error') # sct.run(fsloutput + 'fslmaths dwi -Tmean dwi_mean', verbose) # come back os.chdir(curdir) # Generate output files sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(os.path.join(path_tmp, b0_name + ext), os.path.join(path_out, b0_name + ext_data), verbose) sct.generate_output_file(os.path.join(path_tmp, dwi_name + ext), os.path.join(path_out, dwi_name + ext_data), verbose) if average: sct.generate_output_file( os.path.join(path_tmp, b0_mean_name + ext), os.path.join(path_out, b0_mean_name + ext_data), verbose) sct.generate_output_file( os.path.join(path_tmp, dwi_mean_name + ext), os.path.join(path_out, dwi_mean_name + ext_data), verbose) # Remove temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...', verbose) sct.rmtree(path_tmp, verbose=verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv( '\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's', verbose) # to view results sct.printv('\nTo view results, type: ', verbose) if average: sct.display_viewer_syntax(['b0', 'b0_mean', 'dwi', 'dwi_mean']) else: sct.display_viewer_syntax(['b0', 'dwi'])
def main(): # Initialization fname_data = '' interp_factor = param.interp_factor remove_temp_files = param.remove_temp_files verbose = param.verbose suffix = param.suffix smoothing_sigma = param.smoothing_sigma # start timer start_time = time.time() # get path of the toolbox status, path_sct = commands.getstatusoutput('echo $SCT_DIR') # Parameters for debug mode if param.debug: fname_data = path_sct+'/testing/data/errsm_23/t2/t2_manual_segmentation.nii.gz' remove_temp_files = 0 param.mask_size = 10 else: # Check input parameters try: opts, args = getopt.getopt(sys.argv[1:],'hi:v:r:s:') except getopt.GetoptError: usage() if not opts: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ('-i'): fname_data = arg elif opt in ('-r'): remove_temp_files = int(arg) elif opt in ('-s'): smoothing_sigma = arg elif opt in ('-v'): verbose = int(arg) # display usage if a mandatory argument is not provided if fname_data == '': usage() # print arguments print '\nCheck parameters:' print ' segmentation ........... '+fname_data print ' interp factor .......... '+str(interp_factor) print ' smoothing sigma ........ '+str(smoothing_sigma) # check existence of input files print('\nCheck existence of input files...') sct.check_file_exist(fname_data, verbose) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(fname_data) # create temporary folder print('\nCreate temporary folder...') path_tmp = 'tmp.'+time.strftime("%y%m%d%H%M%S") sct.run('mkdir '+path_tmp) from sct_convert import convert sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(fname_data, path_tmp+'/data.nii') # go to tmp folder os.chdir(path_tmp) # Get dimensions of data sct.printv('\nGet dimensions of data...', verbose) nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim sct.printv('.. '+str(nx)+' x '+str(ny)+' x '+str(nz), verbose) # upsample data sct.printv('\nUpsample data...', verbose) sct.run('sct_resample -i data.nii -x linear -vox '+str(nx*interp_factor)+'x'+str(ny*interp_factor)+'x'+str(nz*interp_factor)+' -o data_up.nii', verbose) # Smooth along centerline sct.printv('\nSmooth along centerline...', verbose) sct.run('sct_smooth_spinalcord -i data_up.nii -s data_up.nii'+' -smooth '+str(smoothing_sigma)+' -r '+str(remove_temp_files)+' -v '+str(verbose), verbose) # downsample data sct.printv('\nDownsample data...', verbose) sct.run('sct_resample -i data_up_smooth.nii -x linear -vox '+str(nx)+'x'+str(ny)+'x'+str(nz)+' -o data_up_smooth_down.nii', verbose) # come back to parent folder os.chdir('..') # Generate output files print('\nGenerate output files...') fname_out = sct.generate_output_file(path_tmp+'/data_up_smooth_down.nii', ''+file_data+suffix+ext_data) # Delete temporary files if remove_temp_files == 1: print '\nRemove temporary files...' sct.run('rm -rf '+ path_tmp) # display elapsed time elapsed_time = time.time() - start_time print '\nFinished! Elapsed time: '+str(int(round(elapsed_time)))+'s' # to view results print '\nTo view results, type:' print 'fslview '+file_data+' '+file_data+suffix+' &\n'
def check_and_correct_segmentation(fname_segmentation, fname_centerline, folder_output='', threshold_distance=5.0, remove_temp_files=1, verbose=0): """ This function takes the outputs of isct_propseg (centerline and segmentation) and check if the centerline of the segmentation is coherent with the centerline provided by the isct_propseg, especially on the edges (related to issue #1074). Args: fname_segmentation: filename of binary segmentation fname_centerline: filename of binary centerline threshold_distance: threshold, in mm, beyond which centerlines are not coherent verbose: Returns: None """ sct.printv('\nCheck consistency of segmentation...', verbose) # creating a temporary folder in which all temporary files will be placed and deleted afterwards path_tmp = sct.tmp_create(basename="propseg", verbose=verbose) from sct_convert import convert convert(fname_segmentation, os.path.join(path_tmp, "tmp.segmentation.nii.gz"), squeeze_data=False, verbose=0) convert(fname_centerline, os.path.join(path_tmp, "tmp.centerline.nii.gz"), squeeze_data=False, verbose=0) fname_seg_absolute = os.path.abspath(fname_segmentation) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # convert segmentation image to RPI im_input = Image('tmp.segmentation.nii.gz') image_input_orientation = orientation(im_input, get=True, verbose=False) sct_image.main( "-i tmp.segmentation.nii.gz -setorient RPI -o tmp.segmentation_RPI.nii.gz -v 0" .split()) sct_image.main( "-i tmp.centerline.nii.gz -setorient RPI -o tmp.centerline_RPI.nii.gz -v 0" .split()) # go through segmentation image, and compare with centerline from propseg im_seg = Image('tmp.segmentation_RPI.nii.gz') im_centerline = Image('tmp.centerline_RPI.nii.gz') # Get size of data sct.printv('\nGet data dimensions...', verbose) nx, ny, nz, nt, px, py, pz, pt = im_seg.dim # extraction of centerline provided by isct_propseg and computation of center of mass for each slice # the centerline is defined as the center of the tubular mesh outputed by propseg. centerline, key_centerline = {}, [] for i in range(nz): slice = im_centerline.data[:, :, i] if np.any(slice): x_centerline, y_centerline = ndi.measurements.center_of_mass(slice) centerline[str(i)] = [x_centerline, y_centerline] key_centerline.append(i) minz_centerline = np.min(key_centerline) maxz_centerline = np.max(key_centerline) mid_slice = int((maxz_centerline - minz_centerline) / 2) # for each slice of the segmentation, check if only one object is present. If not, remove the slice from segmentation. # If only one object (the spinal cord) is present in the slice, check if its center of mass is close to the centerline of isct_propseg. slices_to_remove = [ False ] * nz # flag that decides if the slice must be removed for i in range(minz_centerline, maxz_centerline + 1): # extraction of slice slice = im_seg.data[:, :, i] distance = -1 label_objects, nb_labels = ndi.label( slice) # count binary objects in the slice if nb_labels > 1: # if there is more that one object in the slice, the slice is removed from the segmentation slices_to_remove[i] = True elif nb_labels == 1: # check if the centerline is coherent with the one from isct_propseg x_centerline, y_centerline = ndi.measurements.center_of_mass(slice) slice_nearest_coord = min(key_centerline, key=lambda x: abs(x - i)) coord_nearest_coord = centerline[str(slice_nearest_coord)] distance = np.sqrt(( (x_centerline - coord_nearest_coord[0]) * px)**2 + ( (y_centerline - coord_nearest_coord[1]) * py)**2 + ((i - slice_nearest_coord) * pz)**2) if distance >= threshold_distance: # threshold must be adjusted, default is 5 mm slices_to_remove[i] = True # Check list of removal and keep one continuous centerline (improve this comment) # Method: # starting from mid-centerline (in both directions), the first True encountered is applied to all following slices slice_to_change = False for i in range(mid_slice, nz): if slice_to_change: slices_to_remove[i] = True elif slices_to_remove[i]: slice_to_change = True slice_to_change = False for i in range(mid_slice, 0, -1): if slice_to_change: slices_to_remove[i] = True elif slices_to_remove[i]: slice_to_change = True for i in range(0, nz): # remove the slice if slices_to_remove[i]: im_seg.data[:, :, i] *= 0 # saving the image im_seg.setFileName('tmp.segmentation_RPI_c.nii.gz') im_seg.save() # replacing old segmentation with the corrected one sct_image.main( '-i tmp.segmentation_RPI_c.nii.gz -setorient {} -o {} -v 0'.format( image_input_orientation, fname_seg_absolute).split()) os.chdir(curdir) # display information about how much of the segmentation has been corrected # remove temporary files if remove_temp_files: # sct.printv("\nRemove temporary files...", verbose) sct.rmtree(path_tmp)
def main(args = None): orientation = '' change_header = '' fname_out = '' if not args: args = sys.argv[1:] # Building the command, do sanity checks parser = get_parser() arguments = parser.parse(sys.argv[1:]) fname_in = arguments['-i'] if '-o' in arguments: fname_out = arguments['-o'] if '-s' in arguments: orientation = arguments['-s'] if '-a' in arguments: change_header = arguments['-a'] remove_tmp_files = int(arguments['-r']) verbose = int(arguments['-v']) inversion = False # change orientation # create temporary folder sct.printv('\nCreate temporary folder...', verbose) path_tmp = 'tmp.'+time.strftime("%y%m%d%H%M%S/") status, output = sct.run('mkdir '+path_tmp, verbose) # copy file in temp folder sct.printv('\nCopy files to tmp folder...', verbose) convert(fname_in, path_tmp+'data.nii', verbose=0) # go to temp folder os.chdir(path_tmp) # Get dimensions of data sct.printv('\nGet dimensions of data...', verbose) nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim sct.printv(str(nx) + ' x ' + str(ny) + ' x ' + str(nz)+ ' x ' + str(nt), verbose) # if data are 3d, directly set or get orientation if nt == 1: if orientation != '': # set orientation sct.printv('\nChange orientation...', verbose) if change_header == '': set_orientation('data.nii', orientation, 'data_orient.nii') else: set_orientation('data.nii', change_header, 'data_orient.nii', True) else: # get orientation sct.printv('\nGet orientation...', verbose) print get_orientation('data.nii') else: # split along T dimension sct.printv('\nSplit along T dimension...', verbose) im = Image('data.nii') im_split_list = split_data(im, 3) for im_s in im_split_list: im_s.save() if orientation != '': # set orientation sct.printv('\nChange orientation...', verbose) for it in range(nt): file_data_split = 'data_T'+str(it).zfill(4)+'.nii' file_data_split_orient = 'data_orient_T'+str(it).zfill(4)+'.nii' set_orientation(file_data_split, orientation, file_data_split_orient) # Merge files back sct.printv('\nMerge file back...', verbose) from glob import glob im_data_list = [Image(fname) for fname in glob('data_orient_T*.nii')] im_concat = concat_data(im_data_list, 3) im_concat.setFileName('data_orient.nii') im_concat.save() else: sct.printv('\nGet orientation...', verbose) print get_orientation('data_T0000.nii') # come back to parent folder os.chdir('..') # Generate output files if orientation != '': # Build fname_out if fname_out == '': path_data, file_data, ext_data = sct.extract_fname(fname_in) fname_out = path_data+file_data+'_'+orientation+ext_data sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(path_tmp+'data_orient.nii', fname_out) # Remove temporary files if remove_tmp_files == 1: sct.printv('\nRemove temporary files...', verbose) sct.run('rm -rf '+path_tmp, verbose)
def main(args=None): # initialization start_time = time.time() path_out = '.' param = Param() # check user arguments if not args: args = sys.argv[1:] # Get parser info parser = get_parser() arguments = parser.parse(sys.argv[1:]) param.fname_data = arguments['-i'] param.fname_bvecs = arguments['-bvec'] if '-bval' in arguments: param.fname_bvals = arguments['-bval'] if '-bvalmin' in arguments: param.bval_min = arguments['-bvalmin'] if '-g' in arguments: param.group_size = arguments['-g'] if '-m' in arguments: param.fname_mask = arguments['-m'] if '-param' in arguments: param.update(arguments['-param']) if '-thr' in arguments: param.otsu = arguments['-thr'] if '-x' in arguments: param.interp = arguments['-x'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-r' in arguments: param.remove_temp_files = int(arguments['-r']) param.verbose = int(arguments.get('-v')) sct.init_sct(log_level=param.verbose, update=True) # Update log level # Get full path param.fname_data = os.path.abspath(param.fname_data) param.fname_bvecs = os.path.abspath(param.fname_bvecs) if param.fname_bvals != '': param.fname_bvals = os.path.abspath(param.fname_bvals) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) path_mask, file_mask, ext_mask = sct.extract_fname(param.fname_mask) path_tmp = sct.tmp_create(basename="dmri_moco", verbose=param.verbose) # names of files in temporary folder mask_name = 'mask' bvecs_fname = 'bvecs.txt' # Copying input data to tmp folder sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, os.path.join(path_tmp, "dmri.nii")) sct.copy(param.fname_bvecs, os.path.join(path_tmp, bvecs_fname), verbose=param.verbose) if param.fname_mask != '': sct.copy(param.fname_mask, os.path.join(path_tmp, mask_name + ext_mask), verbose=param.verbose) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # update field in param (because used later). # TODO: make this cleaner... if param.fname_mask != '': param.fname_mask = mask_name + ext_mask # run moco fname_data_moco_tmp = dmri_moco(param) # generate b0_moco_mean and dwi_moco_mean args = [ '-i', fname_data_moco_tmp, '-bvec', 'bvecs.txt', '-a', '1', '-v', '0' ] if not param.fname_bvals == '': # if bvals file is provided args += ['-bval', param.fname_bvals] fname_b0, fname_b0_mean, fname_dwi, fname_dwi_mean = sct_dmri_separate_b0_and_dwi.main( args=args) # come back os.chdir(curdir) # Generate output files fname_dmri_moco = os.path.join(path_out, file_data + param.suffix + ext_data) fname_dmri_moco_b0_mean = sct.add_suffix(fname_dmri_moco, '_b0_mean') fname_dmri_moco_dwi_mean = sct.add_suffix(fname_dmri_moco, '_dwi_mean') sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(fname_data_moco_tmp, fname_dmri_moco, param.verbose) sct.generate_output_file(fname_b0_mean, fname_dmri_moco_b0_mean, param.verbose) sct.generate_output_file(fname_dwi_mean, fname_dmri_moco_dwi_mean, param.verbose) # Delete temporary files if param.remove_temp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.rmtree(path_tmp, verbose=param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv( '\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's', param.verbose) sct.display_viewer_syntax([fname_dmri_moco, file_data], mode='ortho,ortho')
def main(args=None): # initialization start_time = time.time() path_out = '.' param = Param() # check user arguments if not args: args = sys.argv[1:] # Get parser info parser = get_parser() arguments = parser.parse(sys.argv[1:]) param.fname_data = arguments['-i'] param.fname_bvecs = arguments['-bvec'] if '-bval' in arguments: param.fname_bvals = arguments['-bval'] if '-bvalmin' in arguments: param.bval_min = arguments['-bvalmin'] if '-g' in arguments: param.group_size = arguments['-g'] if '-m' in arguments: param.fname_mask = arguments['-m'] if '-param' in arguments: param.update(arguments['-param']) if '-thr' in arguments: param.otsu = arguments['-thr'] if '-x' in arguments: param.interp = arguments['-x'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-r' in arguments: param.remove_temp_files = int(arguments['-r']) param.verbose = int(arguments.get('-v')) sct.init_sct(log_level=param.verbose, update=True) # Update log level # Get full path param.fname_data = os.path.abspath(param.fname_data) param.fname_bvecs = os.path.abspath(param.fname_bvecs) if param.fname_bvals != '': param.fname_bvals = os.path.abspath(param.fname_bvals) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) path_mask, file_mask, ext_mask = sct.extract_fname(param.fname_mask) path_tmp = sct.tmp_create(basename="dmri_moco", verbose=param.verbose) # names of files in temporary folder mask_name = 'mask' bvecs_fname = 'bvecs.txt' # Copying input data to tmp folder sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, os.path.join(path_tmp, "dmri.nii")) sct.copy(param.fname_bvecs, os.path.join(path_tmp, bvecs_fname), verbose=param.verbose) if param.fname_mask != '': sct.copy(param.fname_mask, os.path.join(path_tmp, mask_name + ext_mask), verbose=param.verbose) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # update field in param (because used later). # TODO: make this cleaner... if param.fname_mask != '': param.fname_mask = mask_name + ext_mask # run moco fname_data_moco_tmp = dmri_moco(param) # generate b0_moco_mean and dwi_moco_mean args = ['-i', fname_data_moco_tmp, '-bvec', 'bvecs.txt', '-a', '1', '-v', '0'] if not param.fname_bvals == '': # if bvals file is provided args += ['-bval', param.fname_bvals] fname_b0, fname_b0_mean, fname_dwi, fname_dwi_mean = sct_dmri_separate_b0_and_dwi.main(args=args) # come back os.chdir(curdir) # Generate output files fname_dmri_moco = os.path.join(path_out, file_data + param.suffix + ext_data) fname_dmri_moco_b0_mean = sct.add_suffix(fname_dmri_moco, '_b0_mean') fname_dmri_moco_dwi_mean = sct.add_suffix(fname_dmri_moco, '_dwi_mean') sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(fname_data_moco_tmp, fname_dmri_moco, param.verbose) sct.generate_output_file(fname_b0_mean, fname_dmri_moco_b0_mean, param.verbose) sct.generate_output_file(fname_dwi_mean, fname_dmri_moco_dwi_mean, param.verbose) # Delete temporary files if param.remove_temp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.rmtree(path_tmp, verbose=param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's', param.verbose) sct.display_viewer_syntax([fname_dmri_moco, file_data], mode='ortho,ortho')
def execute(self): print 'Execution of the SCAD algorithm in ' + str(os.getcwd()) original_name = self.input_image.file_name vesselness_file_name = "imageVesselNessFilter.nii.gz" raw_file_name = "raw.nii" self.setup_debug_folder() if self.debug: import matplotlib.pyplot as plt # import for debug purposes # create tmp and copy input path_tmp = self.create_temporary_path() conv.convert(self.input_image.absolutepath, path_tmp + raw_file_name) if self.vesselness_provided: sct.run('cp ' + vesselness_file_name + ' ' + path_tmp + vesselness_file_name) os.chdir(path_tmp) # get input image information img = Image(raw_file_name) # save original orientation and change image to RPI self.raw_orientation = img.change_orientation() # get body symmetry if self.enable_symmetry: from msct_image import change_data_orientation sym = SymmetryDetector(raw_file_name, self.contrast, crop_xy=0) self.raw_symmetry = sym.execute() img.change_orientation(self.raw_orientation) self.output_debug_file(img, self.raw_symmetry, "body_symmetry") img.change_orientation() # vesselness filter if not self.vesselness_provided: sct.run('isct_vesselness -i ' + raw_file_name + ' -t ' + self._contrast + " -radius " + str(self.spinalcord_radius)) # load vesselness filter data and perform minimum path on it img = Image(vesselness_file_name) self.output_debug_file(img, img.data, "Vesselness_Filter") img.change_orientation() self.minimum_path_data, self.J1_min_path, self.J2_min_path = get_minimum_path( img.data, invert=1, debug=1) self.output_debug_file(img, self.minimum_path_data, "minimal_path") self.output_debug_file(img, self.J1_min_path, "J1_minimal_path") self.output_debug_file(img, self.J2_min_path, "J2_minimal_path") # Apply an exponent to the minimum path self.minimum_path_powered = np.power(self.minimum_path_data, self.minimum_path_exponent) self.output_debug_file( img, self.minimum_path_powered, "minimal_path_power_" + str(self.minimum_path_exponent)) # Saving in Image since smooth_minimal_path needs pixel dimensions img.data = self.minimum_path_powered # smooth resulting minimal path self.smoothed_min_path = smooth_minimal_path(img) self.output_debug_file(img, self.smoothed_min_path.data, "minimal_path_smooth") # normalise symmetry values between 0 and 1 if self.enable_symmetry: normalised_symmetry = normalize_array_histogram(self.raw_symmetry) self.output_debug_file(img, self.smoothed_min_path.data, "minimal_path_smooth") # multiply normalised symmetry data with the minimum path result from msct_image import change_data_orientation self.spine_detect_data = np.multiply( self.smoothed_min_path.data, change_data_orientation( np.power(normalised_symmetry, self.symmetry_exponent), self.raw_orientation, "RPI")) self.output_debug_file(img, self.spine_detect_data, "symmetry_x_min_path") # extract the centerline from the minimal path image self.centerline_with_outliers = get_centerline( self.spine_detect_data, self.spine_detect_data.shape) else: # extract the centerline from the minimal path image self.centerline_with_outliers = get_centerline( self.smoothed_min_path.data, self.smoothed_min_path.data.shape) self.output_debug_file(img, self.centerline_with_outliers, "centerline_with_outliers") # saving centerline with outliers to have img.data = self.centerline_with_outliers img.change_orientation() img.file_name = "centerline_with_outliers" img.save() # use a b-spline to smooth out the centerline x, y, z, dx, dy, dz = smooth_centerline( "centerline_with_outliers.nii.gz") # save the centerline nx, ny, nz, nt, px, py, pz, pt = img.dim img.data = np.zeros((nx, ny, nz)) for i in range(0, np.size(x) - 1): img.data[int(x[i]), int(y[i]), int(z[i])] = 1 self.output_debug_file(img, img.data, "centerline") img.change_orientation(self.raw_orientation) img.file_name = "centerline" img.save() # copy back centerline os.chdir('../') conv.convert(path_tmp + img.file_name + img.ext, self.output_filename) if self.rm_tmp_file == 1: import shutil shutil.rmtree(path_tmp) print "To view the output with FSL :" sct.printv( "fslview " + self.input_image.absolutepath + " " + self.output_filename + " -l Red", self.verbose, "info")
def main(args=None): # initialization start_time = time.time() path_out = '.' param = Param() # reducing the number of CPU used for moco (see issue #201) os.environ["ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS"] = "1" # get path of the toolbox # status, param.path_sct = sct.run('echo $SCT_DIR') # check user arguments if not args: args = sys.argv[1:] # Get parser info parser = get_parser() arguments = parser.parse(sys.argv[1:]) param.fname_data = arguments['-i'] param.fname_bvecs = arguments['-bvec'] if '-bval' in arguments: param.fname_bvals = arguments['-bval'] if '-bvalmin' in arguments: param.bval_min = arguments['-bvalmin'] if '-g' in arguments: param.group_size = arguments['-g'] if '-m' in arguments: param.fname_mask = arguments['-m'] if '-param' in arguments: param.update(arguments['-param']) if '-thr' in arguments: param.otsu = arguments['-thr'] if '-x' in arguments: param.interp = arguments['-x'] if '-ofolder' in arguments: path_out = arguments['-ofolder'] if '-r' in arguments: param.remove_temp_files = int(arguments['-r']) if '-v' in arguments: param.verbose = int(arguments['-v']) # Get full path param.fname_data = os.path.abspath(param.fname_data) param.fname_bvecs = os.path.abspath(param.fname_bvecs) if param.fname_bvals != '': param.fname_bvals = os.path.abspath(param.fname_bvals) if param.fname_mask != '': param.fname_mask = os.path.abspath(param.fname_mask) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) path_mask, file_mask, ext_mask = sct.extract_fname(param.fname_mask) path_tmp = sct.tmp_create(basename="dmri_moco", verbose=param.verbose) # names of files in temporary folder ext = '.nii' dmri_name = 'dmri' mask_name = 'mask' bvecs_fname = 'bvecs.txt' # Copying input data to tmp folder sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(param.fname_data, os.path.join(path_tmp, dmri_name + ext)) sct.copy(param.fname_bvecs, os.path.join(path_tmp, bvecs_fname), verbose=param.verbose) if param.fname_mask != '': sct.copy(param.fname_mask, os.path.join(path_tmp, mask_name + ext_mask), verbose=param.verbose) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # update field in param (because used later). # TODO: make this cleaner... if param.fname_mask != '': param.fname_mask = mask_name + ext_mask # run moco dmri_moco(param) # come back os.chdir(curdir) # Generate output files fname_dmri_moco = os.path.join(path_out, file_data + param.suffix + ext_data) sct.create_folder(path_out) sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file( os.path.join(path_tmp, dmri_name + param.suffix + ext), os.path.join(path_out, file_data + param.suffix + ext_data), param.verbose) sct.generate_output_file( os.path.join(path_tmp, "b0_mean.nii"), os.path.join(path_out, 'b0' + param.suffix + '_mean' + ext_data), param.verbose) sct.generate_output_file( os.path.join(path_tmp, "dwi_mean.nii"), os.path.join(path_out, 'dwi' + param.suffix + '_mean' + ext_data), param.verbose) # Delete temporary files if param.remove_temp_files == 1: sct.printv('\nDelete temporary files...', param.verbose) sct.rmtree(path_tmp, verbose=param.verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv( '\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's', param.verbose) sct.display_viewer_syntax([fname_dmri_moco, file_data], mode='ortho,ortho')
def main(args=None): # initialize parameters param = Param() # call main function parser = get_parser() if args: arguments = parser.parse_args(args) else: arguments = parser.parse_args(args=None if sys.argv[1:] else ['--help']) fname_data = arguments.i fname_bvecs = arguments.bvec average = arguments.a verbose = int(arguments.v) init_sct(log_level=verbose, update=True) # Update log level remove_temp_files = arguments.r path_out = arguments.ofolder fname_bvals = arguments.bval if arguments.bvalmin: param.bval_min = arguments.bvalmin # Initialization start_time = time.time() # printv(arguments) printv('\nInput parameters:', verbose) printv(' input file ............' + fname_data, verbose) printv(' bvecs file ............' + fname_bvecs, verbose) printv(' bvals file ............' + fname_bvals, verbose) printv(' average ...............' + str(average), verbose) # Get full path fname_data = os.path.abspath(fname_data) fname_bvecs = os.path.abspath(fname_bvecs) if fname_bvals: fname_bvals = os.path.abspath(fname_bvals) # Extract path, file and extension path_data, file_data, ext_data = extract_fname(fname_data) # create temporary folder path_tmp = tmp_create(basename="dmri_separate") # copy files into tmp folder and convert to nifti printv('\nCopy files into temporary folder...', verbose) ext = '.nii' dmri_name = 'dmri' b0_name = file_data + '_b0' b0_mean_name = b0_name + '_mean' dwi_name = file_data + '_dwi' dwi_mean_name = dwi_name + '_mean' if not convert(fname_data, os.path.join(path_tmp, dmri_name + ext)): printv('ERROR in convert.', 1, 'error') copy(fname_bvecs, os.path.join(path_tmp, "bvecs"), verbose=verbose) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # Get size of data im_dmri = Image(dmri_name + ext) printv('\nGet dimensions data...', verbose) nx, ny, nz, nt, px, py, pz, pt = im_dmri.dim printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt), verbose) # Identify b=0 and DWI images printv(fname_bvals) index_b0, index_dwi, nb_b0, nb_dwi = identify_b0(fname_bvecs, fname_bvals, param.bval_min, verbose) # Split into T dimension printv('\nSplit along T dimension...', verbose) im_dmri_split_list = split_data(im_dmri, 3) for im_d in im_dmri_split_list: im_d.save() # Merge b=0 images printv('\nMerge b=0...', verbose) from sct_image import concat_data l = [] for it in range(nb_b0): l.append(dmri_name + '_T' + str(index_b0[it]).zfill(4) + ext) im_out = concat_data(l, 3).save(b0_name + ext) # Average b=0 images if average: printv('\nAverage b=0...', verbose) run_proc(['sct_maths', '-i', b0_name + ext, '-o', b0_mean_name + ext, '-mean', 't'], verbose) # Merge DWI l = [] for it in range(nb_dwi): l.append(dmri_name + '_T' + str(index_dwi[it]).zfill(4) + ext) im_out = concat_data(l, 3).save(dwi_name + ext) # Average DWI images if average: printv('\nAverage DWI...', verbose) run_proc(['sct_maths', '-i', dwi_name + ext, '-o', dwi_mean_name + ext, '-mean', 't'], verbose) # come back os.chdir(curdir) # Generate output files fname_b0 = os.path.abspath(os.path.join(path_out, b0_name + ext_data)) fname_dwi = os.path.abspath(os.path.join(path_out, dwi_name + ext_data)) fname_b0_mean = os.path.abspath(os.path.join(path_out, b0_mean_name + ext_data)) fname_dwi_mean = os.path.abspath(os.path.join(path_out, dwi_mean_name + ext_data)) printv('\nGenerate output files...', verbose) generate_output_file(os.path.join(path_tmp, b0_name + ext), fname_b0, verbose=verbose) generate_output_file(os.path.join(path_tmp, dwi_name + ext), fname_dwi, verbose=verbose) if average: generate_output_file(os.path.join(path_tmp, b0_mean_name + ext), fname_b0_mean, verbose=verbose) generate_output_file(os.path.join(path_tmp, dwi_mean_name + ext), fname_dwi_mean, verbose=verbose) # Remove temporary files if remove_temp_files == 1: printv('\nRemove temporary files...', verbose) rmtree(path_tmp, verbose=verbose) # display elapsed time elapsed_time = time.time() - start_time printv('\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's', verbose) return fname_b0, fname_b0_mean, fname_dwi, fname_dwi_mean
def main(args=None): # Initialization # fname_anat = '' # fname_centerline = '' sigma = 3 # default value of the standard deviation for the Gaussian smoothing (in terms of number of voxels) # remove_temp_files = param.remove_temp_files # verbose = param.verbose start_time = time.time() parser = get_parser() arguments = parser.parse(sys.argv[1:]) fname_anat = arguments['-i'] fname_centerline = arguments['-s'] if '-smooth' in arguments: sigma = arguments['-smooth'] if '-r' in arguments: remove_temp_files = int(arguments['-r']) if '-v' in arguments: verbose = int(arguments['-v']) # Display arguments sct.printv('\nCheck input arguments...') sct.printv(' Volume to smooth .................. ' + fname_anat) sct.printv(' Centerline ........................ ' + fname_centerline) sct.printv(' Sigma (mm) ........................ ' + str(sigma)) sct.printv(' Verbose ........................... ' + str(verbose)) # Check that input is 3D: from msct_image import Image nx, ny, nz, nt, px, py, pz, pt = Image(fname_anat).dim dim = 4 # by default, will be adjusted later if nt == 1: dim = 3 if nz == 1: dim = 2 if dim == 4: sct.printv( 'WARNING: the input image is 4D, please split your image to 3D before smoothing spinalcord using :\n' 'sct_image -i ' + fname_anat + ' -split t -o ' + fname_anat, verbose, 'warning') sct.printv('4D images not supported, aborting ...', verbose, 'error') # Extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) path_centerline, file_centerline, ext_centerline = sct.extract_fname( fname_centerline) # create temporary folder sct.printv('\nCreate temporary folder...', verbose) path_tmp = sct.slash_at_the_end('tmp.' + time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir ' + path_tmp, verbose) # Copying input data to tmp folder sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) sct.run('cp ' + fname_anat + ' ' + path_tmp + 'anat' + ext_anat, verbose) sct.run( 'cp ' + fname_centerline + ' ' + path_tmp + 'centerline' + ext_centerline, verbose) # go to tmp folder os.chdir(path_tmp) # convert to nii format convert('anat' + ext_anat, 'anat.nii') convert('centerline' + ext_centerline, 'centerline.nii') # Change orientation of the input image into RPI sct.printv('\nOrient input volume to RPI orientation...') fname_anat_rpi = set_orientation('anat.nii', 'RPI', filename=True) move(fname_anat_rpi, 'anat_rpi.nii') # Change orientation of the input image into RPI sct.printv('\nOrient centerline to RPI orientation...') fname_centerline_rpi = set_orientation('centerline.nii', 'RPI', filename=True) move(fname_centerline_rpi, 'centerline_rpi.nii') # Straighten the spinal cord # straighten segmentation sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose) # check if warp_curve2straight and warp_straight2curve already exist (i.e. no need to do it another time) if os.path.isfile('../warp_curve2straight.nii.gz') and os.path.isfile( '../warp_straight2curve.nii.gz') and os.path.isfile( '../straight_ref.nii.gz'): # if they exist, copy them into current folder sct.printv( 'WARNING: Straightening was already run previously. Copying warping fields...', verbose, 'warning') shutil.copy('../warp_curve2straight.nii.gz', 'warp_curve2straight.nii.gz') shutil.copy('../warp_straight2curve.nii.gz', 'warp_straight2curve.nii.gz') shutil.copy('../straight_ref.nii.gz', 'straight_ref.nii.gz') # apply straightening sct.run( 'sct_apply_transfo -i anat_rpi.nii -w warp_curve2straight.nii.gz -d straight_ref.nii.gz -o anat_rpi_straight.nii -x spline', verbose) else: sct.run( 'sct_straighten_spinalcord -i anat_rpi.nii -s centerline_rpi.nii -qc 0 -x spline', verbose) # Smooth the straightened image along z sct.printv('\nSmooth the straightened image along z...') sct.run( 'sct_maths -i anat_rpi_straight.nii -smooth 0,0,' + str(sigma) + ' -o anat_rpi_straight_smooth.nii', verbose) # Apply the reversed warping field to get back the curved spinal cord sct.printv( '\nApply the reversed warping field to get back the curved spinal cord...' ) sct.run( 'sct_apply_transfo -i anat_rpi_straight_smooth.nii -o anat_rpi_straight_smooth_curved.nii -d anat.nii -w warp_straight2curve.nii.gz -x spline', verbose) # replace zeroed voxels by original image (issue #937) sct.printv('\nReplace zeroed voxels by original image...', verbose) nii_smooth = Image('anat_rpi_straight_smooth_curved.nii') data_smooth = nii_smooth.data data_input = Image('anat.nii').data indzero = np.where(data_smooth == 0) data_smooth[indzero] = data_input[indzero] nii_smooth.data = data_smooth nii_smooth.setFileName('anat_rpi_straight_smooth_curved_nonzero.nii') nii_smooth.save() # come back to parent folder os.chdir('..') # Generate output file sct.printv('\nGenerate output file...') sct.generate_output_file( path_tmp + '/anat_rpi_straight_smooth_curved_nonzero.nii', file_anat + '_smooth' + ext_anat) # Remove temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...') sct.run('rm -rf ' + path_tmp) # Display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's\n') # to view results sct.printv('Done! To view results, type:', verbose) sct.printv('fslview ' + file_anat + ' ' + file_anat + '_smooth &\n', verbose, 'info')
def main(args=None): # Initialization # fname_anat = '' # fname_centerline = '' sigma = 3 # default value of the standard deviation for the Gaussian smoothing (in terms of number of voxels) param = Param() # remove_temp_files = param.remove_temp_files # verbose = param.verbose start_time = time.time() parser = get_parser() arguments = parser.parse(sys.argv[1:]) fname_anat = arguments['-i'] fname_centerline = arguments['-s'] if '-smooth' in arguments: sigma = arguments['-smooth'] if '-param' in arguments: param.update(arguments['-param']) if '-r' in arguments: remove_temp_files = int(arguments['-r']) if '-v' in arguments: verbose = int(arguments['-v']) # Display arguments sct.printv('\nCheck input arguments...') sct.printv(' Volume to smooth .................. ' + fname_anat) sct.printv(' Centerline ........................ ' + fname_centerline) sct.printv(' Sigma (mm) ........................ ' + str(sigma)) sct.printv(' Verbose ........................... ' + str(verbose)) # Check that input is 3D: from spinalcordtoolbox.image import Image nx, ny, nz, nt, px, py, pz, pt = Image(fname_anat).dim dim = 4 # by default, will be adjusted later if nt == 1: dim = 3 if nz == 1: dim = 2 if dim == 4: sct.printv( 'WARNING: the input image is 4D, please split your image to 3D before smoothing spinalcord using :\n' 'sct_image -i ' + fname_anat + ' -split t -o ' + fname_anat, verbose, 'warning') sct.printv('4D images not supported, aborting ...', verbose, 'error') # Extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) path_centerline, file_centerline, ext_centerline = sct.extract_fname( fname_centerline) path_tmp = sct.tmp_create(basename="smooth_spinalcord", verbose=verbose) # Copying input data to tmp folder sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) sct.copy(fname_anat, os.path.join(path_tmp, "anat" + ext_anat)) sct.copy(fname_centerline, os.path.join(path_tmp, "centerline" + ext_centerline)) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # convert to nii format convert('anat' + ext_anat, 'anat.nii') convert('centerline' + ext_centerline, 'centerline.nii') # Change orientation of the input image into RPI sct.printv('\nOrient input volume to RPI orientation...') fname_anat_rpi = msct_image.Image("anat.nii") \ .change_orientation("RPI", generate_path=True) \ .save() \ .absolutepath # Change orientation of the input image into RPI sct.printv('\nOrient centerline to RPI orientation...') fname_centerline_rpi = msct_image.Image("centerline.nii") \ .change_orientation("RPI", generate_path=True) \ .save() \ .absolutepath # Straighten the spinal cord # straighten segmentation sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose) cache_sig = sct.cache_signature( input_files=[fname_anat_rpi, fname_centerline_rpi], input_params={"x": "spline"}, ) cachefile = os.path.join(curdir, "straightening.cache") if sct.cache_valid(cachefile, cache_sig) and os.path.isfile( os.path.join( curdir, 'warp_curve2straight.nii.gz')) and os.path.isfile( os.path.join( curdir, 'warp_straight2curve.nii.gz')) and os.path.isfile( os.path.join(curdir, 'straight_ref.nii.gz')): # if they exist, copy them into current folder sct.printv('Reusing existing warping field which seems to be valid', verbose, 'warning') sct.copy(os.path.join(curdir, 'warp_curve2straight.nii.gz'), 'warp_curve2straight.nii.gz') sct.copy(os.path.join(curdir, 'warp_straight2curve.nii.gz'), 'warp_straight2curve.nii.gz') sct.copy(os.path.join(curdir, 'straight_ref.nii.gz'), 'straight_ref.nii.gz') # apply straightening sct.run([ 'sct_apply_transfo', '-i', fname_anat_rpi, '-w', 'warp_curve2straight.nii.gz', '-d', 'straight_ref.nii.gz', '-o', 'anat_rpi_straight.nii', '-x', 'spline' ], verbose) else: sct.run([ 'sct_straighten_spinalcord', '-i', fname_anat_rpi, '-o', 'anat_rpi_straight.nii', '-s', fname_centerline_rpi, '-x', 'spline', '-param', 'algo_fitting=' + param.algo_fitting ], verbose) sct.cache_save(cachefile, cache_sig) # Smooth the straightened image along z sct.printv('\nSmooth the straightened image along z...') sct.run([ 'sct_maths', '-i', 'anat_rpi_straight.nii', '-smooth', '0,0,' + str(sigma), '-o', 'anat_rpi_straight_smooth.nii' ], verbose) # Apply the reversed warping field to get back the curved spinal cord sct.printv( '\nApply the reversed warping field to get back the curved spinal cord...' ) sct.run([ 'sct_apply_transfo', '-i', 'anat_rpi_straight_smooth.nii', '-o', 'anat_rpi_straight_smooth_curved.nii', '-d', 'anat.nii', '-w', 'warp_straight2curve.nii.gz', '-x', 'spline' ], verbose) # replace zeroed voxels by original image (issue #937) sct.printv('\nReplace zeroed voxels by original image...', verbose) nii_smooth = Image('anat_rpi_straight_smooth_curved.nii') data_smooth = nii_smooth.data data_input = Image('anat.nii').data indzero = np.where(data_smooth == 0) data_smooth[indzero] = data_input[indzero] nii_smooth.data = data_smooth nii_smooth.save('anat_rpi_straight_smooth_curved_nonzero.nii') # come back os.chdir(curdir) # Generate output file sct.printv('\nGenerate output file...') sct.generate_output_file( os.path.join(path_tmp, "anat_rpi_straight_smooth_curved_nonzero.nii"), file_anat + '_smooth' + ext_anat) # Remove temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...') sct.rmtree(path_tmp) # Display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's\n') sct.display_viewer_syntax([file_anat, file_anat + '_smooth'], verbose=verbose)
def main(): # Initialization fname_mt0 = '' fname_mt1 = '' file_out = param.file_out # register = param.register # remove_tmp_files = param.remove_tmp_files # verbose = param.verbose # get path of the toolbox # status, path_sct = commands.getstatusoutput('echo $SCT_DIR') # Check input parameters parser = get_parser() arguments = parser.parse(sys.argv[1:]) fname_mt0 = arguments['-mt0'] fname_mt1 = arguments['-mt1'] remove_tmp_files = int(arguments['-r']) verbose = int(arguments['-v']) # Extract path/file/extension path_mt0, file_mt0, ext_mt0 = sct.extract_fname(fname_mt0) path_out, file_out, ext_out = '', file_out, ext_mt0 # create temporary folder path_tmp = sct.tmp_create() # Copying input data to tmp folder and convert to nii sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) from sct_convert import convert convert(fname_mt0, path_tmp + 'mt0.nii', type='float32') convert(fname_mt1, path_tmp + 'mt1.nii', type='float32') # go to tmp folder os.chdir(path_tmp) # compute MTR sct.printv('\nCompute MTR...', verbose) from msct_image import Image nii_mt1 = Image('mt1.nii') data_mt1 = nii_mt1.data data_mt0 = Image('mt0.nii').data data_mtr = 100 * (data_mt0 - data_mt1) / data_mt0 # save MTR file nii_mtr = nii_mt1 nii_mtr.data = data_mtr nii_mtr.setFileName('mtr.nii') nii_mtr.save() # sct.run(fsloutput+'fslmaths -dt double mt0.nii -sub mt1.nii -mul 100 -div mt0.nii -thr 0 -uthr 100 mtr.nii', verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(path_tmp + 'mtr.nii', path_out + file_out + ext_out) # Remove temporary files if remove_tmp_files == 1: sct.printv('\nRemove temporary files...') sct.run('rm -rf ' + path_tmp) # to view results sct.printv('\nDone! To view results, type:', verbose) sct.printv( 'fslview ' + fname_mt0 + ' ' + fname_mt1 + ' ' + file_out + ' &\n', verbose, 'info')
def crop_with_gui(self): import matplotlib.pyplot as plt import matplotlib.image as mpimg # Initialization fname_data = self.input_filename suffix_out = '_crop' remove_temp_files = self.rm_tmp_files verbose = self.verbose # Check file existence sct.printv('\nCheck file existence...', verbose) sct.check_file_exist(fname_data, verbose) # Get dimensions of data sct.printv('\nGet dimensions of data...', verbose) nx, ny, nz, nt, px, py, pz, pt = Image(fname_data).dim sct.printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), verbose) # check if 4D data if not nt == 1: sct.printv( '\nERROR in ' + os.path.basename(__file__) + ': Data should be 3D.\n', 1, 'error') sys.exit(2) # sct.printv(arguments) sct.printv('\nCheck parameters:') sct.printv(' data ................... ' + fname_data) # Extract path/file/extension path_data, file_data, ext_data = sct.extract_fname(fname_data) path_out, file_out, ext_out = '', file_data + suffix_out, ext_data path_tmp = sct.tmp_create() + "/" # copy files into tmp folder from sct_convert import convert sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) convert(fname_data, os.path.join(path_tmp, "data.nii")) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # change orientation sct.printv('\nChange orientation to RPI...', verbose) Image('data.nii').change_orientation("RPI").save('data_rpi.nii') # get image of medial slab sct.printv('\nGet image of medial slab...', verbose) image_array = nibabel.load('data_rpi.nii').get_data() nx, ny, nz = image_array.shape scipy.misc.imsave('image.jpg', image_array[math.floor(nx / 2), :, :]) # Display the image sct.printv('\nDisplay image and get cropping region...', verbose) fig = plt.figure() # fig = plt.gcf() # ax = plt.gca() ax = fig.add_subplot(111) img = mpimg.imread("image.jpg") implot = ax.imshow(img.T) implot.set_cmap('gray') plt.gca().invert_yaxis() # mouse callback ax.set_title( 'Left click on the top and bottom of your cropping field.\n Right click to remove last point.\n Close window when your done.' ) line, = ax.plot([], [], 'ro') # empty line cropping_coordinates = LineBuilder(line) plt.show() # disconnect callback # fig.canvas.mpl_disconnect(line) # check if user clicked two times if len(cropping_coordinates.xs) != 2: sct.printv( '\nERROR: You have to select two points. Exit program.\n', 1, 'error') sys.exit(2) # convert coordinates to integer zcrop = [int(i) for i in cropping_coordinates.ys] # sort coordinates zcrop.sort() # crop image sct.printv('\nCrop image...', verbose) nii = Image('data_rpi.nii') data_crop = nii.data[:, :, zcrop[0]:zcrop[1]] nii.data = data_crop nii.absolutepath = 'data_rpi_crop.nii' nii.save() # come back os.chdir(curdir) sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(os.path.join(path_tmp, "data_rpi_crop.nii"), os.path.join(path_out, file_out + ext_out)) # Remove temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...') sct.rmtree(path_tmp) sct.display_viewer_syntax( files=[os.path.join(path_out, file_out + ext_out)])
def main(): # Initialization fname_anat = '' fname_centerline = '' fwhm = param.fwhm width=param.width remove_temp_files = param.remove_temp_files start_time = time.time() verbose = param.verbose # extract path of the script path_script = os.path.dirname(__file__) + '/' # Parameters for debug mode if param.debug == 1: print '\n*** WARNING: DEBUG MODE ON ***\n' fname_anat = '/home/django/ibouchard/errsm_22_t2_cropped_rpi.nii.gz' fname_centerline = '/home/django/ibouchard//errsm_22_t2_cropped_centerline.nii.gz' fwhm=1 width=20 # Check input param try: opts, args = getopt.getopt(sys.argv[1:], 'hi:c:f:w:r:') except getopt.GetoptError as err: print str(err) usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ('-i'): fname_anat = arg elif opt in ('-c'): fname_centerline = arg elif opt in ('-f'): fwhm = int(arg) elif opt in ('w'): width=int(arg) elif opt in ('-r'): remove_temp_files = int(arg) # display usage if a mandatory argument is not provided if fname_anat == '' or fname_centerline == '': usage() # check existence of input files sct.check_file_exist(fname_anat) sct.check_file_exist(fname_centerline) # extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) # extract path/file/extension path_centerline, file_centerline, ext_centerline = sct.extract_fname(fname_centerline) # Display arguments print '\nCheck input arguments...' print '.. Anatomical image: ' + fname_anat print '.. Centerline: ' + fname_centerline print '.. Full width at half maximum: ' + str(fwhm) print '.. Width of the square window: ' + str(width) # create temporary folder sct.printv('\nCreate temporary folder...', verbose) path_tmp = sct.slash_at_the_end('tmp.'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+path_tmp, verbose) # Copying input data to tmp folder and convert to nii sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) sct.run('cp '+fname_anat+' '+path_tmp+'data'+ext_anat, verbose) sct.run('cp '+fname_centerline+' '+path_tmp+'centerline'+ext_centerline, verbose) # go to tmp folder os.chdir(path_tmp) # convert to nii format convert('data'+ext_anat, 'data.nii') convert('centerline'+ext_centerline, 'centerline.nii') # # Get dimensions of data # sct.printv('\nGet dimensions of data...', param.verbose) # nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim # # #Delete existing tmp file in the current folder to avoid problems # #Delete existing tmp file in the current folder to avoid problems # if os.path.isfile('tmp.anat.nii'): # sct.run('rm tmp.anat.nii') # if os.path.isfile('tmp.centerline.nii'): # sct.run('rm tmp.centerline.nii') # # # Convert to nii and delete nii.gz if still existing # print '\nCopy input data...' # sct.run('cp ' + fname_anat + ' tmp.anat'+ext_anat) # convert('data'+ext_data, 'data.nii') # # sct.run('fslchfiletype NIFTI tmp.anat') # if os.path.isfile('tmp.anat.nii.gz'): # sct.run('rm tmp.anat.nii.gz') # print '.. Anatomical image copied' # sct.run('cp ' + fname_centerline + ' tmp.centerline'+ext_centerline) # sct.run('fslchfiletype NIFTI tmp.centerline') # if os.path.isfile('tmp.centerline.nii.gz'): # sct.run('rm tmp.centerline.nii.gz') # print '.. Centerline image copied' # Open anatomical image #========================================================================================== # Reorient input anatomical volume into RL PA IS orientation print '\nReorient input volume to RL PA IS orientation...' sct.run(sct.fsloutput + 'fslswapdim tmp.anat RL PA IS tmp.anat_orient') print '\nGet dimensions of input anatomical image...' nx_a, ny_a, nz_a, nt_a, px_a, py_a, pz_a, pt_a = sct.get_dimension('tmp.anat_orient') #nx_a, ny_a, nz_a, nt_a, px_a, py_a, pz_a, pt_a = sct.get_dimension(fname_anat) print '.. matrix size: ' + str(nx_a) + ' x ' + str(ny_a) + ' x ' + str(nz_a) print '.. voxel size: ' + str(px_a) + 'mm x ' + str(py_a) + 'mm x ' + str(pz_a) + 'mm' print '\nOpen anatomical volume...' file = nibabel.load('tmp.anat_orient.nii') #file = nibabel.load(fname_anat) data_anat = file.get_data() data_anat=np.array(data_anat) data_anat_smoothed=np.copy(data_anat) # Open centerline #========================================================================================== # Reorient binary point into RL PA IS orientation print '\nReorient centerline volume into RL PA IS orientation...' sct.run(sct.fsloutput + 'fslswapdim tmp.centerline RL PA IS tmp.centerline_orient') print '\nGet dimensions of input centerline...' nx, ny, nz, nt, px, py, pz, pt = sct.get_dimension('tmp.centerline_orient') #nx, ny, nz, nt, px, py, pz, pt = sct.get_dimension(fname_centerline) print '.. matrix size: ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) print '.. voxel size: ' + str(px) + 'mm x ' + str(py) + 'mm x ' + str(pz) + 'mm' print '\nOpen centerline volume...' file = nibabel.load('tmp.centerline_orient.nii') #file = nibabel.load(fname_centerline) data_centerline = file.get_data() #Loop across z and associate x,y coordinate with the point having maximum intensity x_centerline = [0 for iz in range(0, nz, 1)] y_centerline = [0 for iz in range(0, nz, 1)] z_centerline = [iz for iz in range(0, nz, 1)] for iz in range(0, nz, 1): x_centerline[iz], y_centerline[iz] = np.unravel_index(data_centerline[:, :, iz].argmax(), data_centerline[:, :, iz].shape) del data_centerline # Fit polynomial function through centerline #========================================================================================== #Fit centerline in the Z-X plane using polynomial function print '\nFit centerline in the Z-X plane using polynomial function...' coeffsx = np.polyfit(z_centerline, x_centerline, deg=param.deg_poly) polyx = np.poly1d(coeffsx) x_centerline_fit = np.polyval(polyx, z_centerline) #Fit centerline in the Z-Y plane using polynomial function print '\nFit centerline in the Z-Y plane using polynomial function...' coeffsy = np.polyfit(z_centerline, y_centerline, deg=param.deg_poly) polyy = np.poly1d(coeffsy) y_centerline_fit = np.polyval(polyy, z_centerline) # Find tangent function of centerline along z #========================================================================================== # Find tangent to centerline in zx plane, along z print '\nFind tangent to centerline along z, in the Z-X plane...' poly_tangent_xz = np.polyder(polyx) tangent_xz = np.polyval(poly_tangent_xz, z_centerline) # Find tangent to centerline in zy plane, along z print '\nFind tangent to centerline along z, in the Z-Y plane...' poly_tangent_yz = np.polyder(polyy) tangent_yz = np.polyval(poly_tangent_yz, z_centerline) # Create a Gaussian kernel with users parameters #========================================================================================== print '\nGenerate a Gaussian kernel with users parameters... ' # Convert the fwhm given by users in standard deviation (sigma) and find the size of gaussian kernel knowing # that size_kernel=(6*sigma-1) must be odd sigma = int(np.round((fwhm/pz_a)*(math.sqrt(1/(2*(math.log(2))))))) size_kernel= (np.round(6*sigma)) if size_kernel%2==0: size_kernel=size_kernel-1 #Creates an 1D-array impulsion and apply a gaussian filter. The result is a Gaussian kernel. kernel_temp = np.zeros(size_kernel) kernel_temp[math.ceil(size_kernel/2)] = 1 kernel= ndimage.filters.gaussian_filter1d(kernel_temp, sigma, order=0) sum_kernel=np.sum(kernel) print '.. Full width at half maximum: ' + str(fwhm) print '.. Kernel size : '+str(size_kernel) print '.. Sigma (Standard deviation): ' + str(sigma) del kernel_temp ## Smooth along the spinal cord ##========================================================================================== print '\nSmooth along the spinal cord...' print '\n Voxel position along z axis...' # Initialisations position=np.zeros(3) flag=np.zeros((nx_a,ny_a,nz_a)) data_weight=np.ones((nx_a,ny_a,nz_a)) smoothing_array=np.zeros(size_kernel) x_near=np.zeros(2) y_near=np.zeros(2) z_near=np.zeros(2) floor_position=np.zeros(3) ceil_position=np.zeros(3) position_d=np.zeros(3) #For every voxel along z axis, for iz in range(0,nz_a,1): print '.. '+str(iz+1)+ '/'+str(nz_a) # Determine the square area to smooth around the centerline xmin=x_centerline[iz]-int(width/2) xmax=x_centerline[iz]+int(width/2) ymin=y_centerline[iz]-int(width/2) ymax=y_centerline[iz]+int(width/2) #Find the angle between the tangent and the x axis in xz plane. theta_xz = -(math.atan(tangent_xz[iz])) #Find the angle between the tangent and the y axis in yz plane. theta_yz = -(math.atan(tangent_yz[iz])) #Construct a rotation array around y axis. Rxz=np.zeros((3,3)) Rxz[1,1]=1 Rxz[0,0]=(math.cos(theta_xz)) Rxz[2,0]=(math.sin(theta_xz)) Rxz[0,2]=-(math.sin(theta_xz)) Rxz[2,2]=(math.cos(theta_xz)) #Construct a rotation array around x axis. Ryz=np.zeros((3,3)) Ryz[0,0]=1 Ryz[1,1]=(math.cos(theta_yz)) Ryz[1,2]=(math.sin(theta_yz)) Ryz[2,1]=-(math.sin(theta_yz)) Ryz[2,2]=(math.cos(theta_yz)) #For every voxels in the given plane, included in the square area for ix in range(xmin,xmax,1): for iy in range(ymin,ymax,1): #The area to smooth has the same high as the 1D mask length isize=0 centerline_point=[np.copy(x_centerline[iz]), np.copy(y_centerline[iz]), np.copy(iz)] #For every voxels along the line orthogonal to the considered plane and included in the kernel. #(Here we full a vector called smoothing_array, which has the same length as the kernel, is oriented in the direction of centerline and contains interpolated values of intensity) for isize in range(0,size_kernel, 1): #Find the position in the xy plane, before rotation position = [ix, iy, iz+isize-(np.floor(size_kernel/2))] #Find the position after rotation by multiplying the position centered on centerline point with rotation array around x and y axis. new_position= np.dot((np.dot((np.subtract(np.copy(position),centerline_point)), Rxz)), Ryz) + centerline_point #If the resulting voxel is out of image boundaries, pad the smoothing array with a zero if (new_position[0]<0)or (new_position[1]<0)or(new_position[2]<0)or(new_position[0]>nx_a-1)or (new_position[1]>ny_a-1)or(new_position[2]>nz_a-1): smoothing_array[isize]=0 #Otherwise, fill the smoothing array with the linear interpolation of values around the actual position else: # Trilinear interpolation #========================================================================================================================================== # Determine the coordinates in grid surrounding the position of the central voxel and perform a trilinear interpolation x_near[0]=np.copy(np.floor(new_position[0])) x_near[1]=np.copy(np.ceil(new_position[0])) xd=(new_position[0]-x_near[0]) y_near[0]=np.copy(np.floor(new_position[1])) y_near[1]=np.copy(np.ceil(new_position[1])) yd=(new_position[1]-y_near[0]) z_near[0]=np.copy(np.floor(new_position[2])) z_near[1]=np.copy(np.ceil(new_position[2])) zd=(new_position[2]-z_near[0]) c00=((data_anat[x_near[0],y_near[0],z_near[0]])*(1-xd))+((data_anat[x_near[1],y_near[0],z_near[0]])*(xd)) c10=((data_anat[x_near[0],y_near[1],z_near[0]])*(1-xd))+((data_anat[x_near[1],y_near[1],z_near[0]])*(xd)) c01=((data_anat[x_near[0],y_near[0],z_near[1]])*(1-xd))+((data_anat[x_near[1],y_near[0],z_near[1]])*(xd)) c11=((data_anat[x_near[0],y_near[1],z_near[1]])*(1-xd))+((data_anat[x_near[1],y_near[1],z_near[1]])*(xd)) c0=c00*(1-yd)+c10*yd c1=c01*(1-yd)+c11*yd smoothing_array[isize]=c0*(1-zd)+c1*zd #If actual position is in the z=z_centerline plane, save the coordinates in the variable central_position. (Otherwise, don't save it). if isize==(np.floor(size_kernel/2)): central_position=np.copy(new_position) #If the central_position is out of boundaries, don't consider it anymore. if (central_position[0]<0)or (central_position[1]<0)or(central_position[2]<0)or(central_position[0]>nx_a-1)or (central_position[1]>ny_a-1)or(central_position[2]>nz_a-1): continue else: #Otherwise, perform the convolution of the smoothing_array and the kernel for the central voxel only (equivalent to element-wise multiply). Normalize the result. result=((np.sum(np.copy(smoothing_array)*kernel))/sum_kernel) # Determine the coordinates in grid surrounding the position of the central voxel for i in range(0,3,1): floor_position[i]=math.floor(central_position[i]) ceil_position[i]=math.ceil(central_position[i]) position_d[i]=central_position[i]-floor_position[i] # Reverse trilinear interpolation #========================================================================================================================================== # Split the resuling intensity given by the convolution between the 8 voxels surrounding the point where the convolution is calculated (central_position). # The array data_anat_smoothed is the the volume os the anatomical image smoothed alog the spinal cord. # The array flag is a volume that indicates if a the corresponding voxel in the anatomical image is inside the smoothing area around the spinal cord and if there is already been an operation on this voxel. # The default value of flag is 0. If it is set to 1, it means there is an operation on the corresponding voxel in anatomical image. Then we clear both the data_anat_smoothed and data_weight corresponding voxel to 0. # The array data_weight represent the is represent the sum of weights used to calculate the intensity for every voxel. In a perfect case, this sum would be 1, but because there is an angle between # two adjacent planes, the sum will be lower so we need to normalize the result. The default value for data_weight is 1, but once there is an operation on the corresponding voxel (flag=1), we accumulate the weights used. if (flag[ceil_position[0],ceil_position[1],ceil_position[2]]==0): data_anat_smoothed[ceil_position[0],ceil_position[1],ceil_position[2]]=0 data_weight[ceil_position[0],ceil_position[1],ceil_position[2]]=0 flag[ceil_position[0],ceil_position[1],ceil_position[2]]=1 weight=(position_d[0])*(position_d[1])*(position_d[2]) data_anat_smoothed[ceil_position[0],ceil_position[1],ceil_position[2]]=data_anat_smoothed[ceil_position[0],ceil_position[1],ceil_position[2]]+(weight*result) data_weight[ceil_position[0],ceil_position[1],ceil_position[2]]=data_weight[ceil_position[0],ceil_position[1],ceil_position[2]]+(weight) if (flag[floor_position[0],floor_position[1],floor_position[2]]==0): data_anat_smoothed[floor_position[0],floor_position[1],floor_position[2]]=0 data_weight[floor_position[0],floor_position[1],floor_position[2]]=0 flag[floor_position[0],floor_position[1],floor_position[2]]=1 weight=(1-position_d[0])*(1-position_d[1])*(1-position_d[2]) data_anat_smoothed[floor_position[0],floor_position[1],floor_position[2]]=data_anat_smoothed[floor_position[0],floor_position[1],floor_position[2]]+(weight*result) data_weight[floor_position[0],floor_position[1],floor_position[2]]=data_weight[floor_position[0],floor_position[1],floor_position[2]]+(weight) if (flag[ceil_position[0],floor_position[1],floor_position[2]]==0): data_anat_smoothed[ceil_position[0],floor_position[1],floor_position[2]]=0 data_weight[ceil_position[0],floor_position[1],floor_position[2]]=0 flag[ceil_position[0],floor_position[1],floor_position[2]]=1 weight=(position_d[0])*(1-position_d[1])*(1-position_d[2]) data_anat_smoothed[ceil_position[0],floor_position[1],floor_position[2]]=data_anat_smoothed[ceil_position[0],floor_position[1],floor_position[2]]+(weight*result) data_weight[ceil_position[0],floor_position[1],floor_position[2]]=data_weight[ceil_position[0],floor_position[1],floor_position[2]]+(weight) if (flag[ceil_position[0],ceil_position[1],floor_position[2]]==0): data_anat_smoothed[ceil_position[0],ceil_position[1],floor_position[2]]=0 data_weight[ceil_position[0],ceil_position[1],floor_position[2]]=0 flag[ceil_position[0],ceil_position[1],floor_position[2]]=1 weight=(position_d[0])*(position_d[1])*(1-position_d[2]) data_anat_smoothed[ceil_position[0],ceil_position[1],floor_position[2]]=data_anat_smoothed[ceil_position[0],ceil_position[1],floor_position[2]]+(weight*result) data_weight[ceil_position[0],ceil_position[1],floor_position[2]]=data_weight[ceil_position[0],ceil_position[1],floor_position[2]]+(weight) if (flag[ceil_position[0],floor_position[1],ceil_position[2]]==0): data_anat_smoothed[ceil_position[0],floor_position[1],ceil_position[2]]=0 data_weight[ceil_position[0],floor_position[1],ceil_position[2]]=0 flag[ceil_position[0],floor_position[1],ceil_position[2]]=1 weight=(position_d[0])*(1-position_d[1])*(position_d[2]) data_anat_smoothed[ceil_position[0],floor_position[1],ceil_position[2]]=data_anat_smoothed[ceil_position[0],floor_position[1],ceil_position[2]]+(weight*result) data_weight[ceil_position[0],floor_position[1],ceil_position[2]]=data_weight[ceil_position[0],floor_position[1],ceil_position[2]]+(weight) if (flag[floor_position[0],ceil_position[1],floor_position[2]]==0): data_anat_smoothed[floor_position[0],ceil_position[1],floor_position[2]]=0 data_weight[floor_position[0],ceil_position[1],floor_position[2]]=0 flag[floor_position[0],ceil_position[1],floor_position[2]]=1 weight=(1-position_d[0])*(position_d[1])*(1-position_d[2]) data_anat_smoothed[floor_position[0],ceil_position[1],floor_position[2]]=data_anat_smoothed[floor_position[0],ceil_position[1],floor_position[2]]+(weight*result) data_weight[floor_position[0],ceil_position[1],floor_position[2]]=data_weight[floor_position[0],ceil_position[1],floor_position[2]]+(weight) if (flag[floor_position[0],ceil_position[1],ceil_position[2]]==0): data_anat_smoothed[floor_position[0],ceil_position[1],ceil_position[2]]=0 data_weight[floor_position[0],ceil_position[1],ceil_position[2]]=0 flag[floor_position[0],ceil_position[1],ceil_position[2]]=1 weight=(1-position_d[0])*(position_d[1])*(position_d[2]) data_anat_smoothed[floor_position[0],ceil_position[1], ceil_position[2]]= data_anat_smoothed[floor_position[0],ceil_position[1], ceil_position[2]]+(weight*result) data_weight[floor_position[0],ceil_position[1], ceil_position[2]]= data_weight[floor_position[0],ceil_position[1], ceil_position[2]]+(weight) if (flag[floor_position[0],floor_position[1],ceil_position[2]]==0): data_anat_smoothed[floor_position[0],floor_position[1],ceil_position[2]]=0 flag[floor_position[0],floor_position[1],ceil_position[2]]=1 data_weight[floor_position[0],floor_position[1],ceil_position[2]]=0 weight=(1-position_d[0])*(1-position_d[1])*(position_d[2]) data_anat_smoothed[floor_position[0],floor_position[1],ceil_position[2]]=data_anat_smoothed[floor_position[0],floor_position[1],ceil_position[2]]+(weight*result) data_weight[floor_position[0],floor_position[1],ceil_position[2]]=data_weight[floor_position[0],floor_position[1],ceil_position[2]]+(weight) # Once we covered the whole spinal cord along z, we normalize the resulting image considering the weight used to calculate each voxel intensity data_anat_smoothed=data_anat_smoothed/data_weight #Generate output file #========================================================================================== # Write NIFTI volumes print '\nWrite NIFTI volumes...' if os.path.isfile('tmp.im_smoothed.nii'): sct.run('rm tmp.im_smoothed.nii') img = nibabel.Nifti1Image(data_anat_smoothed, None) nibabel.save(img, 'tmp.im_smoothed.nii') print '.. File created: tmp.im_smoothed.nii' #Copy header geometry from input data print '\nCopy header geometry from input data and reorient the volume...' sct.run(sct.fsloutput+'fslcpgeom tmp.anat_orient.nii tmp.im_smoothed.nii ') #Generate output file print '\nGenerate output file (in current folder)...' sct.generate_output_file('tmp.im_smoothed.nii','./',file_anat+'_smoothed',ext_anat) # Delete temporary files if remove_temp_files == 1: print '\nDelete temporary files...' sct.run('rm tmp.anat.nii') sct.run('rm tmp.centerline.nii') sct.run('rm tmp.anat_orient.nii') sct.run('rm tmp.centerline_orient.nii') #Display elapsed time elapsed_time = time.time() - start_time print '\nFinished!' print '.. '+str(int(round(elapsed_time)))+'s\n'
def crop_with_gui(self): import matplotlib.pyplot as plt import matplotlib.image as mpimg # Initialization fname_data = self.input_filename suffix_out = '_crop' remove_temp_files = self.rm_tmp_files verbose = self.verbose # Check file existence sct.printv('\nCheck file existence...', verbose) sct.check_file_exist(fname_data, verbose) # Get dimensions of data sct.printv('\nGet dimensions of data...', verbose) nx, ny, nz, nt, px, py, pz, pt = Image(fname_data).dim sct.printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), verbose) # check if 4D data if not nt == 1: sct.printv('\nERROR in ' + os.path.basename(__file__) + ': Data should be 3D.\n', 1, 'error') sys.exit(2) # sct.printv(arguments) sct.printv('\nCheck parameters:') sct.printv(' data ................... ' + fname_data) # Extract path/file/extension path_data, file_data, ext_data = sct.extract_fname(fname_data) path_out, file_out, ext_out = '', file_data + suffix_out, ext_data path_tmp = sct.tmp_create() + "/" # copy files into tmp folder from sct_convert import convert sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) convert(fname_data, os.path.join(path_tmp, "data.nii")) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # change orientation sct.printv('\nChange orientation to RPI...', verbose) Image('data.nii').change_orientation("RPI").save('data_rpi.nii') # get image of medial slab sct.printv('\nGet image of medial slab...', verbose) image_array = nibabel.load('data_rpi.nii').get_data() nx, ny, nz = image_array.shape scipy.misc.imsave('image.jpg', image_array[math.floor(nx / 2), :, :]) # Display the image sct.printv('\nDisplay image and get cropping region...', verbose) fig = plt.figure() # fig = plt.gcf() # ax = plt.gca() ax = fig.add_subplot(111) img = mpimg.imread("image.jpg") implot = ax.imshow(img.T) implot.set_cmap('gray') plt.gca().invert_yaxis() # mouse callback ax.set_title('Left click on the top and bottom of your cropping field.\n Right click to remove last point.\n Close window when your done.') line, = ax.plot([], [], 'ro') # empty line cropping_coordinates = LineBuilder(line) plt.show() # disconnect callback # fig.canvas.mpl_disconnect(line) # check if user clicked two times if len(cropping_coordinates.xs) != 2: sct.printv('\nERROR: You have to select two points. Exit program.\n', 1, 'error') sys.exit(2) # convert coordinates to integer zcrop = [int(i) for i in cropping_coordinates.ys] # sort coordinates zcrop.sort() # crop image sct.printv('\nCrop image...', verbose) nii = Image('data_rpi.nii') data_crop = nii.data[:, :, zcrop[0]:zcrop[1]] nii.data = data_crop nii.absolutepath = 'data_rpi_crop.nii' nii.save() # come back os.chdir(curdir) sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(os.path.join(path_tmp, "data_rpi_crop.nii"), os.path.join(path_out, file_out + ext_out)) # Remove temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...') sct.rmtree(path_tmp) sct.display_viewer_syntax(files=[os.path.join(path_out, file_out + ext_out)])
def create_mask(): fsloutput = "export FSLOUTPUTTYPE=NIFTI; " # for faster processing, all outputs are in NIFTI # display usage if a mandatory argument is not provided if param.fname_data == "" or param.method == "": sct.printv("\nERROR: All mandatory arguments are not provided. See usage (add -h).\n", 1, "error") # parse argument for method method_list = param.method.replace(" ", "").split(",") # remove spaces and parse with comma # method_list = param.method.split(',') # parse with comma method_type = method_list[0] # check existence of method type if not method_type in param.method_list: sct.printv( "\nERROR in " + os.path.basename(__file__) + ': Method "' + method_type + '" is not recognized. See usage (add -h).\n', 1, "error", ) # check method val if not method_type == "center": method_val = method_list[1] del method_list # check existence of shape if not param.shape in param.shape_list: sct.printv( "\nERROR in " + os.path.basename(__file__) + ': Shape "' + param.shape + '" is not recognized. See usage (add -h).\n', 1, "error", ) # check existence of input files sct.printv("\ncheck existence of input files...", param.verbose) sct.check_file_exist(param.fname_data, param.verbose) if method_type == "centerline": sct.check_file_exist(method_val, param.verbose) # check if orientation is RPI sct.printv("\nCheck if orientation is RPI...", param.verbose) status, output = sct.run("sct_orientation -i " + param.fname_data) if not output == "RPI": sct.printv( "\nERROR in " + os.path.basename(__file__) + ": Orientation of input image should be RPI. Use sct_orientation to put your image in RPI.\n", 1, "error", ) # display input parameters sct.printv("\nInput parameters:", param.verbose) sct.printv(" data .................." + param.fname_data, param.verbose) sct.printv(" method ................" + method_type, param.verbose) # Extract path/file/extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) # Get output folder and file name if param.fname_out == "": param.fname_out = param.file_prefix + file_data + ext_data # fname_out = os.path.abspath(path_out+file_out+ext_out) # create temporary folder sct.printv("\nCreate temporary folder...", param.verbose) path_tmp = sct.slash_at_the_end("tmp." + time.strftime("%y%m%d%H%M%S"), 1) sct.run("mkdir " + path_tmp, param.verbose) # Copying input data to tmp folder and convert to nii # NB: cannot use c3d here because c3d cannot convert 4D data. sct.printv("\nCopying input data to tmp folder and convert to nii...", param.verbose) convert(param.fname_data, path_tmp + "data.nii") # sct.run('cp '+param.fname_data+' '+path_tmp+'data'+ext_data, param.verbose) if method_type == "centerline": convert(method_val, path_tmp + "centerline.nii.gz") # sct.run('isct_c3d '+method_val+' -o '+path_tmp+'/centerline.nii.gz') # go to tmp folder os.chdir(path_tmp) # Get dimensions of data sct.printv("\nGet dimensions of data...", param.verbose) nx, ny, nz, nt, px, py, pz, pt = Image("data.nii").dim sct.printv(" " + str(nx) + " x " + str(ny) + " x " + str(nz) + " x " + str(nt), param.verbose) # in case user input 4d data if nt != 1: sct.printv( "WARNING in " + os.path.basename(__file__) + ": Input image is 4d but output mask will 3D.", param.verbose, "warning", ) # extract first volume to have 3d reference nii = Image("data.nii") data3d = nii.data[:, :, :, 0] nii.data = data3d nii.save() if method_type == "coord": # parse to get coordinate coord = map(int, method_val.split("x")) if method_type == "point": # get file name fname_point = method_val # extract coordinate of point sct.printv("\nExtract coordinate of point...", param.verbose) status, output = sct.run("sct_label_utils -i " + fname_point + " -t display-voxel", param.verbose) # parse to get coordinate coord = output[output.find("Position=") + 10 : -17].split(",") if method_type == "center": # set coordinate at center of FOV coord = round(float(nx) / 2), round(float(ny) / 2) if method_type == "centerline": # get name of centerline from user argument fname_centerline = "centerline.nii.gz" else: # generate volume with line along Z at coordinates 'coord' sct.printv("\nCreate line...", param.verbose) fname_centerline = create_line("data.nii", coord, nz) # create mask sct.printv("\nCreate mask...", param.verbose) centerline = nibabel.load(fname_centerline) # open centerline hdr = centerline.get_header() # get header hdr.set_data_dtype("uint8") # set imagetype to uint8 data_centerline = centerline.get_data() # get centerline z_centerline = [iz for iz in range(0, nz, 1) if data_centerline[:, :, iz].any()] nz = len(z_centerline) # get center of mass of the centerline cx = [0] * nz cy = [0] * nz for iz in range(0, nz, 1): cx[iz], cy[iz] = ndimage.measurements.center_of_mass(numpy.array(data_centerline[:, :, z_centerline[iz]])) # create 2d masks file_mask = "data_mask" for iz in range(nz): center = numpy.array([cx[iz], cy[iz]]) mask2d = create_mask2d(center, param.shape, param.size, nx, ny) # Write NIFTI volumes img = nibabel.Nifti1Image(mask2d, None, hdr) nibabel.save(img, (file_mask + str(iz) + ".nii")) # merge along Z # cmd = 'fslmerge -z mask ' cmd = "sct_concat_data -dim z -o mask.nii.gz -i " for iz in range(nz): cmd = cmd + file_mask + str(iz) + ".nii," # remove ',' at the end of the string cmd = cmd[:-1] status, output = sct.run(cmd, param.verbose) # copy geometry copy_header("data.nii", "mask.nii.gz") # come back to parent folder os.chdir("..") # Generate output files sct.printv("\nGenerate output files...", param.verbose) sct.generate_output_file(path_tmp + "mask.nii.gz", param.fname_out) # Remove temporary files if param.remove_tmp_files == 1: sct.printv("\nRemove temporary files...", param.verbose) sct.run("rm -rf " + path_tmp, param.verbose) # to view results sct.printv("\nDone! To view results, type:", param.verbose) sct.printv("fslview " + param.fname_data + " " + param.fname_out + " -l Red -t 0.5 &", param.verbose, "info") print
def main(args=None): if not args: args = sys.argv[1:] # initialize parameters param = Param() # call main function parser = get_parser() arguments = parser.parse(args) fname_data = arguments['-i'] fname_bvecs = arguments['-bvec'] average = arguments['-a'] verbose = int(arguments.get('-v')) sct.init_sct(log_level=verbose, update=True) # Update log level remove_temp_files = int(arguments['-r']) path_out = arguments['-ofolder'] if '-bval' in arguments: fname_bvals = arguments['-bval'] else: fname_bvals = '' if '-bvalmin' in arguments: param.bval_min = arguments['-bvalmin'] # Initialization start_time = time.time() # sct.printv(arguments) sct.printv('\nInput parameters:', verbose) sct.printv(' input file ............' + fname_data, verbose) sct.printv(' bvecs file ............' + fname_bvecs, verbose) sct.printv(' bvals file ............' + fname_bvals, verbose) sct.printv(' average ...............' + str(average), verbose) # Get full path fname_data = os.path.abspath(fname_data) fname_bvecs = os.path.abspath(fname_bvecs) if fname_bvals: fname_bvals = os.path.abspath(fname_bvals) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(fname_data) # create temporary folder path_tmp = sct.tmp_create(basename="dmri_separate", verbose=verbose) # copy files into tmp folder and convert to nifti sct.printv('\nCopy files into temporary folder...', verbose) ext = '.nii' dmri_name = 'dmri' b0_name = file_data + '_b0' b0_mean_name = b0_name + '_mean' dwi_name = file_data + '_dwi' dwi_mean_name = dwi_name + '_mean' if not convert(fname_data, os.path.join(path_tmp, dmri_name + ext)): sct.printv('ERROR in convert.', 1, 'error') sct.copy(fname_bvecs, os.path.join(path_tmp, "bvecs"), verbose=verbose) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # Get size of data im_dmri = Image(dmri_name + ext) sct.printv('\nGet dimensions data...', verbose) nx, ny, nz, nt, px, py, pz, pt = im_dmri.dim sct.printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt), verbose) # Identify b=0 and DWI images sct.printv(fname_bvals) index_b0, index_dwi, nb_b0, nb_dwi = identify_b0(fname_bvecs, fname_bvals, param.bval_min, verbose) # Split into T dimension sct.printv('\nSplit along T dimension...', verbose) im_dmri_split_list = split_data(im_dmri, 3) for im_d in im_dmri_split_list: im_d.save() # Merge b=0 images sct.printv('\nMerge b=0...', verbose) from sct_image import concat_data l = [] for it in range(nb_b0): l.append(dmri_name + '_T' + str(index_b0[it]).zfill(4) + ext) im_out = concat_data(l, 3).save(b0_name + ext) # Average b=0 images if average: sct.printv('\nAverage b=0...', verbose) sct.run(['sct_maths', '-i', b0_name + ext, '-o', b0_mean_name + ext, '-mean', 't'], verbose) # Merge DWI l = [] for it in range(nb_dwi): l.append(dmri_name + '_T' + str(index_dwi[it]).zfill(4) + ext) im_out = concat_data(l, 3).save(dwi_name + ext) # Average DWI images if average: sct.printv('\nAverage DWI...', verbose) sct.run(['sct_maths', '-i', dwi_name + ext, '-o', dwi_mean_name + ext, '-mean', 't'], verbose) # come back os.chdir(curdir) # Generate output files fname_b0 = os.path.abspath(os.path.join(path_out, b0_name + ext_data)) fname_dwi = os.path.abspath(os.path.join(path_out, dwi_name + ext_data)) fname_b0_mean = os.path.abspath(os.path.join(path_out, b0_mean_name + ext_data)) fname_dwi_mean = os.path.abspath(os.path.join(path_out, dwi_mean_name + ext_data)) sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(os.path.join(path_tmp, b0_name + ext), fname_b0, verbose) sct.generate_output_file(os.path.join(path_tmp, dwi_name + ext), fname_dwi, verbose) if average: sct.generate_output_file(os.path.join(path_tmp, b0_mean_name + ext), fname_b0_mean, verbose) sct.generate_output_file(os.path.join(path_tmp, dwi_mean_name + ext), fname_dwi_mean, verbose) # Remove temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...', verbose) sct.rmtree(path_tmp, verbose=verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's', verbose) return fname_b0, fname_b0_mean, fname_dwi, fname_dwi_mean
def main(): # Initialization fname_data = '' interp_factor = param.interp_factor remove_temp_files = param.remove_temp_files verbose = param.verbose suffix = param.suffix smoothing_sigma = param.smoothing_sigma # start timer start_time = time.time() # Parameters for debug mode if param.debug: fname_data = os.path.join(sct.__data_dir__, 'sct_testing_data', 't2', 't2_seg.nii.gz') remove_temp_files = 0 param.mask_size = 10 else: # Check input parameters try: opts, args = getopt.getopt(sys.argv[1:], 'hi:v:r:s:') except getopt.GetoptError: usage() if not opts: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ('-i'): fname_data = arg elif opt in ('-r'): remove_temp_files = int(arg) elif opt in ('-s'): smoothing_sigma = arg elif opt in ('-v'): verbose = int(arg) # display usage if a mandatory argument is not provided if fname_data == '': usage() # sct.printv(arguments) sct.printv('\nCheck parameters:') sct.printv(' segmentation ........... ' + fname_data) sct.printv(' interp factor .......... ' + str(interp_factor)) sct.printv(' smoothing sigma ........ ' + str(smoothing_sigma)) # check existence of input files sct.printv('\nCheck existence of input files...') sct.check_file_exist(fname_data, verbose) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(fname_data) path_tmp = sct.tmp_create(basename="binary_to_trilinear", verbose=verbose) from sct_convert import convert sct.printv('\nCopying input data to tmp folder and convert to nii...', param.verbose) convert(fname_data, os.path.join(path_tmp, "data.nii")) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # Get dimensions of data sct.printv('\nGet dimensions of data...', verbose) nx, ny, nz, nt, px, py, pz, pt = Image('data.nii').dim sct.printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), verbose) # upsample data sct.printv('\nUpsample data...', verbose) sct.run(["sct_resample", "-i", "data.nii", "-x", "linear", "-vox", str(nx * interp_factor) + 'x' + str(ny * interp_factor) + 'x' + str(nz * interp_factor), "-o", "data_up.nii"], verbose) # Smooth along centerline sct.printv('\nSmooth along centerline...', verbose) sct.run(["sct_smooth_spinalcord", "-i", "data_up.nii", "-s", "data_up.nii", "-smooth", str(smoothing_sigma), "-r", str(remove_temp_files), "-v", str(verbose)], verbose) # downsample data sct.printv('\nDownsample data...', verbose) sct.run(["sct_resample", "-i", "data_up_smooth.nii", "-x", "linear", "-vox", str(nx) + 'x' + str(ny) + 'x' + str(nz), "-o", "data_up_smooth_down.nii"], verbose) # come back os.chdir(curdir) # Generate output files sct.printv('\nGenerate output files...') fname_out = sct.generate_output_file(os.path.join(path_tmp, "data_up_smooth_down.nii"), '' + file_data + suffix + ext_data) # Delete temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...') sct.rmtree(path_tmp) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's') # to view results sct.printv('\nTo view results, type:') sct.printv('fslview ' + file_data + ' ' + file_data + suffix + ' &\n')
def main(args=None): # Initialization param = Param() start_time = time.time() parser = get_parser() arguments = parser.parse(sys.argv[1:]) fname_anat = arguments['-i'] fname_centerline = arguments['-s'] if '-smooth' in arguments: sigma = arguments['-smooth'] if '-param' in arguments: param.update(arguments['-param']) if '-r' in arguments: remove_temp_files = int(arguments['-r']) verbose = int(arguments.get('-v')) sct.init_sct(log_level=verbose, update=True) # Update log level # Display arguments sct.printv('\nCheck input arguments...') sct.printv(' Volume to smooth .................. ' + fname_anat) sct.printv(' Centerline ........................ ' + fname_centerline) sct.printv(' Sigma (mm) ........................ ' + str(sigma)) sct.printv(' Verbose ........................... ' + str(verbose)) # Check that input is 3D: from spinalcordtoolbox.image import Image nx, ny, nz, nt, px, py, pz, pt = Image(fname_anat).dim dim = 4 # by default, will be adjusted later if nt == 1: dim = 3 if nz == 1: dim = 2 if dim == 4: sct.printv('WARNING: the input image is 4D, please split your image to 3D before smoothing spinalcord using :\n' 'sct_image -i ' + fname_anat + ' -split t -o ' + fname_anat, verbose, 'warning') sct.printv('4D images not supported, aborting ...', verbose, 'error') # Extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) path_centerline, file_centerline, ext_centerline = sct.extract_fname(fname_centerline) path_tmp = sct.tmp_create(basename="smooth_spinalcord", verbose=verbose) # Copying input data to tmp folder sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) sct.copy(fname_anat, os.path.join(path_tmp, "anat" + ext_anat)) sct.copy(fname_centerline, os.path.join(path_tmp, "centerline" + ext_centerline)) # go to tmp folder curdir = os.getcwd() os.chdir(path_tmp) # convert to nii format convert('anat' + ext_anat, 'anat.nii') convert('centerline' + ext_centerline, 'centerline.nii') # Change orientation of the input image into RPI sct.printv('\nOrient input volume to RPI orientation...') fname_anat_rpi = msct_image.Image("anat.nii") \ .change_orientation("RPI", generate_path=True) \ .save() \ .absolutepath # Change orientation of the input image into RPI sct.printv('\nOrient centerline to RPI orientation...') fname_centerline_rpi = msct_image.Image("centerline.nii") \ .change_orientation("RPI", generate_path=True) \ .save() \ .absolutepath # Straighten the spinal cord # straighten segmentation sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose) cache_sig = sct.cache_signature(input_files=[fname_anat_rpi, fname_centerline_rpi], input_params={"x": "spline"}) cachefile = os.path.join(curdir, "straightening.cache") if sct.cache_valid(cachefile, cache_sig) and os.path.isfile(os.path.join(curdir, 'warp_curve2straight.nii.gz')) and os.path.isfile(os.path.join(curdir, 'warp_straight2curve.nii.gz')) and os.path.isfile(os.path.join(curdir, 'straight_ref.nii.gz')): # if they exist, copy them into current folder sct.printv('Reusing existing warping field which seems to be valid', verbose, 'warning') sct.copy(os.path.join(curdir, 'warp_curve2straight.nii.gz'), 'warp_curve2straight.nii.gz') sct.copy(os.path.join(curdir, 'warp_straight2curve.nii.gz'), 'warp_straight2curve.nii.gz') sct.copy(os.path.join(curdir, 'straight_ref.nii.gz'), 'straight_ref.nii.gz') # apply straightening sct.run(['sct_apply_transfo', '-i', fname_anat_rpi, '-w', 'warp_curve2straight.nii.gz', '-d', 'straight_ref.nii.gz', '-o', 'anat_rpi_straight.nii', '-x', 'spline'], verbose) else: sct.run(['sct_straighten_spinalcord', '-i', fname_anat_rpi, '-o', 'anat_rpi_straight.nii', '-s', fname_centerline_rpi, '-x', 'spline', '-param', 'algo_fitting='+param.algo_fitting], verbose) sct.cache_save(cachefile, cache_sig) # move warping fields locally (to use caching next time) sct.copy('warp_curve2straight.nii.gz', os.path.join(curdir, 'warp_curve2straight.nii.gz')) sct.copy('warp_straight2curve.nii.gz', os.path.join(curdir, 'warp_straight2curve.nii.gz')) # Smooth the straightened image along z sct.printv('\nSmooth the straightened image...') sigma_smooth = ",".join([str(i) for i in sigma]) sct_maths.main(args=['-i', 'anat_rpi_straight.nii', '-smooth', sigma_smooth, '-o', 'anat_rpi_straight_smooth.nii', '-v', '0']) # Apply the reversed warping field to get back the curved spinal cord sct.printv('\nApply the reversed warping field to get back the curved spinal cord...') sct.run(['sct_apply_transfo', '-i', 'anat_rpi_straight_smooth.nii', '-o', 'anat_rpi_straight_smooth_curved.nii', '-d', 'anat.nii', '-w', 'warp_straight2curve.nii.gz', '-x', 'spline'], verbose) # replace zeroed voxels by original image (issue #937) sct.printv('\nReplace zeroed voxels by original image...', verbose) nii_smooth = Image('anat_rpi_straight_smooth_curved.nii') data_smooth = nii_smooth.data data_input = Image('anat.nii').data indzero = np.where(data_smooth == 0) data_smooth[indzero] = data_input[indzero] nii_smooth.data = data_smooth nii_smooth.save('anat_rpi_straight_smooth_curved_nonzero.nii') # come back os.chdir(curdir) # Generate output file sct.printv('\nGenerate output file...') sct.generate_output_file(os.path.join(path_tmp, "anat_rpi_straight_smooth_curved_nonzero.nii"), file_anat + '_smooth' + ext_anat) # Remove temporary files if remove_temp_files == 1: sct.printv('\nRemove temporary files...') sct.rmtree(path_tmp) # Display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(np.round(elapsed_time))) + 's\n') sct.display_viewer_syntax([file_anat, file_anat + '_smooth'], verbose=verbose)
def main(args=None): if not args: args = sys.argv[1:] # initialize parameters param = Param() # call main function parser = get_parser() arguments = parser.parse(args) fname_data = arguments['-i'] fname_bvecs = arguments['-bvec'] average = arguments['-a'] verbose = int(arguments['-v']) remove_tmp_files = int(arguments['-r']) path_out = arguments['-ofolder'] if '-bval' in arguments: fname_bvals = arguments['-bval'] else: fname_bvals = '' if '-bvalmin' in arguments: param.bval_min = arguments['-bvalmin'] # Initialization start_time = time.time() # sct.printv(arguments) sct.printv('\nInput parameters:', verbose) sct.printv(' input file ............' + fname_data, verbose) sct.printv(' bvecs file ............' + fname_bvecs, verbose) sct.printv(' bvals file ............' + fname_bvals, verbose) sct.printv(' average ...............' + str(average), verbose) # Get full path fname_data = os.path.abspath(fname_data) fname_bvecs = os.path.abspath(fname_bvecs) if fname_bvals: fname_bvals = os.path.abspath(fname_bvals) # Extract path, file and extension path_data, file_data, ext_data = sct.extract_fname(fname_data) # # get output folder # if path_out == '': # path_out = '' # create temporary folder sct.printv('\nCreate temporary folder...', verbose) path_tmp = sct.slash_at_the_end('tmp.' + time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir ' + path_tmp, verbose) # copy files into tmp folder and convert to nifti sct.printv('\nCopy files into temporary folder...', verbose) ext = '.nii' dmri_name = 'dmri' b0_name = 'b0' b0_mean_name = b0_name + '_mean' dwi_name = 'dwi' dwi_mean_name = dwi_name + '_mean' from sct_convert import convert if not convert(fname_data, path_tmp + dmri_name + ext): sct.printv('ERROR in convert.', 1, 'error') sct.run('cp ' + fname_bvecs + ' ' + path_tmp + 'bvecs', verbose) # go to tmp folder os.chdir(path_tmp) # Get size of data im_dmri = Image(dmri_name + ext) sct.printv('\nGet dimensions data...', verbose) nx, ny, nz, nt, px, py, pz, pt = im_dmri.dim sct.printv('.. ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) + ' x ' + str(nt), verbose) # Identify b=0 and DWI images sct.printv(fname_bvals) index_b0, index_dwi, nb_b0, nb_dwi = identify_b0(fname_bvecs, fname_bvals, param.bval_min, verbose) # Split into T dimension sct.printv('\nSplit along T dimension...', verbose) im_dmri_split_list = split_data(im_dmri, 3) for im_d in im_dmri_split_list: im_d.save() # Merge b=0 images sct.printv('\nMerge b=0...', verbose) cmd = 'sct_image -concat t -o ' + b0_name + ext + ' -i ' for it in range(nb_b0): cmd = cmd + dmri_name + '_T' + str(index_b0[it]).zfill(4) + ext + ',' cmd = cmd[:-1] # remove ',' at the end of the string # WARNING: calling concat_data in python instead of in command line causes a non understood issue status, output = sct.run(cmd, param.verbose) # Average b=0 images if average: sct.printv('\nAverage b=0...', verbose) sct.run('sct_maths -i ' + b0_name + ext + ' -o ' + b0_mean_name + ext + ' -mean t', verbose) # Merge DWI cmd = 'sct_image -concat t -o ' + dwi_name + ext + ' -i ' for it in range(nb_dwi): cmd = cmd + dmri_name + '_T' + str(index_dwi[it]).zfill(4) + ext + ',' cmd = cmd[:-1] # remove ',' at the end of the string # WARNING: calling concat_data in python instead of in command line causes a non understood issue status, output = sct.run(cmd, param.verbose) # Average DWI images if average: sct.printv('\nAverage DWI...', verbose) sct.run('sct_maths -i ' + dwi_name + ext + ' -o ' + dwi_mean_name + ext + ' -mean t', verbose) # if not average_data_across_dimension('dwi.nii', 'dwi_mean.nii', 3): # sct.printv('ERROR in average_data_across_dimension', 1, 'error') # sct.run(fsloutput + 'fslmaths dwi -Tmean dwi_mean', verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(path_tmp + b0_name + ext, path_out + b0_name + ext_data, verbose) sct.generate_output_file(path_tmp + dwi_name + ext, path_out + dwi_name + ext_data, verbose) if average: sct.generate_output_file(path_tmp + b0_mean_name + ext, path_out + b0_mean_name + ext_data, verbose) sct.generate_output_file(path_tmp + dwi_mean_name + ext, path_out + dwi_mean_name + ext_data, verbose) # Remove temporary files if remove_tmp_files == 1: sct.printv('\nRemove temporary files...', verbose) sct.run('rm -rf ' + path_tmp, verbose) # display elapsed time elapsed_time = time.time() - start_time sct.printv('\nFinished! Elapsed time: ' + str(int(round(elapsed_time))) + 's', verbose) # to view results sct.printv('\nTo view results, type: ', verbose) if average: sct.printv('fslview b0 b0_mean dwi dwi_mean &\n', verbose) else: sct.printv('fslview b0 dwi &\n', verbose)