def main(): # Initialization path_data = '' xmin = '50' xsize = '100' ymin = '0' ysize = '-1' zmin = '0' zsize = '-1' fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI # Parameters for debug mode if param.debug: print '\n*** WARNING: DEBUG MODE ON ***\n' path_data = '/Volumes/folder_shared/template/t2' path_out = '/Volumes/folder_shared/template/t2_crop' else: # Check input parameters try: opts, args = getopt.getopt(sys.argv[1:], 'hi:o:') except getopt.GetoptError: usage() if not opts: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ("-i"): path_data = arg elif opt in ("-o"): path_out = arg # check input folder sct.check_folder_exist(path_data) # add slash path_data = sct.slash_at_the_end(path_data, 1) path_out = sct.slash_at_the_end(path_out, 1) # create output folder if os.path.exists(path_out): sct.printv('WARNING: Output folder exists. Deleting it.', 1, 'warning') # remove dir shutil.rmtree(path_out) # create dir os.makedirs(path_out) # list all files in folder files = [f for f in glob.glob(path_data+'*.nii.gz')] # for files in glob.glob(path_data+'*.nii.gz'): # print files # crop files one by one (to inform user) for f in files: path_f, file_f, ext_f = sct.extract_fname(f) sct.run('fslroi '+f+' '+path_out+file_f+' '+xmin+' '+xsize+' '+ymin+' '+ysize+' '+zmin+' '+zsize) # to view results print '\nDone!'
def read_json(path_dir, json_requirements=None, fname_json='dataset_description.json'): path_dir = sct.slash_at_the_end(path_dir, slash=1) if fname_json not in os.listdir(path_dir) and json_requirements is not None: accept_subject = False elif json_requirements is None: accept_subject = True else: json_file = open(path_dir+fname_json) dic_info = json.load(json_file) json_file.close() # pass keys and items to lower case dic_info = dict((k.lower(), v.lower()) for k, v in dic_info.iteritems()) # if no condition is not verified, accept subject accept_subject = True # read requirements: list_conditions = json_requirements.split(',') for condition in list_conditions: key, val = condition.split('=') key, val = key.lower(), val.lower() # if key do not exist, do not accept subject if key not in dic_info.keys(): accept_subject = False # if value for this key is not the one required, do not accept subject elif dic_info[key] != val: accept_subject = False return accept_subject
def compute_model(self): printv('\nComputing the model dictionary ...', self.param.verbose, 'normal') # create model folder if os.path.exists(self.param_model.new_model_dir) and os.listdir(self.param_model.new_model_dir) != []: shutil.move(self.param_model.new_model_dir, slash_at_the_end(self.param_model.new_model_dir, slash=0) + '_old') if not os.path.exists(self.param_model.new_model_dir): os.mkdir(self.param_model.new_model_dir) # write model info param_fic = open(self.param_model.new_model_dir + 'info.txt', 'w') param_fic.write('Model computed on '+'-'.join(str(t) for t in time.localtime()[:3])+'\n') param_fic.write(str(self.param_model)) param_fic.write(str(self.param_data)) param_fic.close() printv('\n\tLoading data dictionary ...', self.param.verbose, 'normal') self.load_model_data() self.mean_image = np.mean([dic_slice.im for dic_slice in self.slices], axis=0) printv('\n\tCo-register all the data into a common groupwise space ...', self.param.verbose, 'normal') self.coregister_model_data() printv('\n\tNormalize data intensities against averaged median values in the dictionary ...', self.param.verbose, 'normal') self.normalize_model_data() printv('\nComputing the model reduced space ...', self.param.verbose, 'normal') self.compute_reduced_space() printv('\nSaving model elements ...', self.param.verbose, 'normal') self.save_model()
def create_temporary_path(self): import time from sct_utils import slash_at_the_end path_tmp = slash_at_the_end("tmp." + time.strftime("%y%m%d%H%M%S"), 1) sct.run("mkdir " + path_tmp, self.verbose) return path_tmp
def main(args=None): parser = get_parser() param = Param() arguments = parser.parse(sys.argv[1:]) fname_src = arguments["-d"] fname_transfo = arguments["-w"] warp_atlas = int(arguments["-a"]) warp_spinal_levels = int(arguments["-s"]) folder_out = sct.slash_at_the_end(arguments['-ofolder'], 1) path_template = sct.slash_at_the_end(arguments['-t'], 1) verbose = int(arguments['-v']) qc = int(arguments['-qc']) # call main function WarpTemplate(fname_src, fname_transfo, warp_atlas, warp_spinal_levels, folder_out, path_template, verbose, qc)
def test_function(script_name): if script_name == 'test_debug': return test_debug() # JULIEN else: # Using the retest variable to recheck if we can perform tests after we downloaded the data retest = 1 # while condition values are arbitrary and are present to prevent infinite loop while 0 < retest < 3: # build script name fname_log = script_name + ".log" tmp_script_name = script_name result_folder = "results_"+script_name script_name = "test_"+script_name if retest == 1: # create folder and go in it sct.create_folder(result_folder) os.chdir(result_folder) # display script name print_line('Checking '+script_name) # import function as a module script_tested = importlib.import_module(script_name) # test function status, output = script_tested.test(param.path_data) # returning script_name to its original name script_name = tmp_script_name # manage status if status == 0: print_ok() retest = 0 else: print_fail() print output print "\nTest files missing, downloading them now \n" os.chdir('../..') downloaddata() param.path_data = sct.slash_at_the_end(os.path.abspath(param.path_data), 1) # check existence of testing data folder sct.check_folder_exist(param.path_data) os.chdir(param.path_tmp + result_folder) retest += 1 # log file write_to_log_file(fname_log, output, 'w') # go back to parent folder os.chdir('..') # end while loop # return return status
def __init__(self): self.download = 0 self.path_data = sct.slash_at_the_end(path_sct_testing, 1) self.function_to_test = None # self.function_to_avoid = None self.remove_tmp_file = 0 self.verbose = 1 self.url_git = 'https://github.com/neuropoly/sct_testing_data.git' self.path_tmp = ""
def load_model_data(self): ''' Data should be organized with one folder per subject containing: - A WM/GM contrasted image containing 'im' in its name - a segmentation of the SC containing 'seg' in its name - a/several manual segmentation(s) of GM containing 'gm' in its/their name(s) - a file containing vertebral level information as a nifti image or as a text file containing 'level' in its name ''' path_data = slash_at_the_end(self.param_model.path_data, slash=1) list_sub = [sub for sub in os.listdir(path_data) if os.path.isdir(os.path.join(path_data, sub))] if self.param_model.ind_rm is not None and self.param_model.ind_rm < len(list_sub): list_sub.pop(self.param_model.ind_rm) # total number of slices: J j = 0 for sub in list_sub: # load images of each subject fname_data = None fname_sc_seg = None list_fname_gmseg = [] fname_level = None for file_name in os.listdir(path_data+sub): fname = path_data+sub+'/'+file_name if os.path.isfile(fname): if 'gm' in file_name: list_fname_gmseg.append(fname) elif 'seg' in file_name: fname_sc_seg = fname elif 'im' in file_name: fname_data = fname if 'level' in file_name: fname_level = fname info_data = 'Loaded files: \n' info_data += 'Image: ....... '+str(fname_data)+'\n' info_data += 'SC seg: ...... ' + str(fname_sc_seg)+ '\n' info_data += 'GM seg: ...... ' + str(list_fname_gmseg) + '\n' info_data += 'Levels: ...... ' + str(fname_level) + '\n' if fname_data == None or fname_sc_seg == None or list_fname_gmseg == []: printv(info_data, self.param.verbose, 'error') else: printv(info_data, self.param.verbose, 'normal') # preprocess data list_slices_sub, info = pre_processing(fname_data, fname_sc_seg, fname_level=fname_level, fname_manual_gmseg=list_fname_gmseg, new_res=self.param_data.axial_res, square_size_size_mm=self.param_data.square_size_size_mm, denoising=self.param_data.denoising, for_model=True) for i_slice, slice_sub in enumerate(list_slices_sub): slice_sub.set(slice_id=i_slice+j) self.slices.append(slice_sub) j += len(list_slices_sub)
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 produce_output_files(self): """ Method used to output all debug files at the same time. To be used after the algorithm is executed :return: """ import time from sct_utils import slash_at_the_end path_tmp = slash_at_the_end("scad_output_" + time.strftime("%y%m%d%H%M%S"), 1) sct.run("mkdir " + path_tmp, self.verbose) # getting input image header img = self.input_image.copy() # saving body symmetry img.data = self.raw_symmetry img.change_orientation(self.raw_orientation) img.file_name += "body_symmetry" img.save() # saving minimum paths img.data = self.minimum_path_data img.change_orientation(self.raw_orientation) img.file_name = "min_path" img.save() img.data = self.J1_min_path img.change_orientation(self.raw_orientation) img.file_name = "J1_min_path" img.save() img.data = self.J2_min_path img.change_orientation(self.raw_orientation) img.file_name = "J2_min_path" img.save() # saving minimum path powered img.data = self.minimum_path_powered img.change_orientation(self.raw_orientation) img.file_name = "min_path_powered_" + str(self.minimum_path_exponent) img.save() # saving smoothed min path img = self.smoothed_min_path.copy() img.change_orientation(self.raw_orientation) img.file_name = "min_path_power_" + str(self.minimum_path_exponent) + "_smoothed" img.save() # save symmetry_weighted_minimal_path img.data = self.spine_detect_data img.change_orientation(self.raw_orientation) img.file_name = "symmetry_weighted_minimal_path" img.save()
def produce_output_files(self): import time from sct_utils import slash_at_the_end path_tmp = slash_at_the_end('scad_output_'+time.strftime("%y%m%d%H%M%S"), 1) sct.run('mkdir '+path_tmp, self.verbose) # getting input image header os.chdir(path_tmp) try: img = self.input_image.copy() # saving body symmetry img.data = self.raw_symmetry img.change_orientation(self.raw_orientation) img.file_name += "body_symmetry" img.save() # saving minimum paths img.data = self.minimum_path_data img.change_orientation(self.raw_orientation) img.file_name = "min_path" img.save() img.data = self.J1_min_path img.change_orientation(self.raw_orientation) img.file_name = "J1_min_path" img.save() img.data = self.J2_min_path img.change_orientation(self.raw_orientation) img.file_name = "J2_min_path" img.save() # saving minimum path powered img.data = self.minimum_path_powered img.change_orientation(self.raw_orientation) img.file_name = "min_path_powered_"+str(self.minimum_path_exponent) img.save() # saving smoothed min path img = self.smoothed_min_path.copy() img.change_orientation(self.raw_orientation) img.file_name = "min_path_power_"+str(self.minimum_path_exponent)+"_smoothed" img.save() # save symmetry_weighted_minimal_path img.data = self.spine_detect_data img.change_orientation(self.raw_orientation) img.file_name = "symmetry_weighted_minimal_path" img.save() except Exception, e: raise e
def checkFolderCreation(self, param): # check if the folder exist. If not, create it. sct.printv("Check folder existence...") if self.parser.check_file_exist: result_creation = sct.create_folder(param) else: result_creation = 0 # no need for checking if result_creation == 2: sct.printv("ERROR: Permission denied for folder creation...", type="error") elif result_creation == 1: sct.printv("Folder "+param+" has been created.", 0, type='warning') # add slash at the end param = sct.slash_at_the_end(param, 1) return param
def warp_back_seg(self, path_warp): # get 3D images from list of slices im_dest = self.get_im_from_list(np.array([target_slice.im for target_slice in self.target_im])) im_src_gm = self.get_im_from_list(np.array([target_slice.gm_seg_M for target_slice in self.target_im])) im_src_wm = self.get_im_from_list(np.array([target_slice.wm_seg_M for target_slice in self.target_im])) # fname_dic_space2slice_space = slash_at_the_end(path_warp, slash=1)+'warp_dic2target.nii.gz' interpolation = 'nn' if self.param_seg.type_seg == 'bin' else 'linear' # warp GM im_src_gm_reg = apply_transfo(im_src_gm, im_dest, fname_dic_space2slice_space, interp=interpolation, rm_tmp=self.param.rm_tmp) # warp WM im_src_wm_reg = apply_transfo(im_src_wm, im_dest, fname_dic_space2slice_space, interp=interpolation, rm_tmp=self.param.rm_tmp) for i, target_slice in enumerate(self.target_im): # set GM and WM for each slice target_slice.set(gm_seg=im_src_gm_reg.data[i], wm_seg=im_src_wm_reg.data[i])
def compute_length(fname_segmentation, remove_temp_files, verbose = 0): from math import sqrt # Extract path, file and extension fname_segmentation = os.path.abspath(fname_segmentation) path_data, file_data, ext_data = sct.extract_fname(fname_segmentation) # 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") + '_'+str(randint(1, 1000000)), 1) sct.run('mkdir '+path_tmp, verbose) # copy files into tmp folder sct.run('cp '+fname_segmentation+' '+path_tmp) # go to tmp folder os.chdir(path_tmp) # Change orientation of the input centerline into RPI sct.printv('\nOrient centerline to RPI orientation...', param.verbose) im_seg = Image(file_data+ext_data) fname_segmentation_orient = 'segmentation_rpi' + ext_data im_seg_orient = set_orientation(im_seg, 'RPI') im_seg_orient.setFileName(fname_segmentation_orient) im_seg_orient.save() # Get dimension sct.printv('\nGet dimensions...', param.verbose) nx, ny, nz, nt, px, py, pz, pt = im_seg_orient.dim sct.printv('.. matrix size: '+str(nx)+' x '+str(ny)+' x '+str(nz), param.verbose) sct.printv('.. voxel size: '+str(px)+'mm x '+str(py)+'mm x '+str(pz)+'mm', param.verbose) # smooth segmentation/centerline #x_centerline_fit, y_centerline_fit, z_centerline, x_centerline_deriv,y_centerline_deriv,z_centerline_deriv = smooth_centerline(fname_segmentation_orient, param, 'hanning', 1) x_centerline_fit, y_centerline_fit, z_centerline, x_centerline_deriv,y_centerline_deriv,z_centerline_deriv = smooth_centerline(fname_segmentation_orient, type_window='hanning', window_length=80, algo_fitting='hanning', verbose = verbose) # compute length of centerline result_length = 0.0 for i in range(len(x_centerline_fit)-1): result_length += sqrt(((x_centerline_fit[i+1]-x_centerline_fit[i])*px)**2+((y_centerline_fit[i+1]-y_centerline_fit[i])*py)**2+((z_centerline[i+1]-z_centerline[i])*pz)**2) return result_length
def get_file_label(path_label='', label='', output='file'): """ Get label file name given based on info_label.txt file. Label needs to be a substring of the "name" field. E.g.: T1-weighted, spinal cord, white matter, etc. :param path_label: :param label: :param output: {file, filewithpath} :return: """ # init file_info_label = 'info_label.txt' file_label = '' # make sure there is a slash at the end path_label = sct.slash_at_the_end(path_label, 1) # Open file fname_label = path_label+file_info_label try: f = open(fname_label) except IOError: sct.printv('\nWARNING: Cannot open ' + fname_label, 1, 'warning') # raise else: # Extract lines from file lines = [line for line in f.readlines() if line.strip()] # find line corresponding to label for line in lines: # ignore comment if not line[0] == '#': # check "name" field if label in line.split(',')[1].strip(): file_label = line.split(',')[2].strip() # sct.printv('Found Label ' + label + ' in file: ' + file_label) break if file_label == '': sct.printv('\nWARNING: Label '+label+' not found.', 1, 'warning') # output if output == 'file': return file_label elif output == 'filewithpath': return path_label+file_label
def __init__( self, fname_gm, fname_wm, path_template, fname_warp_template2target, param=None, fname_warp_target2template=None, apply_warp_template=0, ): if param is None: self.param = Param() else: self.param = param self.im_gm = Image(fname_gm) self.im_wm = Image(fname_wm) self.path_template = sct.slash_at_the_end(path_template, 1) if "MNI-Poly-AMU_GM.nii.gz" in os.listdir(self.path_template + "template/"): self.im_template_gm = Image(self.path_template + "template/MNI-Poly-AMU_GM.nii.gz") self.im_template_wm = Image(self.path_template + "template/MNI-Poly-AMU_WM.nii.gz") self.template = "MNI-Poly-AMU" else: self.im_template_gm = Image(self.path_template + "template/PAM50_gm.nii.gz") self.im_template_wm = Image(self.path_template + "template/PAM50_wm.nii.gz") self.template = "PAM50" # Previous warping fields: self.fname_warp_template2target = fname_warp_template2target self.fname_warp_target2template = fname_warp_target2template # new warping fields: self.fname_warp_template2gm = "" self.fname_wwarp_gm2template = "" # temporary fix - related to issue #871 self.apply_warp_template = apply_warp_template
def moco(param): # retrieve parameters fsloutput = 'export FSLOUTPUTTYPE=NIFTI; ' # for faster processing, all outputs are in NIFTI file_data = param.file_data file_target = param.file_target folder_mat = sct.slash_at_the_end(param.mat_moco, 1) # output folder of mat file todo = param.todo suffix = param.suffix #file_schedule = param.file_schedule verbose = param.verbose ext = '.nii' # get path of the toolbox status, path_sct = commands.getstatusoutput('echo $SCT_DIR') # print arguments 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.param[0], param.verbose) sct.printv(' Smoothing kernel ......'+param.param[1], param.verbose) sct.printv(' Gradient step .........'+param.param[2], param.verbose) sct.printv(' Metric ................'+param.param[3], 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('\nGet dimensions data...', verbose) data_im = Image(file_data+ext) nx, ny, nz, nt, px, py, pz, pt = data_im.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) sct.run('cp '+file_target+ext+' target.nii') file_target = 'target' # Split data along T dimension sct.printv('\nSplit data along T dimension...', verbose) data_split_list = split_data(data_im, dim=3) for im in data_split_list: im.save() file_data_splitT = file_data + '_T' # Motion correction: initialization index = np.arange(nt) file_data_splitT_num = [] file_data_splitT_moco_num = [] failed_transfo = [0 for i in range(nt)] file_mat = [[] for i in range(nt)] # Motion correction: Loop across T for indice_index in range(nt): # create indices and display stuff it = index[indice_index] file_data_splitT_num.append(file_data_splitT + str(it).zfill(4)) file_data_splitT_moco_num.append(file_data + suffix + '_T' + str(it).zfill(4)) sct.printv(('\nVolume '+str((it))+'/'+str(nt-1)+':'), verbose) file_mat[it] = folder_mat + 'mat.T' + str(it) # run 3D registration failed_transfo[it] = register(param, file_data_splitT_num[it], file_target, file_mat[it], file_data_splitT_moco_num[it]) # average registered volume with target image # N.B. use weighted averaging: (target * nb_it + moco) / (nb_it + 1) if param.iterative_averaging and indice_index < 10 and failed_transfo[it] == 0: sct.run('sct_maths -i '+file_target+ext+' -mul '+str(indice_index+1)+' -o '+file_target+ext) sct.run('sct_maths -i '+file_target+ext+' -add '+file_data_splitT_moco_num[it]+ext+' -o '+file_target+ext) sct.run('sct_maths -i '+file_target+ext+' -div '+str(indice_index+2)+' -o '+file_target+ext) # Replace failed transformation with the closest good one sct.printv(('\nReplace failed transformations...'), verbose) 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 = [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.run('cp '+file_mat[gT[index_good]]+'Warp.nii.gz'+' '+file_mat[fT[it]]+'Warp.nii.gz') # apply transformation sct.run('sct_apply_transfo -i '+file_data_splitT_num[fT[it]]+'.nii -d '+file_target+'.nii -w '+file_mat[fT[it]]+'Warp.nii.gz'+' -o '+file_data_splitT_moco_num[fT[it]]+'.nii'+' -x '+param.interp, verbose) 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_moco = file_data+suffix if todo != 'estimate': sct.printv('\nMerge data back along T...', verbose) from sct_image import concat_data # im_list = [] fname_list = [] for indice_index in range(len(index)): # im_list.append(Image(file_data_splitT_moco_num[indice_index] + ext)) fname_list.append(file_data_splitT_moco_num[indice_index] + ext) im_out = concat_data(fname_list, 3) im_out.setFileName(file_data_moco + ext) im_out.save() # delete file target.nii (to avoid conflict if this function is run another time) sct.printv('\nRemove temporary file...', verbose) #os.remove('target.nii') sct.run('rm target.nii')
def __init__(self, fname_src, fname_transfo, warp_atlas, warp_spinal_levels, folder_out, path_template, verbose): # Initialization self.fname_src = '' self.fname_transfo = '' self.folder_out = param.folder_out self.path_template = param.path_template self.folder_template = param.folder_template self.folder_atlas = param.folder_atlas self.folder_spinal_levels = param.folder_spinal_levels self.warp_template = param.warp_template self.warp_atlas = param.warp_atlas self.warp_spinal_levels = param.warp_spinal_levels self.verbose = param.verbose start_time = time.time() # Parameters for debug mode if param.debug: print '\n*** WARNING: DEBUG MODE ON ***\n' fname_src = path_sct+'/testing/sct_testing_data/data/mt/mtr.nii.gz' fname_transfo = path_sct+'/testing/sct_testing_data/data/mt/warp_template2mt.nii.gz' warp_atlas = 1 warp_spinal_levels = 1 verbose = 1 else: self.fname_src = fname_src self.fname_transfo = fname_transfo self.warp_atlas = warp_atlas self.warp_spinal_levels = warp_spinal_levels self.folder_out = folder_out self.path_template = path_template self.verbose = verbose # Check file existence sct.printv('\nCheck file existence...', self.verbose) sct.check_file_exist(self.fname_src) sct.check_file_exist(self.fname_transfo) # add slash at the end of folder name (in case there is no slash) self.path_template = sct.slash_at_the_end(self.path_template, 1) self.folder_out = sct.slash_at_the_end(self.folder_out, 1) self.folder_template = sct.slash_at_the_end(self.folder_template, 1) self.folder_atlas = sct.slash_at_the_end(self.folder_atlas, 1) self.folder_spinal_levels = sct.slash_at_the_end(self.folder_spinal_levels, 1) # print arguments print '\nCheck parameters:' print ' Destination image ........ '+self.fname_src print ' Warping field ............ '+self.fname_transfo print ' Path template ............ '+self.path_template print ' Output folder ............ '+self.folder_out+'\n' # Extract path, file and extension path_src, file_src, ext_src = sct.extract_fname(self.fname_src) # create output folder if os.path.exists(self.folder_out): sct.printv('WARNING: Output folder already exists. Deleting it...', self.verbose) sct.run('rm -rf '+self.folder_out) sct.run('mkdir '+self.folder_out) # Warp template objects if self.warp_template == 1: sct.printv('\nWarp template objects...', self.verbose) warp_label(self.path_template, self.folder_template, param.file_info_label, self.fname_src, self.fname_transfo, self.folder_out) # Warp atlas if self.warp_atlas == 1: sct.printv('\nWarp atlas of white matter tracts...', self.verbose) warp_label(self.path_template, self.folder_atlas, param.file_info_label, self.fname_src, self.fname_transfo, self.folder_out) # Warp spinal levels if self.warp_spinal_levels == 1: sct.printv('\nWarp spinal levels...', self.verbose) warp_label(self.path_template, self.folder_spinal_levels, param.file_info_label, self.fname_src, self.fname_transfo, self.folder_out) # to view results sct.printv('\nDone! To view results, type:', self.verbose) sct.printv('fslview '+self.fname_src+' '+self.folder_out+self.folder_template+'MNI-Poly-AMU_T2.nii.gz -b 0,4000 '+self.folder_out+self.folder_template+'MNI-Poly-AMU_level.nii.gz -l MGH-Cortical -t 0.5 '+self.folder_out+self.folder_template+'MNI-Poly-AMU_GM.nii.gz -l Red-Yellow -b 0.5,1 '+self.folder_out+self.folder_template+'MNI-Poly-AMU_WM.nii.gz -l Blue-Lightblue -b 0.5,1 &\n', self.verbose, 'info')
def moco(param): # retrieve parameters fsloutput = "export FSLOUTPUTTYPE=NIFTI; " # for faster processing, all outputs are in NIFTI file_data = param.file_data file_target = param.file_target folder_mat = sct.slash_at_the_end(param.mat_moco, 1) # output folder of mat file todo = param.todo suffix = param.suffix # file_schedule = param.file_schedule verbose = param.verbose ext = ".nii" # get path of the toolbox status, path_sct = commands.getstatusoutput("echo $SCT_DIR") # print arguments 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.param[0], param.verbose) sct.printv(" Smoothing kernel ......" + param.param[1], param.verbose) sct.printv(" Gradient step ........." + param.param[2], param.verbose) sct.printv(" Metric ................" + param.param[3], 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("\nGet dimensions data...", verbose) data_im = Image(file_data + ext) nx, ny, nz, nt, px, py, pz, pt = data_im.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) sct.run("cp " + file_target + ext + " target.nii") file_target = "target" # Split data along T dimension sct.printv("\nSplit data along T dimension...", verbose) data_split_list = split_data(data_im, dim=3) for im in data_split_list: im.save() file_data_splitT = file_data + "_T" # Motion correction: initialization index = np.arange(nt) file_data_splitT_num = [] file_data_splitT_moco_num = [] failed_transfo = [0 for i in range(nt)] file_mat = [[] for i in range(nt)] # Motion correction: Loop across T for indice_index in range(nt): # create indices and display stuff it = index[indice_index] file_data_splitT_num.append(file_data_splitT + str(it).zfill(4)) file_data_splitT_moco_num.append(file_data + suffix + "_T" + str(it).zfill(4)) sct.printv(("\nVolume " + str((it)) + "/" + str(nt - 1) + ":"), verbose) file_mat[it] = folder_mat + "mat.T" + str(it) # run 3D registration failed_transfo[it] = register( param, file_data_splitT_num[it], file_target, file_mat[it], file_data_splitT_moco_num[it] ) # average registered volume with target image # N.B. use weighted averaging: (target * nb_it + moco) / (nb_it + 1) if param.iterative_averaging and indice_index < 10 and failed_transfo[it] == 0: sct.run("sct_maths -i " + file_target + ext + " -mul " + str(indice_index + 1) + " -o " + file_target + ext) sct.run( "sct_maths -i " + file_target + ext + " -add " + file_data_splitT_moco_num[it] + ext + " -o " + file_target + ext ) sct.run("sct_maths -i " + file_target + ext + " -div " + str(indice_index + 2) + " -o " + file_target + ext) # Replace failed transformation with the closest good one sct.printv(("\nReplace failed transformations..."), verbose) 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 = [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.run("cp " + file_mat[gT[index_good]] + "Warp.nii.gz" + " " + file_mat[fT[it]] + "Warp.nii.gz") # apply transformation sct.run( "sct_apply_transfo -i " + file_data_splitT_num[fT[it]] + ".nii -d " + file_target + ".nii -w " + file_mat[fT[it]] + "Warp.nii.gz" + " -o " + file_data_splitT_moco_num[fT[it]] + ".nii" + " -x " + param.interp, verbose, ) 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_moco = file_data + suffix if todo != "estimate": sct.printv("\nMerge data back along T...", verbose) # cmd = fsloutput + 'fslmerge -t ' + file_data_moco # for indice_index in range(len(index)): # cmd = cmd + ' ' + file_data_splitT_moco_num[indice_index] from sct_image import concat_data im_list = [] for indice_index in range(len(index)): im_list.append(Image(file_data_splitT_moco_num[indice_index] + ext)) im_out = concat_data(im_list, 3) im_out.setFileName(file_data_moco + ext) im_out.save()
def main(): # Initialization to defaults parameters fname_data = '' # data is empty by default path_label = '' # empty by default method = param.method # extraction mode by default labels_of_interest = param.labels_of_interest slices_of_interest = param.slices_of_interest vertebral_levels = param.vertebral_levels average_all_labels = param.average_all_labels fname_output = param.fname_output fname_vertebral_labeling = param.fname_vertebral_labeling fname_normalizing_label = '' # optional then default is empty normalization_method = '' # optional then default is empty actual_vert_levels = None # variable used in case the vertebral levels asked by the user don't correspond exactly to the vertebral levels available in the metric data warning_vert_levels = None # variable used to warn the user in case the vertebral levels he asked don't correspond exactly to the vertebral levels available in the metric data verbose = param.verbose flag_h = 0 ml_clusters = param.ml_clusters adv_param = param.adv_param adv_param_user = '' # Parameters for debug mode if param.debug: print '\n*** WARNING: DEBUG MODE ON ***\n' status, path_sct_data = commands.getstatusoutput( 'echo $SCT_TESTING_DATA_DIR') fname_data = '/Users/julien/data/temp/sct_example_data/mt/mtr.nii.gz' path_label = '/Users/julien/data/temp/sct_example_data/mt/label/atlas/' method = 'map' ml_clusters = '0:29,30,31' labels_of_interest = '0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29' slices_of_interest = '' vertebral_levels = '' average_all_labels = 1 fname_normalizing_label = '' #path_sct+'/testing/data/errsm_23/mt/label/template/MNI-Poly-AMU_CSF.nii.gz' normalization_method = '' #'whole' else: # Check input parameters try: opts, args = getopt.getopt( sys.argv[1:], 'haf:i:l:m:n:o:p:v:w:z:') # define flags except getopt.GetoptError as err: # check if the arguments are defined print str(err) # error usage() # display usage if not opts: usage() for opt, arg in opts: # explore flags if opt in '-a': average_all_labels = 1 elif opt in '-f': path_label = os.path.abspath(arg) # save path of labels folder elif opt == '-h': # help option flag_h = 1 elif opt in '-i': fname_data = arg elif opt in '-l': labels_of_interest = arg elif opt in '-m': # method for metric extraction method = arg elif opt in '-n': # filename of the label by which the user wants to normalize fname_normalizing_label = arg elif opt in '-o': # output option fname_output = arg # fname of output file elif opt in '-p': adv_param_user = arg elif opt in '-v': # vertebral levels option, if the user wants to average the metric across specific vertebral levels vertebral_levels = arg elif opt in '-w': # method used for the normalization by the metric estimation into the normalizing label (see flag -n): 'sbs' for slice-by-slice or 'whole' for normalization after estimation in the whole labels normalization_method = arg elif opt in '-z': # slices numbers option slices_of_interest = arg # save labels numbers # Display usage with tract parameters by default in case files aren't chosen in arguments inputs if fname_data == '' or path_label == '' or flag_h: param.path_label = path_label usage() # Check existence of data file sct.printv('\ncheck existence of input files...', verbose) sct.check_file_exist(fname_data) sct.check_folder_exist(path_label) if fname_normalizing_label: sct.check_folder_exist(fname_normalizing_label) # add slash at the end path_label = sct.slash_at_the_end(path_label, 1) # Find path to the vertebral labeling file if vertebral levels were specified by the user if vertebral_levels: if slices_of_interest: # impossible to select BOTH specific slices and specific vertebral levels print '\nERROR: You cannot select BOTH vertebral levels AND slice numbers.' usage() else: fname_vertebral_labeling_list = sct.find_file_within_folder( fname_vertebral_labeling, path_label + '..') if len(fname_vertebral_labeling_list) > 1: print color.red + 'ERROR: More than one file named \'' + fname_vertebral_labeling + ' were found in ' + path_label + '. Exit program.' + color.end sys.exit(2) elif len(fname_vertebral_labeling_list) == 0: print color.red + 'ERROR: No file named \'' + fname_vertebral_labeling + ' were found in ' + path_label + '. Exit program.' + color.end sys.exit(2) else: fname_vertebral_labeling = os.path.abspath( fname_vertebral_labeling_list[0]) # Check input parameters check_method(method, fname_normalizing_label, normalization_method) # parse argument for param if not adv_param_user == '': adv_param = adv_param_user.replace(' ', '').split( ',') # remove spaces and parse with comma del adv_param_user # clean variable # TODO: check integrity of input # Extract label info label_id, label_name, label_file = read_label_file(path_label, param.file_info_label) nb_labels_total = len(label_id) # check consistency of label input parameter. label_id_user, average_all_labels = check_labels( labels_of_interest, nb_labels_total, average_all_labels, method) # If 'labels_of_interest' is empty, then # 'label_id_user' contains the index of all labels in the file info_label.txt # print parameters print '\nChecked parameters:' print ' data ...................... ' + fname_data print ' folder label .............. ' + path_label print ' selected labels ........... ' + str(label_id_user) print ' estimation method ......... ' + method print ' slices of interest ........ ' + slices_of_interest print ' vertebral levels .......... ' + vertebral_levels print ' vertebral labeling file.... ' + fname_vertebral_labeling print ' advanced parameters ....... ' + str(adv_param) # Check if the orientation of the data is RPI orientation_data = get_orientation(fname_data) # If orientation is not RPI, change to RPI if orientation_data != 'RPI': sct.printv( '\nCreate temporary folder to change the orientation of the NIFTI files into RPI...', verbose) path_tmp = sct.slash_at_the_end('tmp.' + time.strftime("%y%m%d%H%M%S"), 1) sct.create_folder(path_tmp) # change orientation and load data sct.printv('\nChange image orientation and load it...', verbose) data = nib.load( set_orientation(fname_data, 'RPI', path_tmp + 'orient_data.nii')).get_data() # Do the same for labels sct.printv('\nChange labels orientation and load them...', verbose) labels = np.empty([nb_labels_total], dtype=object) # labels(nb_labels_total, x, y, z) for i_label in range(0, nb_labels_total): labels[i_label] = nib.load( set_orientation(path_label + label_file[i_label], 'RPI', path_tmp + 'orient_' + label_file[i_label])).get_data() if fname_normalizing_label: # if the "normalization" option is wanted, normalizing_label = np.empty( [1], dtype=object ) # choose this kind of structure so as to keep easily the # compatibility with the rest of the code (dimensions: (1, x, y, z)) normalizing_label[0] = nib.load( set_orientation(fname_normalizing_label, 'RPI', path_tmp + 'orient_normalizing_volume.nii')).get_data() if vertebral_levels: # if vertebral levels were selected, data_vertebral_labeling = nib.load( set_orientation( fname_vertebral_labeling, 'RPI', path_tmp + 'orient_vertebral_labeling.nii.gz')).get_data() # Remove the temporary folder used to change the NIFTI files orientation into RPI sct.printv('\nRemove the temporary folder...', verbose) status, output = commands.getstatusoutput('rm -rf ' + path_tmp) else: # Load image sct.printv('\nLoad image...', verbose) data = nib.load(fname_data).get_data() # Load labels sct.printv('\nLoad labels...', verbose) labels = np.empty([nb_labels_total], dtype=object) # labels(nb_labels_total, x, y, z) for i_label in range(0, nb_labels_total): labels[i_label] = nib.load(path_label + label_file[i_label]).get_data() if fname_normalizing_label: # if the "normalization" option is wanted, normalizing_label = np.empty( [1], dtype=object ) # choose this kind of structure so as to keep easily the # compatibility with the rest of the code (dimensions: (1, x, y, z)) normalizing_label[0] = nib.load(fname_normalizing_label).get_data( ) # load the data of the normalizing label if vertebral_levels: # if vertebral levels were selected, data_vertebral_labeling = nib.load( fname_vertebral_labeling).get_data() # Change metric data type into floats for future manipulations (normalization) data = np.float64(data) # Get dimensions of data sct.printv('\nGet dimensions of data...', verbose) nx, ny, nz = data.shape sct.printv(' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz), verbose) # Get dimensions of labels sct.printv('\nGet dimensions of label...', verbose) nx_atlas, ny_atlas, nz_atlas = labels[0].shape sct.printv( '.. ' + str(nx_atlas) + ' x ' + str(ny_atlas) + ' x ' + str(nz_atlas) + ' x ' + str(nb_labels_total), verbose) # Check dimensions consistency between atlas and data if (nx, ny, nz) != (nx_atlas, ny_atlas, nz_atlas): print '\nERROR: Metric data and labels DO NOT HAVE SAME DIMENSIONS.' sys.exit(2) # Update the flag "slices_of_interest" according to the vertebral levels selected by user (if it's the case) if vertebral_levels: slices_of_interest, actual_vert_levels, warning_vert_levels = \ get_slices_matching_with_vertebral_levels(data, vertebral_levels, data_vertebral_labeling) # select slice of interest by cropping data and labels if slices_of_interest: data = remove_slices(data, slices_of_interest) for i_label in range(0, nb_labels_total): labels[i_label] = remove_slices(labels[i_label], slices_of_interest) if fname_normalizing_label: # if the "normalization" option was selected, normalizing_label[0] = remove_slices(normalizing_label[0], slices_of_interest) # if user wants to get unique value across labels, then combine all labels together if average_all_labels == 1: sum_labels_user = np.sum( labels[label_id_user]) # sum the labels selected by user if method == 'ml' or method == 'map': # in case the maximum likelihood and the average across different labels are wanted labels_tmp = np.empty([nb_labels_total - len(label_id_user) + 1], dtype=object) labels = np.delete( labels, label_id_user) # remove the labels selected by user labels_tmp[ 0] = sum_labels_user # put the sum of the labels selected by user in first position of the tmp # variable for i_label in range(1, len(labels_tmp)): labels_tmp[i_label] = labels[ i_label - 1] # fill the temporary array with the values of the non-selected labels labels = labels_tmp # replace the initial labels value by the updated ones (with the summed labels) del labels_tmp # delete the temporary labels else: # in other cases than the maximum likelihood, we can remove other labels (not needed for estimation) labels = np.empty(1, dtype=object) labels[ 0] = sum_labels_user # we create a new label array that includes only the summed labels if fname_normalizing_label: # if the "normalization" option is wanted sct.printv('\nExtract normalization values...', verbose) if normalization_method == 'sbs': # case: the user wants to normalize slice-by-slice for z in range(0, data.shape[-1]): normalizing_label_slice = np.empty( [1], dtype=object ) # in order to keep compatibility with the function # 'extract_metric_within_tract', define a new array for the slice z of the normalizing labels normalizing_label_slice[0] = normalizing_label[0][..., z] metric_normalizing_label = extract_metric_within_tract( data[..., z], normalizing_label_slice, method, 0) # estimate the metric mean in the normalizing label for the slice z if metric_normalizing_label[0][0] != 0: data[..., z] = data[..., z] / metric_normalizing_label[0][ 0] # divide all the slice z by this value elif normalization_method == 'whole': # case: the user wants to normalize after estimations in the whole labels metric_mean_norm_label, metric_std_norm_label = extract_metric_within_tract( data, normalizing_label, method, param.verbose) # mean and std are lists # identify cluster for each tract (for use with robust ML) ml_clusters_array = get_clusters(ml_clusters, labels) # extract metrics within labels sct.printv('\nExtract metric within labels...', verbose) metric_mean, metric_std = extract_metric_within_tract( data, labels, method, verbose, ml_clusters_array, adv_param) # mean and std are lists if fname_normalizing_label and normalization_method == 'whole': # case: user wants to normalize after estimations in the whole labels metric_mean, metric_std = np.divide(metric_mean, metric_mean_norm_label), np.divide( metric_std, metric_std_norm_label) # update label name if average if average_all_labels == 1: label_name[0] = 'AVERAGED' + ' -'.join( label_name[i] for i in label_id_user) # concatenate the names of the # labels selected by the user if the average tag was asked label_id_user = [ 0 ] # update "label_id_user" to select the "averaged" label (which is in first position) metric_mean = metric_mean[label_id_user] metric_std = metric_std[label_id_user] # display metrics sct.printv('\nEstimation results:', 1) for i in range(0, metric_mean.size): sct.printv( str(label_id_user[i]) + ', ' + str(label_name[label_id_user[i]]) + ': ' + str(metric_mean[i]) + ' +/- ' + str(metric_std[i]), 1, 'info') # save and display metrics save_metrics(label_id_user, label_name, slices_of_interest, metric_mean, metric_std, fname_output, fname_data, method, fname_normalizing_label, actual_vert_levels, warning_vert_levels)
def test(path_data, parameters=''): if not parameters: # get file name of vertebral labeling from template # file_vertfile = get_file_label(path_data+'mt/label/template', 'vertebral', output='file') parameters = '-i t2s/t2s.nii.gz -s t2s/t2s_seg.nii.gz -vertfile t2s/MNI-Poly-AMU_level_crop.nii.gz -ref t2s/t2s_gmseg_manual.nii.gz -qc 0' parser = sct_segment_graymatter.get_parser() dict_param = parser.parse(parameters.split(), check_file_exist=False) dict_param_with_path = parser.add_path_to_file(dict_param, path_data, input_file=True) #if -model is used : do not add the path before. if '-model' in dict_param_with_path.keys(): dict_param_with_path['-model'] = dict_param_with_path['-model'][len(path_data):] if '-vertfile' in dict_param_with_path.keys(): dict_param_with_path['-vertfile'] = sct.slash_at_the_end(path_data, slash=1)+dict_param_with_path['-vertfile'] param_with_path = parser.dictionary_to_string(dict_param_with_path) # Check if input files exist if not (os.path.isfile(dict_param_with_path['-i']) and os.path.isfile(dict_param_with_path['-s'])): status = 200 output = 'ERROR: the file(s) provided to test function do not exist in folder: ' + path_data return status, output, DataFrame(data={'status': status, 'output': output, 'dice_gm': float('nan'), 'dice_wm': float('nan'), 'hausdorff': float('nan'), 'med_dist': float('nan'), 'duration_[s]': float('nan')}, index=[path_data]) import time, random subject_folder = path_data.split('/') if subject_folder[-1] == '' and len(subject_folder) > 1: subject_folder = subject_folder[-2] else: subject_folder = subject_folder[-1] path_output = sct.slash_at_the_end('sct_segment_graymatter_' + subject_folder + '_' + time.strftime("%y%m%d%H%M%S") + '_'+str(random.randint(1, 1000000)), slash=1) param_with_path += ' -ofolder ' + path_output cmd = 'sct_segment_graymatter ' + param_with_path time_start = time.time() status, output = sct.run(cmd, 0) duration = time.time() - time_start # initialization of results: must be NaN if test fails result_dice_gm, result_dice_wm, result_hausdorff, result_median_dist = float('nan'), float('nan'), float('nan'), float('nan') if status == 0 and "-ref" in dict_param_with_path.keys() : target_name = sct.extract_fname(dict_param_with_path["-i"])[1] dice_fname = path_output+'dice_coefficient_'+target_name+'.txt' hausdorff_fname = path_output+'hausdorff_dist_'+target_name+'.txt' # Extracting dice results: dice = open(dice_fname, 'r') dice_lines = dice.readlines() dice.close() gm_start = dice_lines.index('Dice coefficient on the Gray Matter segmentation:\n') wm_start = dice_lines.index('Dice coefficient on the White Matter segmentation:\n') # extracting dice on GM gm_dice_lines = dice_lines[gm_start:wm_start-1] gm_dice_lines = gm_dice_lines[gm_dice_lines.index('2D Dice coefficient by slice:\n')+1:-1] null_slices = [] gm_dice = [] for line in gm_dice_lines: n_slice, dc = line.split(' ') # remove \n from dice result dc = dc[:-1] dc = dc[:-4] if '[0m' in dc else dc if dc == '0' or dc == 'nan': null_slices.append(n_slice) else: try: gm_dice.append(float(dc)) except ValueError: gm_dice.append(float(dc[:-4])) result_dice_gm = mean(gm_dice) # extracting dice on WM wm_dice_lines = dice_lines[wm_start:] wm_dice_lines = wm_dice_lines[wm_dice_lines.index('2D Dice coefficient by slice:\n')+1:] wm_dice = [] for line in wm_dice_lines: n_slice, dc = line.split(' ') # remove \n from dice result if line is not wm_dice_lines[-1]: dc = dc[:-1] if n_slice not in null_slices: try: wm_dice.append(float(dc)) except ValueError: wm_dice.append(float(dc[:-4])) result_dice_wm = mean(wm_dice) # Extracting hausdorff distance results hd = open(hausdorff_fname, 'r') hd_lines = hd.readlines() hd.close() # remove title of columns and last empty/non important lines hd_lines = hd_lines[1:-4] hausdorff = [] max_med = [] for line in hd_lines: slice_id, res = line.split(':') slice, n_slice = slice_id.split(' ') if n_slice not in null_slices: hd, med1, med2 = res[:-1].split(' - ') hd, med1, med2 = float(hd), float(med1), float(med2) hausdorff.append(hd) max_med.append(max(med1, med2)) result_hausdorff = mean(hausdorff) result_median_dist = mean(max_med) # Integrity check hd_threshold = 3 # in mm wm_dice_threshold = 0.8 if result_hausdorff > hd_threshold or result_dice_wm < wm_dice_threshold: status = 99 output += '\nResulting segmentation is too different from manual segmentation:\n' \ 'WM dice: '+str(result_dice_wm)+'\n' \ 'Hausdorff distance: '+str(result_hausdorff)+'\n' # transform results into Pandas structure results = DataFrame(data={'status': status, 'output': output, 'dice_gm': result_dice_gm, 'dice_wm': result_dice_wm, 'hausdorff': result_hausdorff, 'med_dist': result_median_dist, 'duration_[s]': duration}, index=[path_data]) return status, output, results
def main(): parser = get_parser() param = Param() arguments = parser.parse(sys.argv[1:]) # get arguments fname_data = arguments['-i'] fname_seg = arguments['-s'] fname_landmarks = arguments['-l'] if '-ofolder' in arguments: path_output = arguments['-ofolder'] else: path_output = '' path_template = sct.slash_at_the_end(arguments['-t'], 1) contrast_template = arguments['-c'] remove_temp_files = int(arguments['-r']) verbose = int(arguments['-v']) if '-param-straighten' in arguments: param.param_straighten = arguments['-param-straighten'] if 'cpu-nb' in arguments: arg_cpu = ' -cpu-nb '+arguments['-cpu-nb'] else: arg_cpu = '' if '-param' in arguments: paramreg_user = arguments['-param'] # update registration parameters for paramStep in paramreg_user: paramreg.addStep(paramStep) # initialize other parameters file_template_label = param.file_template_label output_type = param.output_type zsubsample = param.zsubsample # smoothing_sigma = param.smoothing_sigma # capitalize letters for contrast if contrast_template == 't1': contrast_template = 'T1' elif contrast_template == 't2': contrast_template = 'T2' # retrieve file_template based on contrast fname_template_list = glob(path_template+param.folder_template+'*'+contrast_template+'.nii.gz') # TODO: make sure there is only one file -- check if file is there otherwise it crashes fname_template = fname_template_list[0] # retrieve file_template_seg fname_template_seg_list = glob(path_template+param.folder_template+'*cord.nii.gz') # TODO: make sure there is only one file fname_template_seg = fname_template_seg_list[0] # start timer start_time = time.time() # get absolute path - TO DO: remove! NEVER USE ABSOLUTE PATH... path_template = os.path.abspath(path_template+param.folder_template) # get fname of the template + template objects # fname_template = sct.slash_at_the_end(path_template, 1)+file_template fname_template_label = sct.slash_at_the_end(path_template, 1)+file_template_label # fname_template_seg = sct.slash_at_the_end(path_template, 1)+file_template_seg # check file existence sct.printv('\nCheck template files...') sct.check_file_exist(fname_template, verbose) sct.check_file_exist(fname_template_label, verbose) sct.check_file_exist(fname_template_seg, verbose) # print arguments sct.printv('\nCheck parameters:', verbose) sct.printv('.. Data: '+fname_data, verbose) sct.printv('.. Landmarks: '+fname_landmarks, verbose) sct.printv('.. Segmentation: '+fname_seg, verbose) sct.printv('.. Path template: '+path_template, verbose) sct.printv('.. Path output: '+path_output, verbose) sct.printv('.. Output type: '+str(output_type), verbose) sct.printv('.. Remove temp files: '+str(remove_temp_files), verbose) sct.printv('\nParameters for registration:') for pStep in range(1, len(paramreg.steps)+1): sct.printv('Step #'+paramreg.steps[str(pStep)].step, verbose) sct.printv('.. Type #'+paramreg.steps[str(pStep)].type, verbose) sct.printv('.. Algorithm................ '+paramreg.steps[str(pStep)].algo, verbose) sct.printv('.. Metric................... '+paramreg.steps[str(pStep)].metric, verbose) sct.printv('.. Number of iterations..... '+paramreg.steps[str(pStep)].iter, verbose) sct.printv('.. Shrink factor............ '+paramreg.steps[str(pStep)].shrink, verbose) sct.printv('.. Smoothing factor......... '+paramreg.steps[str(pStep)].smooth, verbose) sct.printv('.. Gradient step............ '+paramreg.steps[str(pStep)].gradStep, verbose) sct.printv('.. Degree of polynomial..... '+paramreg.steps[str(pStep)].poly, verbose) path_data, file_data, ext_data = sct.extract_fname(fname_data) sct.printv('\nCheck input labels...') # check if label image contains coherent labels image_label = Image(fname_landmarks) # -> all labels must be different labels = image_label.getNonZeroCoordinates(sorting='value') hasDifferentLabels = True for lab in labels: for otherlabel in labels: if lab != otherlabel and lab.hasEqualValue(otherlabel): hasDifferentLabels = False break if not hasDifferentLabels: sct.printv('ERROR: Wrong landmarks input. All labels must be different.', verbose, 'error') # all labels must be available in tempalte image_label_template = Image(fname_template_label) labels_template = image_label_template.getNonZeroCoordinates(sorting='value') if labels[-1].value > labels_template[-1].value: sct.printv('ERROR: Wrong landmarks input. Labels must have correspondence in template space. \nLabel max ' 'provided: ' + str(labels[-1].value) + '\nLabel max from template: ' + str(labels_template[-1].value), verbose, 'error') # create temporary folder path_tmp = sct.tmp_create(verbose=verbose) # set temporary file names ftmp_data = 'data.nii' ftmp_seg = 'seg.nii.gz' ftmp_label = 'label.nii.gz' ftmp_template = 'template.nii' ftmp_template_seg = 'template_seg.nii.gz' ftmp_template_label = 'template_label.nii.gz' # copy files to temporary folder sct.printv('\nCopying input data to tmp folder and convert to nii...', verbose) sct.run('sct_convert -i '+fname_data+' -o '+path_tmp+ftmp_data) sct.run('sct_convert -i '+fname_seg+' -o '+path_tmp+ftmp_seg) sct.run('sct_convert -i '+fname_landmarks+' -o '+path_tmp+ftmp_label) sct.run('sct_convert -i '+fname_template+' -o '+path_tmp+ftmp_template) sct.run('sct_convert -i '+fname_template_seg+' -o '+path_tmp+ftmp_template_seg) sct.run('sct_convert -i '+fname_template_label+' -o '+path_tmp+ftmp_template_label) # go to tmp folder os.chdir(path_tmp) # smooth segmentation (jcohenadad, issue #613) sct.printv('\nSmooth segmentation...', verbose) sct.run('sct_maths -i '+ftmp_seg+' -smooth 1.5 -o '+add_suffix(ftmp_seg, '_smooth')) ftmp_seg = add_suffix(ftmp_seg, '_smooth') # resample data to 1mm isotropic sct.printv('\nResample data to 1mm isotropic...', verbose) sct.run('sct_resample -i '+ftmp_data+' -mm 1.0x1.0x1.0 -x linear -o '+add_suffix(ftmp_data, '_1mm')) ftmp_data = add_suffix(ftmp_data, '_1mm') sct.run('sct_resample -i '+ftmp_seg+' -mm 1.0x1.0x1.0 -x linear -o '+add_suffix(ftmp_seg, '_1mm')) ftmp_seg = add_suffix(ftmp_seg, '_1mm') # N.B. resampling of labels is more complicated, because they are single-point labels, therefore resampling with neighrest neighbour can make them disappear. Therefore a more clever approach is required. resample_labels(ftmp_label, ftmp_data, add_suffix(ftmp_label, '_1mm')) ftmp_label = add_suffix(ftmp_label, '_1mm') # Change orientation of input images to RPI sct.printv('\nChange orientation of input images to RPI...', verbose) sct.run('sct_image -i '+ftmp_data+' -setorient RPI -o '+add_suffix(ftmp_data, '_rpi')) ftmp_data = add_suffix(ftmp_data, '_rpi') sct.run('sct_image -i '+ftmp_seg+' -setorient RPI -o '+add_suffix(ftmp_seg, '_rpi')) ftmp_seg = add_suffix(ftmp_seg, '_rpi') sct.run('sct_image -i '+ftmp_label+' -setorient RPI -o '+add_suffix(ftmp_label, '_rpi')) ftmp_label = add_suffix(ftmp_label, '_rpi') # get landmarks in native space # crop segmentation # output: segmentation_rpi_crop.nii.gz status_crop, output_crop = sct.run('sct_crop_image -i '+ftmp_seg+' -o '+add_suffix(ftmp_seg, '_crop')+' -dim 2 -bzmax', verbose) ftmp_seg = add_suffix(ftmp_seg, '_crop') cropping_slices = output_crop.split('Dimension 2: ')[1].split('\n')[0].split(' ') # straighten segmentation sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose) sct.run('sct_straighten_spinalcord -i '+ftmp_seg+' -s '+ftmp_seg+' -o '+add_suffix(ftmp_seg, '_straight')+' -qc 0 -r 0 -v '+str(verbose)+' '+param.param_straighten+arg_cpu, verbose) # N.B. DO NOT UPDATE VARIABLE ftmp_seg BECAUSE TEMPORARY USED LATER # re-define warping field using non-cropped space (to avoid issue #367) sct.run('sct_concat_transfo -w warp_straight2curve.nii.gz -d '+ftmp_data+' -o warp_straight2curve.nii.gz') # Label preparation: # -------------------------------------------------------------------------------- # Remove unused label on template. Keep only label present in the input label image sct.printv('\nRemove unused label on template. Keep only label present in the input label image...', verbose) sct.run('sct_label_utils -p remove -i '+ftmp_template_label+' -o '+ftmp_template_label+' -r '+ftmp_label) # Dilating the input label so they can be straighten without losing them sct.printv('\nDilating input labels using 3vox ball radius') sct.run('sct_maths -i '+ftmp_label+' -o '+add_suffix(ftmp_label, '_dilate')+' -dilate 3') ftmp_label = add_suffix(ftmp_label, '_dilate') # Apply straightening to labels sct.printv('\nApply straightening to labels...', verbose) sct.run('sct_apply_transfo -i '+ftmp_label+' -o '+add_suffix(ftmp_label, '_straight')+' -d '+add_suffix(ftmp_seg, '_straight')+' -w warp_curve2straight.nii.gz -x nn') ftmp_label = add_suffix(ftmp_label, '_straight') # Create crosses for the template labels and get coordinates sct.printv('\nCreate a 15 mm cross for the template labels...', verbose) template_image = Image(ftmp_template_label) coordinates_input = template_image.getNonZeroCoordinates(sorting='value') # jcohenadad, issue #628 <<<<< # landmark_template = ProcessLabels.get_crosses_coordinates(coordinates_input, gapxy=15) landmark_template = coordinates_input # >>>>> if verbose == 2: # TODO: assign cross to image before saving template_image.setFileName(add_suffix(ftmp_template_label, '_cross')) template_image.save(type='minimize_int') # Create crosses for the input labels into straight space and get coordinates sct.printv('\nCreate a 15 mm cross for the input labels...', verbose) label_straight_image = Image(ftmp_label) coordinates_input = label_straight_image.getCoordinatesAveragedByValue() # landmarks are sorted by value # jcohenadad, issue #628 <<<<< # landmark_straight = ProcessLabels.get_crosses_coordinates(coordinates_input, gapxy=15) landmark_straight = coordinates_input # >>>>> if verbose == 2: # TODO: assign cross to image before saving label_straight_image.setFileName(add_suffix(ftmp_label, '_cross')) label_straight_image.save(type='minimize_int') # Reorganize landmarks points_fixed, points_moving = [], [] for coord in landmark_straight: point_straight = label_straight_image.transfo_pix2phys([[coord.x, coord.y, coord.z]]) points_moving.append([point_straight[0][0], point_straight[0][1], point_straight[0][2]]) for coord in landmark_template: point_template = template_image.transfo_pix2phys([[coord.x, coord.y, coord.z]]) points_fixed.append([point_template[0][0], point_template[0][1], point_template[0][2]]) # Register curved landmarks on straight landmarks based on python implementation sct.printv('\nComputing rigid transformation (algo=translation-scaling-z) ...', verbose) import msct_register_landmarks # for some reason, the moving and fixed points are inverted between ITK transform and our python-based transform. # and for another unknown reason, x and y dimensions have a negative sign (at least for translation and center of rotation). if verbose == 2: show_transfo = True else: show_transfo = False (rotation_matrix, translation_array, points_moving_reg, points_moving_barycenter) = msct_register_landmarks.getRigidTransformFromLandmarks(points_moving, points_fixed, constraints='translation-scaling-z', show=show_transfo) # writing rigid transformation file text_file = open("straight2templateAffine.txt", "w") text_file.write("#Insight Transform File V1.0\n") text_file.write("#Transform 0\n") text_file.write("Transform: AffineTransform_double_3_3\n") text_file.write("Parameters: %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f\n" % ( rotation_matrix[0, 0], rotation_matrix[0, 1], rotation_matrix[0, 2], rotation_matrix[1, 0], rotation_matrix[1, 1], rotation_matrix[1, 2], rotation_matrix[2, 0], rotation_matrix[2, 1], rotation_matrix[2, 2], -translation_array[0, 0], -translation_array[0, 1], translation_array[0, 2])) text_file.write("FixedParameters: %.9f %.9f %.9f\n" % (-points_moving_barycenter[0], -points_moving_barycenter[1], points_moving_barycenter[2])) text_file.close() # Concatenate transformations: curve --> straight --> affine sct.printv('\nConcatenate transformations: curve --> straight --> affine...', verbose) sct.run('sct_concat_transfo -w warp_curve2straight.nii.gz,straight2templateAffine.txt -d template.nii -o warp_curve2straightAffine.nii.gz') # Apply transformation sct.printv('\nApply transformation...', verbose) sct.run('sct_apply_transfo -i '+ftmp_data+' -o '+add_suffix(ftmp_data, '_straightAffine')+' -d '+ftmp_template+' -w warp_curve2straightAffine.nii.gz') ftmp_data = add_suffix(ftmp_data, '_straightAffine') sct.run('sct_apply_transfo -i '+ftmp_seg+' -o '+add_suffix(ftmp_seg, '_straightAffine')+' -d '+ftmp_template+' -w warp_curve2straightAffine.nii.gz -x linear') ftmp_seg = add_suffix(ftmp_seg, '_straightAffine') # threshold and binarize sct.printv('\nBinarize segmentation...', verbose) sct.run('sct_maths -i '+ftmp_seg+' -thr 0.4 -o '+add_suffix(ftmp_seg, '_thr')) sct.run('sct_maths -i '+add_suffix(ftmp_seg, '_thr')+' -bin -o '+add_suffix(ftmp_seg, '_thr_bin')) ftmp_seg = add_suffix(ftmp_seg, '_thr_bin') # find min-max of anat2template (for subsequent cropping) zmin_template, zmax_template = find_zmin_zmax(ftmp_seg) # crop template in z-direction (for faster processing) sct.printv('\nCrop data in template space (for faster processing)...', verbose) sct.run('sct_crop_image -i '+ftmp_template+' -o '+add_suffix(ftmp_template, '_crop')+' -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template)) ftmp_template = add_suffix(ftmp_template, '_crop') sct.run('sct_crop_image -i '+ftmp_template_seg+' -o '+add_suffix(ftmp_template_seg, '_crop')+' -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template)) ftmp_template_seg = add_suffix(ftmp_template_seg, '_crop') sct.run('sct_crop_image -i '+ftmp_data+' -o '+add_suffix(ftmp_data, '_crop')+' -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template)) ftmp_data = add_suffix(ftmp_data, '_crop') sct.run('sct_crop_image -i '+ftmp_seg+' -o '+add_suffix(ftmp_seg, '_crop')+' -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template)) ftmp_seg = add_suffix(ftmp_seg, '_crop') # sub-sample in z-direction sct.printv('\nSub-sample in z-direction (for faster processing)...', verbose) sct.run('sct_resample -i '+ftmp_template+' -o '+add_suffix(ftmp_template, '_sub')+' -f 1x1x'+zsubsample, verbose) ftmp_template = add_suffix(ftmp_template, '_sub') sct.run('sct_resample -i '+ftmp_template_seg+' -o '+add_suffix(ftmp_template_seg, '_sub')+' -f 1x1x'+zsubsample, verbose) ftmp_template_seg = add_suffix(ftmp_template_seg, '_sub') sct.run('sct_resample -i '+ftmp_data+' -o '+add_suffix(ftmp_data, '_sub')+' -f 1x1x'+zsubsample, verbose) ftmp_data = add_suffix(ftmp_data, '_sub') sct.run('sct_resample -i '+ftmp_seg+' -o '+add_suffix(ftmp_seg, '_sub')+' -f 1x1x'+zsubsample, verbose) ftmp_seg = add_suffix(ftmp_seg, '_sub') # Registration straight spinal cord to template sct.printv('\nRegister straight spinal cord to template...', verbose) # loop across registration steps warp_forward = [] warp_inverse = [] for i_step in range(1, len(paramreg.steps)+1): sct.printv('\nEstimate transformation for step #'+str(i_step)+'...', verbose) # identify which is the src and dest if paramreg.steps[str(i_step)].type == 'im': src = ftmp_data dest = ftmp_template interp_step = 'linear' elif paramreg.steps[str(i_step)].type == 'seg': src = ftmp_seg dest = ftmp_template_seg interp_step = 'nn' else: sct.printv('ERROR: Wrong image type.', 1, 'error') # if step>1, apply warp_forward_concat to the src image to be used if i_step > 1: # sct.run('sct_apply_transfo -i '+src+' -d '+dest+' -w '+','.join(warp_forward)+' -o '+sct.add_suffix(src, '_reg')+' -x '+interp_step, verbose) sct.run('sct_apply_transfo -i '+src+' -d '+dest+' -w '+','.join(warp_forward)+' -o '+add_suffix(src, '_reg')+' -x '+interp_step, verbose) src = 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.append(warp_inverse_out) # Concatenate transformations: sct.printv('\nConcatenate transformations: anat --> template...', verbose) sct.run('sct_concat_transfo -w warp_curve2straightAffine.nii.gz,'+','.join(warp_forward)+' -d template.nii -o warp_anat2template.nii.gz', verbose) # sct.run('sct_concat_transfo -w warp_curve2straight.nii.gz,straight2templateAffine.txt,'+','.join(warp_forward)+' -d template.nii -o warp_anat2template.nii.gz', verbose) sct.printv('\nConcatenate transformations: template --> anat...', verbose) warp_inverse.reverse() sct.run('sct_concat_transfo -w '+','.join(warp_inverse)+',-straight2templateAffine.txt,warp_straight2curve.nii.gz -d data.nii -o warp_template2anat.nii.gz', verbose) # Apply warping fields to anat and template if output_type == 1: sct.run('sct_apply_transfo -i template.nii -o template2anat.nii.gz -d data.nii -w warp_template2anat.nii.gz -crop 1', verbose) sct.run('sct_apply_transfo -i data.nii -o anat2template.nii.gz -d template.nii -w warp_anat2template.nii.gz -crop 1', verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(path_tmp+'warp_template2anat.nii.gz', path_output+'warp_template2anat.nii.gz', verbose) sct.generate_output_file(path_tmp+'warp_anat2template.nii.gz', path_output+'warp_anat2template.nii.gz', verbose) if output_type == 1: sct.generate_output_file(path_tmp+'template2anat.nii.gz', path_output+'template2anat'+ext_data, verbose) sct.generate_output_file(path_tmp+'anat2template.nii.gz', path_output+'anat2template'+ext_data, verbose) # Delete temporary files if remove_temp_files: sct.printv('\nDelete temporary files...', verbose) 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', verbose) # to view results sct.printv('\nTo view results, type:', verbose) sct.printv('fslview '+fname_data+' '+path_output+'template2anat -b 0,4000 &', verbose, 'info') sct.printv('fslview '+fname_template+' -b 0,5000 '+path_output+'anat2template &\n', verbose, 'info')
file_download_result = download_file(url_to_ants_repository, ants_downloaded_file) if file_download_result.status == InstallationResult.SUCCESS: # unzip ants repository cmd = 'unzip -u -d ./ ' + ants_downloaded_file print ">> " + cmd status, output = sct.run(cmd) if status != 0: print '\nERROR! \n' + output + '\nExit program.\n' sys.exit(2) sct.run('mv ' + ants_downloaded_folder + ' ANTs/') else: print 'ERROR: ANTs download failed. Please check your internet connexion or contact administrators.\n' usage() else: path_ants = sct.slash_at_the_end(path_ants) + '/' if not os.path.isdir(path_ants + 'ANTs/'): print 'ERROR: Path to ANTs must be a directory containing the folder ANTs/.' print 'Path specified: ' + path_ants + '\n' usage() # process list of scripts scripts = ants_scripts if scripts_target: scripts = [] scripts_temp = scripts_target.split(',') for sc in scripts_temp: if sc in ants_scripts: scripts.append(sc) else:
input_level_fname = None input_ref_gm_seg = None compute_ratio = False if seg_param.debug: print '\n*** WARNING: DEBUG MODE ON ***\n' fname_input = model_param.path_model + "/errsm_34.nii.gz" fname_input = model_param.path_model + "/errsm_34_seg_in.nii.gz" else: parser = get_parser() arguments = parser.parse(sys.argv[1:]) input_target_fname = arguments["-i"] input_sc_seg_fname = arguments["-s"] if "-model" in arguments: model_param.path_model = arguments["-model"] model_param.todo_model = 'load' seg_param.output_path = sct.slash_at_the_end(arguments["-ofolder"], slash=1) if "-t2" in arguments: input_t2_data = arguments["-t2"] if "-vert" in arguments: input_level_fname = arguments["-vert"] if "-use-levels" in arguments: model_param.use_levels = bool(int(arguments["-use-levels"])) if "-weight" in arguments: model_param.weight_gamma = arguments["-weight"] if "-denoising" in arguments: seg_param.target_denoising = bool(int(arguments["-denoising"])) if "-normalize" in arguments: seg_param.target_normalization = bool(int(arguments["-normalize"])) if "-means" in arguments: seg_param.target_means = arguments["-means"]
def main(): # get default parameters step1 = Paramreg(step='1', type='seg', algo='slicereg', metric='MeanSquares', iter='10') step2 = Paramreg(step='2', type='im', algo='syn', metric='MI', iter='3') # step1 = Paramreg() paramreg = ParamregMultiStep([step1, step2]) # step1 = Paramreg_step(step='1', type='seg', algo='bsplinesyn', metric='MeanSquares', iter='10', shrink='1', smooth='0', gradStep='0.5') # step2 = Paramreg_step(step='2', type='im', algo='syn', metric='MI', iter='10', shrink='1', smooth='0', gradStep='0.5') # paramreg = ParamregMultiStep([step1, step2]) # Initialize the parser parser = Parser(__file__) parser.usage.set_description('Register anatomical image to the template.') parser.add_option(name="-i", type_value="file", description="Anatomical image.", mandatory=True, example="anat.nii.gz") parser.add_option(name="-s", type_value="file", description="Spinal cord segmentation.", mandatory=True, example="anat_seg.nii.gz") parser.add_option( name="-l", type_value="file", description= "Labels. See: http://sourceforge.net/p/spinalcordtoolbox/wiki/create_labels/", mandatory=True, default_value='', example="anat_labels.nii.gz") parser.add_option(name="-t", type_value="folder", description="Path to MNI-Poly-AMU template.", mandatory=False, default_value=param.path_template) parser.add_option( name="-p", type_value=[[':'], 'str'], description= """Parameters for registration (see sct_register_multimodal). Default:\n--\nstep=1\ntype=""" + paramreg.steps['1'].type + """\nalgo=""" + paramreg.steps['1'].algo + """\nmetric=""" + paramreg.steps['1'].metric + """\npoly=""" + paramreg.steps['1'].poly + """\n--\nstep=2\ntype=""" + paramreg.steps['2'].type + """\nalgo=""" + paramreg.steps['2'].algo + """\nmetric=""" + paramreg.steps['2'].metric + """\niter=""" + paramreg.steps['2'].iter + """\nshrink=""" + paramreg.steps['2'].shrink + """\nsmooth=""" + paramreg.steps['2'].smooth + """\ngradStep=""" + paramreg.steps['2'].gradStep + """\n--""", mandatory=False, example= "step=2,type=seg,algo=bsplinesyn,metric=MeanSquares,iter=5,shrink=2:step=3,type=im,algo=syn,metric=MI,iter=5,shrink=1,gradStep=0.3" ) parser.add_option(name="-r", type_value="multiple_choice", description="""Remove temporary files.""", mandatory=False, default_value='1', example=['0', '1']) parser.add_option( name="-v", type_value="multiple_choice", description="""Verbose. 0: nothing. 1: basic. 2: extended.""", mandatory=False, default_value=param.verbose, example=['0', '1', '2']) if param.debug: print '\n*** WARNING: DEBUG MODE ON ***\n' fname_data = '/Users/julien/data/temp/sct_example_data/t2/t2.nii.gz' fname_landmarks = '/Users/julien/data/temp/sct_example_data/t2/labels.nii.gz' fname_seg = '/Users/julien/data/temp/sct_example_data/t2/t2_seg.nii.gz' path_template = param.path_template remove_temp_files = 0 verbose = 2 # speed = 'superfast' #param_reg = '2,BSplineSyN,0.6,MeanSquares' else: arguments = parser.parse(sys.argv[1:]) # get arguments fname_data = arguments['-i'] fname_seg = arguments['-s'] fname_landmarks = arguments['-l'] path_template = arguments['-t'] remove_temp_files = int(arguments['-r']) verbose = int(arguments['-v']) if '-p' in arguments: paramreg_user = arguments['-p'] # update registration parameters for paramStep in paramreg_user: paramreg.addStep(paramStep) # initialize other parameters file_template = param.file_template file_template_label = param.file_template_label file_template_seg = param.file_template_seg output_type = param.output_type zsubsample = param.zsubsample # smoothing_sigma = param.smoothing_sigma # start timer start_time = time.time() # get absolute path - TO DO: remove! NEVER USE ABSOLUTE PATH... path_template = os.path.abspath(path_template) # get fname of the template + template objects fname_template = sct.slash_at_the_end(path_template, 1) + file_template fname_template_label = sct.slash_at_the_end(path_template, 1) + file_template_label fname_template_seg = sct.slash_at_the_end(path_template, 1) + file_template_seg # check file existence sct.printv('\nCheck template files...') sct.check_file_exist(fname_template, verbose) sct.check_file_exist(fname_template_label, verbose) sct.check_file_exist(fname_template_seg, verbose) # print arguments sct.printv('\nCheck parameters:', verbose) sct.printv('.. Data: ' + fname_data, verbose) sct.printv('.. Landmarks: ' + fname_landmarks, verbose) sct.printv('.. Segmentation: ' + fname_seg, verbose) sct.printv('.. Path template: ' + path_template, verbose) sct.printv('.. Output type: ' + str(output_type), verbose) sct.printv('.. Remove temp files: ' + str(remove_temp_files), verbose) sct.printv('\nParameters for registration:') for pStep in range(1, len(paramreg.steps) + 1): sct.printv('Step #' + paramreg.steps[str(pStep)].step, verbose) sct.printv('.. Type #' + paramreg.steps[str(pStep)].type, verbose) sct.printv( '.. Algorithm................ ' + paramreg.steps[str(pStep)].algo, verbose) sct.printv( '.. Metric................... ' + paramreg.steps[str(pStep)].metric, verbose) sct.printv( '.. Number of iterations..... ' + paramreg.steps[str(pStep)].iter, verbose) sct.printv( '.. Shrink factor............ ' + paramreg.steps[str(pStep)].shrink, verbose) sct.printv( '.. Smoothing factor......... ' + paramreg.steps[str(pStep)].smooth, verbose) sct.printv( '.. Gradient step............ ' + paramreg.steps[str(pStep)].gradStep, verbose) sct.printv( '.. Degree of polynomial..... ' + paramreg.steps[str(pStep)].poly, verbose) path_data, file_data, ext_data = sct.extract_fname(fname_data) sct.printv('\nCheck input labels...') # check if label image contains coherent labels image_label = Image(fname_landmarks) # -> all labels must be different labels = image_label.getNonZeroCoordinates(sorting='value') hasDifferentLabels = True for lab in labels: for otherlabel in labels: if lab != otherlabel and lab.hasEqualValue(otherlabel): hasDifferentLabels = False break if not hasDifferentLabels: sct.printv( 'ERROR: Wrong landmarks input. All labels must be different.', verbose, 'error') # all labels must be available in tempalte image_label_template = Image(fname_template_label) labels_template = image_label_template.getNonZeroCoordinates( sorting='value') if labels[-1].value > labels_template[-1].value: sct.printv( 'ERROR: Wrong landmarks input. Labels must have correspondance in tempalte space. \nLabel max ' 'provided: ' + str(labels[-1].value) + '\nLabel max from template: ' + str(labels_template[-1].value), verbose, 'error') # 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) # copy files to temporary folder sct.printv('\nCopy files...', verbose) sct.run('isct_c3d ' + fname_data + ' -o ' + path_tmp + '/data.nii') sct.run('isct_c3d ' + fname_landmarks + ' -o ' + path_tmp + '/landmarks.nii.gz') sct.run('isct_c3d ' + fname_seg + ' -o ' + path_tmp + '/segmentation.nii.gz') sct.run('isct_c3d ' + fname_template + ' -o ' + path_tmp + '/template.nii') sct.run('isct_c3d ' + fname_template_label + ' -o ' + path_tmp + '/template_labels.nii.gz') sct.run('isct_c3d ' + fname_template_seg + ' -o ' + path_tmp + '/template_seg.nii.gz') # go to tmp folder os.chdir(path_tmp) # resample data to 1mm isotropic sct.printv('\nResample data to 1mm isotropic...', verbose) sct.run( 'isct_c3d data.nii -resample-mm 1.0x1.0x1.0mm -interpolation Linear -o datar.nii' ) sct.run( 'isct_c3d segmentation.nii.gz -resample-mm 1.0x1.0x1.0mm -interpolation NearestNeighbor -o segmentationr.nii.gz' ) # N.B. resampling of labels is more complicated, because they are single-point labels, therefore resampling with neighrest neighbour can make them disappear. Therefore a more clever approach is required. resample_labels('landmarks.nii.gz', 'datar.nii', 'landmarksr.nii.gz') # # TODO # sct.run('sct_label_utils -i datar.nii -t create -x 124,186,19,2:129,98,23,8 -o landmarksr.nii.gz') # Change orientation of input images to RPI sct.printv('\nChange orientation of input images to RPI...', verbose) set_orientation('datar.nii', 'RPI', 'data_rpi.nii') set_orientation('landmarksr.nii.gz', 'RPI', 'landmarks_rpi.nii.gz') set_orientation('segmentationr.nii.gz', 'RPI', 'segmentation_rpi.nii.gz') # # Change orientation of input images to RPI # sct.printv('\nChange orientation of input images to RPI...', verbose) # set_orientation('data.nii', 'RPI', 'data_rpi.nii') # set_orientation('landmarks.nii.gz', 'RPI', 'landmarks_rpi.nii.gz') # set_orientation('segmentation.nii.gz', 'RPI', 'segmentation_rpi.nii.gz') # get landmarks in native space # crop segmentation # output: segmentation_rpi_crop.nii.gz sct.run( 'sct_crop_image -i segmentation_rpi.nii.gz -o segmentation_rpi_crop.nii.gz -dim 2 -bzmax' ) # straighten segmentation sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose) sct.run( 'sct_straighten_spinalcord -i segmentation_rpi_crop.nii.gz -c segmentation_rpi_crop.nii.gz -r 0 -v ' + str(verbose), verbose) # re-define warping field using non-cropped space (to avoid issue #367) sct.run( 'sct_concat_transfo -w warp_straight2curve.nii.gz -d data_rpi.nii -o warp_straight2curve.nii.gz' ) # Label preparation: # -------------------------------------------------------------------------------- # Remove unused label on template. Keep only label present in the input label image sct.printv( '\nRemove unused label on template. Keep only label present in the input label image...', verbose) sct.run( 'sct_label_utils -t remove -i template_labels.nii.gz -o template_label.nii.gz -r landmarks_rpi.nii.gz' ) # Make sure landmarks are INT sct.printv('\nConvert landmarks to INT...', verbose) sct.run( 'isct_c3d template_label.nii.gz -type int -o template_label.nii.gz', verbose) # Create a cross for the template labels - 5 mm sct.printv('\nCreate a 5 mm cross for the template labels...', verbose) sct.run( 'sct_label_utils -t cross -i template_label.nii.gz -o template_label_cross.nii.gz -c 5' ) # Create a cross for the input labels and dilate for straightening preparation - 5 mm sct.printv( '\nCreate a 5mm cross for the input labels and dilate for straightening preparation...', verbose) sct.run( 'sct_label_utils -t cross -i landmarks_rpi.nii.gz -o landmarks_rpi_cross3x3.nii.gz -c 5 -d' ) # Apply straightening to labels sct.printv('\nApply straightening to labels...', verbose) sct.run( 'sct_apply_transfo -i landmarks_rpi_cross3x3.nii.gz -o landmarks_rpi_cross3x3_straight.nii.gz -d segmentation_rpi_crop_straight.nii.gz -w warp_curve2straight.nii.gz -x nn' ) # Convert landmarks from FLOAT32 to INT sct.printv('\nConvert landmarks from FLOAT32 to INT...', verbose) sct.run( 'isct_c3d landmarks_rpi_cross3x3_straight.nii.gz -type int -o landmarks_rpi_cross3x3_straight.nii.gz' ) # Remove labels that do not correspond with each others. sct.printv('\nRemove labels that do not correspond with each others.', verbose) sct.run( 'sct_label_utils -t remove-symm -i landmarks_rpi_cross3x3_straight.nii.gz -o landmarks_rpi_cross3x3_straight.nii.gz,template_label_cross.nii.gz -r template_label_cross.nii.gz' ) # Estimate affine transfo: straight --> template (landmark-based)' sct.printv( '\nEstimate affine transfo: straight anat --> template (landmark-based)...', verbose) # converting landmarks straight and curved to physical coordinates image_straight = Image('landmarks_rpi_cross3x3_straight.nii.gz') landmark_straight = image_straight.getNonZeroCoordinates(sorting='value') image_template = Image('template_label_cross.nii.gz') landmark_template = image_template.getNonZeroCoordinates(sorting='value') # Reorganize landmarks points_fixed, points_moving = [], [] landmark_straight_mean = [] for coord in landmark_straight: if coord.value not in [c.value for c in landmark_straight_mean]: temp_landmark = coord temp_number = 1 for other_coord in landmark_straight: if coord.hasEqualValue(other_coord) and coord != other_coord: temp_landmark += other_coord temp_number += 1 landmark_straight_mean.append(temp_landmark / temp_number) for coord in landmark_straight_mean: point_straight = image_straight.transfo_pix2phys( [[coord.x, coord.y, coord.z]]) points_moving.append( [point_straight[0][0], point_straight[0][1], point_straight[0][2]]) for coord in landmark_template: point_template = image_template.transfo_pix2phys( [[coord.x, coord.y, coord.z]]) points_fixed.append( [point_template[0][0], point_template[0][1], point_template[0][2]]) # Register curved landmarks on straight landmarks based on python implementation sct.printv( '\nComputing rigid transformation (algo=translation-scaling-z) ...', verbose) import msct_register_landmarks (rotation_matrix, translation_array, points_moving_reg, points_moving_barycenter) = \ msct_register_landmarks.getRigidTransformFromLandmarks( points_fixed, points_moving, constraints='translation-scaling-z', show=False) # writing rigid transformation file text_file = open("straight2templateAffine.txt", "w") text_file.write("#Insight Transform File V1.0\n") text_file.write("#Transform 0\n") text_file.write( "Transform: FixedCenterOfRotationAffineTransform_double_3_3\n") text_file.write( "Parameters: %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f\n" % (1.0 / rotation_matrix[0, 0], rotation_matrix[0, 1], rotation_matrix[0, 2], rotation_matrix[1, 0], 1.0 / rotation_matrix[1, 1], rotation_matrix[1, 2], rotation_matrix[2, 0], rotation_matrix[2, 1], 1.0 / rotation_matrix[2, 2], translation_array[0, 0], translation_array[0, 1], -translation_array[0, 2])) text_file.write("FixedParameters: %.9f %.9f %.9f\n" % (points_moving_barycenter[0], points_moving_barycenter[1], points_moving_barycenter[2])) text_file.close() # Apply affine transformation: straight --> template sct.printv('\nApply affine transformation: straight --> template...', verbose) sct.run( 'sct_concat_transfo -w warp_curve2straight.nii.gz,straight2templateAffine.txt -d template.nii -o warp_curve2straightAffine.nii.gz' ) sct.run( 'sct_apply_transfo -i data_rpi.nii -o data_rpi_straight2templateAffine.nii -d template.nii -w warp_curve2straightAffine.nii.gz' ) sct.run( 'sct_apply_transfo -i segmentation_rpi.nii.gz -o segmentation_rpi_straight2templateAffine.nii.gz -d template.nii -w warp_curve2straightAffine.nii.gz -x linear' ) # threshold to 0.5 nii = Image('segmentation_rpi_straight2templateAffine.nii.gz') data = nii.data data[data < 0.5] = 0 nii.data = data nii.setFileName('segmentation_rpi_straight2templateAffine_th.nii.gz') nii.save() # find min-max of anat2template (for subsequent cropping) zmin_template, zmax_template = find_zmin_zmax( 'segmentation_rpi_straight2templateAffine_th.nii.gz') # crop template in z-direction (for faster processing) sct.printv('\nCrop data in template space (for faster processing)...', verbose) sct.run( 'sct_crop_image -i template.nii -o template_crop.nii -dim 2 -start ' + str(zmin_template) + ' -end ' + str(zmax_template)) sct.run( 'sct_crop_image -i template_seg.nii.gz -o template_seg_crop.nii.gz -dim 2 -start ' + str(zmin_template) + ' -end ' + str(zmax_template)) sct.run( 'sct_crop_image -i data_rpi_straight2templateAffine.nii -o data_rpi_straight2templateAffine_crop.nii -dim 2 -start ' + str(zmin_template) + ' -end ' + str(zmax_template)) sct.run( 'sct_crop_image -i segmentation_rpi_straight2templateAffine.nii.gz -o segmentation_rpi_straight2templateAffine_crop.nii.gz -dim 2 -start ' + str(zmin_template) + ' -end ' + str(zmax_template)) # sub-sample in z-direction sct.printv('\nSub-sample in z-direction (for faster processing)...', verbose) sct.run( 'sct_resample -i template_crop.nii -o template_crop_r.nii -f 1x1x' + zsubsample, verbose) sct.run( 'sct_resample -i template_seg_crop.nii.gz -o template_seg_crop_r.nii.gz -f 1x1x' + zsubsample, verbose) sct.run( 'sct_resample -i data_rpi_straight2templateAffine_crop.nii -o data_rpi_straight2templateAffine_crop_r.nii -f 1x1x' + zsubsample, verbose) sct.run( 'sct_resample -i segmentation_rpi_straight2templateAffine_crop.nii.gz -o segmentation_rpi_straight2templateAffine_crop_r.nii.gz -f 1x1x' + zsubsample, verbose) # Registration straight spinal cord to template sct.printv('\nRegister straight spinal cord to template...', verbose) # loop across registration steps warp_forward = [] warp_inverse = [] for i_step in range(1, len(paramreg.steps) + 1): sct.printv( '\nEstimate transformation for step #' + str(i_step) + '...', verbose) # identify which is the src and dest if paramreg.steps[str(i_step)].type == 'im': src = 'data_rpi_straight2templateAffine_crop_r.nii' dest = 'template_crop_r.nii' interp_step = 'linear' elif paramreg.steps[str(i_step)].type == 'seg': src = 'segmentation_rpi_straight2templateAffine_crop_r.nii.gz' dest = 'template_seg_crop_r.nii.gz' interp_step = 'nn' else: sct.printv('ERROR: Wrong image type.', 1, 'error') # if step>1, apply warp_forward_concat to the src image to be used if i_step > 1: # sct.run('sct_apply_transfo -i '+src+' -d '+dest+' -w '+','.join(warp_forward)+' -o '+sct.add_suffix(src, '_reg')+' -x '+interp_step, 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.append(warp_inverse_out) # Concatenate transformations: sct.printv('\nConcatenate transformations: anat --> template...', verbose) sct.run( 'sct_concat_transfo -w warp_curve2straightAffine.nii.gz,' + ','.join(warp_forward) + ' -d template.nii -o warp_anat2template.nii.gz', verbose) # sct.run('sct_concat_transfo -w warp_curve2straight.nii.gz,straight2templateAffine.txt,'+','.join(warp_forward)+' -d template.nii -o warp_anat2template.nii.gz', verbose) warp_inverse.reverse() sct.run( 'sct_concat_transfo -w ' + ','.join(warp_inverse) + ',-straight2templateAffine.txt,warp_straight2curve.nii.gz -d data.nii -o warp_template2anat.nii.gz', verbose) # Apply warping fields to anat and template if output_type == 1: sct.run( 'sct_apply_transfo -i template.nii -o template2anat.nii.gz -d data.nii -w warp_template2anat.nii.gz -c 1', verbose) sct.run( 'sct_apply_transfo -i data.nii -o anat2template.nii.gz -d template.nii -w warp_anat2template.nii.gz -c 1', verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(path_tmp + '/warp_template2anat.nii.gz', 'warp_template2anat.nii.gz', verbose) sct.generate_output_file(path_tmp + '/warp_anat2template.nii.gz', 'warp_anat2template.nii.gz', verbose) if output_type == 1: sct.generate_output_file(path_tmp + '/template2anat.nii.gz', 'template2anat' + ext_data, verbose) sct.generate_output_file(path_tmp + '/anat2template.nii.gz', 'anat2template' + ext_data, verbose) # Delete temporary files if remove_temp_files: sct.printv('\nDelete temporary files...', verbose) 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', verbose) # to view results sct.printv('\nTo view results, type:', verbose) sct.printv('fslview ' + fname_data + ' template2anat -b 0,4000 &', verbose, 'info') sct.printv('fslview ' + fname_template + ' -b 0,5000 anat2template &\n', verbose, 'info')
def main(args=None): # initializations initz = '' initcenter = '' initc2 = 'auto' param = Param() # check user arguments if not args: args = sys.argv[1:] # Get parser info parser = get_parser() arguments = parser.parse(sys.argv[1:]) fname_in = arguments["-i"] fname_seg = arguments['-s'] contrast = arguments['-c'] path_template = sct.slash_at_the_end(arguments['-t'], 1) # if '-o' in arguments: # file_out = arguments["-o"] # else: # file_out = '' if '-ofolder' in arguments: path_output = sct.slash_at_the_end(os.path.abspath(arguments['-ofolder']), slash=1) else: path_output = sct.slash_at_the_end(os.path.abspath(os.curdir), slash=1) if '-initz' in arguments: initz = arguments['-initz'] if '-initcenter' in arguments: initcenter = arguments['-initcenter'] # if user provided text file, parse and overwrite arguments if '-initfile' in arguments: # open file file = open(arguments['-initfile'], 'r') initfile = ' '+file.read().replace('\n', '') arg_initfile = initfile.split(' ') for i in xrange(len(arg_initfile)): if arg_initfile[i] == '-initz': initz = [int(x) for x in arg_initfile[i+1].split(',')] if arg_initfile[i] == '-initcenter': initcenter = int(arg_initfile[i+1]) if '-initc2' in arguments: initc2 = 'manual' if '-param' in arguments: param.update(arguments['-param'][0]) verbose = int(arguments['-v']) remove_tmp_files = int(arguments['-r']) denoise = int(arguments['-denoise']) laplacian = int(arguments['-laplacian']) # if verbose, import matplotlib # if verbose == 2: # import matplotlib.pyplot as plt # create temporary folder printv('\nCreate temporary folder...', verbose) path_tmp = tmp_create(verbose=verbose) # path_tmp = '/Users/julien/Dropbox/documents/processing/20160813_wang/t12/tmp.160814213032_725693/' # Copying input data to tmp folder printv('\nCopying input data to tmp folder...', verbose) run('sct_convert -i '+fname_in+' -o '+path_tmp+'data.nii') run('sct_convert -i '+fname_seg+' -o '+path_tmp+'segmentation.nii.gz') # Go go temp folder os.chdir(path_tmp) # create label to identify disc printv('\nCreate label to identify disc...', verbose) initauto = False if initz: create_label_z('segmentation.nii.gz', initz[0], initz[1]) # create label located at z_center elif initcenter: # find z centered in FOV nii = Image('segmentation.nii.gz') nii.change_orientation('RPI') # reorient to RPI nx, ny, nz, nt, px, py, pz, pt = nii.dim # Get dimensions z_center = int(round(nz/2)) # get z_center create_label_z('segmentation.nii.gz', z_center, initcenter) # create label located at z_center else: initauto = True # printv('\nERROR: You need to initialize the disc detection algorithm using one of these two options: -initz, -initcenter\n', 1, 'error') # Straighten spinal cord printv('\nStraighten spinal cord...', 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 data.nii -w warp_curve2straight.nii.gz -d straight_ref.nii.gz -o data_straight.nii') else: run('sct_straighten_spinalcord -i data.nii -s segmentation.nii.gz -r 0 -qc 0') # resample to 0.5mm isotropic to match template resolution printv('\nResample to 0.5mm isotropic...', verbose) run('sct_resample -i data_straight.nii -mm 0.5x0.5x0.5 -x linear -o data_straightr.nii', verbose) # run('sct_resample -i segmentation.nii.gz -mm 0.5x0.5x0.5 -x linear -o segmentationr.nii.gz', verbose) # run('sct_resample -i labelz.nii.gz -mm 0.5x0.5x0.5 -x linear -o labelzr.nii', verbose) # Apply straightening to segmentation # N.B. Output is RPI printv('\nApply straightening to segmentation...', verbose) run('sct_apply_transfo -i segmentation.nii.gz -d data_straightr.nii -w warp_curve2straight.nii.gz -o segmentation_straight.nii.gz -x linear', verbose) # Threshold segmentation at 0.5 run('sct_maths -i segmentation_straight.nii.gz -thr 0.5 -o segmentation_straight.nii.gz', verbose) if initauto: init_disc = [] else: # Apply straightening to z-label printv('\nDilate z-label and apply straightening...', verbose) run('sct_apply_transfo -i labelz.nii.gz -d data_straightr.nii -w warp_curve2straight.nii.gz -o labelz_straight.nii.gz -x nn', verbose) # get z value and disk value to initialize labeling printv('\nGet z and disc values from straight label...', verbose) init_disc = get_z_and_disc_values_from_label('labelz_straight.nii.gz') printv('.. '+str(init_disc), verbose) # denoise data if denoise: printv('\nDenoise data...', verbose) run('sct_maths -i data_straightr.nii -denoise h=0.05 -o data_straightr.nii', verbose) # apply laplacian filtering if laplacian: printv('\nApply Laplacian filter...', verbose) run('sct_maths -i data_straightr.nii -laplacian 1 -o data_straightr.nii', verbose) # detect vertebral levels on straight spinal cord vertebral_detection('data_straightr.nii', 'segmentation_straight.nii.gz', contrast, param, init_disc=init_disc, verbose=verbose, path_template=path_template, initc2=initc2, path_output=path_output) # un-straighten labeled spinal cord printv('\nUn-straighten labeling...', verbose) run('sct_apply_transfo -i segmentation_straight_labeled.nii.gz -d segmentation.nii.gz -w warp_straight2curve.nii.gz -o segmentation_labeled.nii.gz -x nn', verbose) # Clean labeled segmentation printv('\nClean labeled segmentation (correct interpolation errors)...', verbose) clean_labeled_segmentation('segmentation_labeled.nii.gz', 'segmentation.nii.gz', 'segmentation_labeled.nii.gz') # label discs printv('\nLabel discs...', verbose) label_discs('segmentation_labeled.nii.gz', verbose=verbose) # come back to parent folder os.chdir('..') # Generate output files path_seg, file_seg, ext_seg = extract_fname(fname_seg) printv('\nGenerate output files...', verbose) generate_output_file(path_tmp+'segmentation_labeled.nii.gz', path_output+file_seg+'_labeled'+ext_seg) generate_output_file(path_tmp+'segmentation_labeled_disc.nii.gz', path_output+file_seg+'_labeled_discs'+ext_seg) # copy straightening files in case subsequent SCT functions need them generate_output_file(path_tmp+'warp_curve2straight.nii.gz', path_output+'warp_curve2straight.nii.gz', verbose) generate_output_file(path_tmp+'warp_straight2curve.nii.gz', path_output+'warp_straight2curve.nii.gz', verbose) generate_output_file(path_tmp+'straight_ref.nii.gz', path_output+'straight_ref.nii.gz', verbose) # Remove temporary files if remove_tmp_files == 1: printv('\nRemove temporary files...', verbose) run('rm -rf '+path_tmp) # to view results printv('\nDone! To view results, type:', verbose) printv('fslview '+fname_in+' '+path_output+file_seg+'_labeled'+' -l Random-Rainbow -t 0.5 &\n', verbose, 'info')
def main(): # get default parameters step1 = Paramreg(step='1', type='seg', algo='slicereg', metric='MeanSquares', iter='10') step2 = Paramreg(step='2', type='im', algo='syn', metric='MI', iter='3') # step1 = Paramreg() paramreg = ParamregMultiStep([step1, step2]) # step1 = Paramreg_step(step='1', type='seg', algo='bsplinesyn', metric='MeanSquares', iter='10', shrink='1', smooth='0', gradStep='0.5') # step2 = Paramreg_step(step='2', type='im', algo='syn', metric='MI', iter='10', shrink='1', smooth='0', gradStep='0.5') # paramreg = ParamregMultiStep([step1, step2]) # Initialize the parser parser = Parser(__file__) parser.usage.set_description('Register anatomical image to the template.') parser.add_option(name="-i", type_value="file", description="Anatomical image.", mandatory=True, example="anat.nii.gz") parser.add_option(name="-s", type_value="file", description="Spinal cord segmentation.", mandatory=True, example="anat_seg.nii.gz") parser.add_option(name="-l", type_value="file", description="Labels. See: http://sourceforge.net/p/spinalcordtoolbox/wiki/create_labels/", mandatory=True, default_value='', example="anat_labels.nii.gz") parser.add_option(name="-t", type_value="folder", description="Path to MNI-Poly-AMU template.", mandatory=False, default_value=param.path_template) parser.add_option(name="-p", type_value=[[':'], 'str'], description="""Parameters for registration (see sct_register_multimodal). Default:\n--\nstep=1\ntype="""+paramreg.steps['1'].type+"""\nalgo="""+paramreg.steps['1'].algo+"""\nmetric="""+paramreg.steps['1'].metric+"""\npoly="""+paramreg.steps['1'].poly+"""\n--\nstep=2\ntype="""+paramreg.steps['2'].type+"""\nalgo="""+paramreg.steps['2'].algo+"""\nmetric="""+paramreg.steps['2'].metric+"""\niter="""+paramreg.steps['2'].iter+"""\nshrink="""+paramreg.steps['2'].shrink+"""\nsmooth="""+paramreg.steps['2'].smooth+"""\ngradStep="""+paramreg.steps['2'].gradStep+"""\n--""", mandatory=False, example="step=2,type=seg,algo=bsplinesyn,metric=MeanSquares,iter=5,shrink=2:step=3,type=im,algo=syn,metric=MI,iter=5,shrink=1,gradStep=0.3") parser.add_option(name="-r", type_value="multiple_choice", description="""Remove temporary files.""", mandatory=False, default_value='1', example=['0', '1']) parser.add_option(name="-v", type_value="multiple_choice", description="""Verbose. 0: nothing. 1: basic. 2: extended.""", mandatory=False, default_value=param.verbose, example=['0', '1', '2']) if param.debug: print '\n*** WARNING: DEBUG MODE ON ***\n' fname_data = '/Users/julien/data/temp/sct_example_data/t2/t2.nii.gz' fname_landmarks = '/Users/julien/data/temp/sct_example_data/t2/labels.nii.gz' fname_seg = '/Users/julien/data/temp/sct_example_data/t2/t2_seg.nii.gz' path_template = param.path_template remove_temp_files = 0 verbose = 2 # speed = 'superfast' #param_reg = '2,BSplineSyN,0.6,MeanSquares' else: arguments = parser.parse(sys.argv[1:]) # get arguments fname_data = arguments['-i'] fname_seg = arguments['-s'] fname_landmarks = arguments['-l'] path_template = arguments['-t'] remove_temp_files = int(arguments['-r']) verbose = int(arguments['-v']) if '-p' in arguments: paramreg_user = arguments['-p'] # update registration parameters for paramStep in paramreg_user: paramreg.addStep(paramStep) # initialize other parameters file_template = param.file_template file_template_label = param.file_template_label file_template_seg = param.file_template_seg output_type = param.output_type zsubsample = param.zsubsample # smoothing_sigma = param.smoothing_sigma # start timer start_time = time.time() # get absolute path - TO DO: remove! NEVER USE ABSOLUTE PATH... path_template = os.path.abspath(path_template) # get fname of the template + template objects fname_template = sct.slash_at_the_end(path_template, 1)+file_template fname_template_label = sct.slash_at_the_end(path_template, 1)+file_template_label fname_template_seg = sct.slash_at_the_end(path_template, 1)+file_template_seg # check file existence sct.printv('\nCheck template files...') sct.check_file_exist(fname_template, verbose) sct.check_file_exist(fname_template_label, verbose) sct.check_file_exist(fname_template_seg, verbose) # print arguments sct.printv('\nCheck parameters:', verbose) sct.printv('.. Data: '+fname_data, verbose) sct.printv('.. Landmarks: '+fname_landmarks, verbose) sct.printv('.. Segmentation: '+fname_seg, verbose) sct.printv('.. Path template: '+path_template, verbose) sct.printv('.. Output type: '+str(output_type), verbose) sct.printv('.. Remove temp files: '+str(remove_temp_files), verbose) sct.printv('\nParameters for registration:') for pStep in range(1, len(paramreg.steps)+1): sct.printv('Step #'+paramreg.steps[str(pStep)].step, verbose) sct.printv('.. Type #'+paramreg.steps[str(pStep)].type, verbose) sct.printv('.. Algorithm................ '+paramreg.steps[str(pStep)].algo, verbose) sct.printv('.. Metric................... '+paramreg.steps[str(pStep)].metric, verbose) sct.printv('.. Number of iterations..... '+paramreg.steps[str(pStep)].iter, verbose) sct.printv('.. Shrink factor............ '+paramreg.steps[str(pStep)].shrink, verbose) sct.printv('.. Smoothing factor......... '+paramreg.steps[str(pStep)].smooth, verbose) sct.printv('.. Gradient step............ '+paramreg.steps[str(pStep)].gradStep, verbose) sct.printv('.. Degree of polynomial..... '+paramreg.steps[str(pStep)].poly, verbose) path_data, file_data, ext_data = sct.extract_fname(fname_data) sct.printv('\nCheck input labels...') # check if label image contains coherent labels image_label = Image(fname_landmarks) # -> all labels must be different labels = image_label.getNonZeroCoordinates(sorting='value') hasDifferentLabels = True for lab in labels: for otherlabel in labels: if lab != otherlabel and lab.hasEqualValue(otherlabel): hasDifferentLabels = False break if not hasDifferentLabels: sct.printv('ERROR: Wrong landmarks input. All labels must be different.', verbose, 'error') # all labels must be available in tempalte image_label_template = Image(fname_template_label) labels_template = image_label_template.getNonZeroCoordinates(sorting='value') if labels[-1].value > labels_template[-1].value: sct.printv('ERROR: Wrong landmarks input. Labels must have correspondance in tempalte space. \nLabel max ' 'provided: ' + str(labels[-1].value) + '\nLabel max from template: ' + str(labels_template[-1].value), verbose, 'error') # 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) # copy files to temporary folder sct.printv('\nCopy files...', verbose) sct.run('isct_c3d '+fname_data+' -o '+path_tmp+'/data.nii') sct.run('isct_c3d '+fname_landmarks+' -o '+path_tmp+'/landmarks.nii.gz') sct.run('isct_c3d '+fname_seg+' -o '+path_tmp+'/segmentation.nii.gz') sct.run('isct_c3d '+fname_template+' -o '+path_tmp+'/template.nii') sct.run('isct_c3d '+fname_template_label+' -o '+path_tmp+'/template_labels.nii.gz') sct.run('isct_c3d '+fname_template_seg+' -o '+path_tmp+'/template_seg.nii.gz') # go to tmp folder os.chdir(path_tmp) # resample data to 1mm isotropic sct.printv('\nResample data to 1mm isotropic...', verbose) sct.run('isct_c3d data.nii -resample-mm 1.0x1.0x1.0mm -interpolation Linear -o datar.nii') sct.run('isct_c3d segmentation.nii.gz -resample-mm 1.0x1.0x1.0mm -interpolation NearestNeighbor -o segmentationr.nii.gz') # N.B. resampling of labels is more complicated, because they are single-point labels, therefore resampling with neighrest neighbour can make them disappear. Therefore a more clever approach is required. resample_labels('landmarks.nii.gz', 'datar.nii', 'landmarksr.nii.gz') # # TODO # sct.run('sct_label_utils -i datar.nii -t create -x 124,186,19,2:129,98,23,8 -o landmarksr.nii.gz') # Change orientation of input images to RPI sct.printv('\nChange orientation of input images to RPI...', verbose) set_orientation('datar.nii', 'RPI', 'data_rpi.nii') set_orientation('landmarksr.nii.gz', 'RPI', 'landmarks_rpi.nii.gz') set_orientation('segmentationr.nii.gz', 'RPI', 'segmentation_rpi.nii.gz') # # Change orientation of input images to RPI # sct.printv('\nChange orientation of input images to RPI...', verbose) # set_orientation('data.nii', 'RPI', 'data_rpi.nii') # set_orientation('landmarks.nii.gz', 'RPI', 'landmarks_rpi.nii.gz') # set_orientation('segmentation.nii.gz', 'RPI', 'segmentation_rpi.nii.gz') # get landmarks in native space # crop segmentation # output: segmentation_rpi_crop.nii.gz sct.run('sct_crop_image -i segmentation_rpi.nii.gz -o segmentation_rpi_crop.nii.gz -dim 2 -bzmax') # straighten segmentation sct.printv('\nStraighten the spinal cord using centerline/segmentation...', verbose) sct.run('sct_straighten_spinalcord -i segmentation_rpi_crop.nii.gz -c segmentation_rpi_crop.nii.gz -r 0 -v '+str(verbose), verbose) # re-define warping field using non-cropped space (to avoid issue #367) sct.run('sct_concat_transfo -w warp_straight2curve.nii.gz -d data_rpi.nii -o warp_straight2curve.nii.gz') # Label preparation: # -------------------------------------------------------------------------------- # Remove unused label on template. Keep only label present in the input label image sct.printv('\nRemove unused label on template. Keep only label present in the input label image...', verbose) sct.run('sct_label_utils -t remove -i template_labels.nii.gz -o template_label.nii.gz -r landmarks_rpi.nii.gz') # Make sure landmarks are INT sct.printv('\nConvert landmarks to INT...', verbose) sct.run('isct_c3d template_label.nii.gz -type int -o template_label.nii.gz', verbose) # Create a cross for the template labels - 5 mm sct.printv('\nCreate a 5 mm cross for the template labels...', verbose) sct.run('sct_label_utils -t cross -i template_label.nii.gz -o template_label_cross.nii.gz -c 5') # Create a cross for the input labels and dilate for straightening preparation - 5 mm sct.printv('\nCreate a 5mm cross for the input labels and dilate for straightening preparation...', verbose) sct.run('sct_label_utils -t cross -i landmarks_rpi.nii.gz -o landmarks_rpi_cross3x3.nii.gz -c 5 -d') # Apply straightening to labels sct.printv('\nApply straightening to labels...', verbose) sct.run('sct_apply_transfo -i landmarks_rpi_cross3x3.nii.gz -o landmarks_rpi_cross3x3_straight.nii.gz -d segmentation_rpi_crop_straight.nii.gz -w warp_curve2straight.nii.gz -x nn') # Convert landmarks from FLOAT32 to INT sct.printv('\nConvert landmarks from FLOAT32 to INT...', verbose) sct.run('isct_c3d landmarks_rpi_cross3x3_straight.nii.gz -type int -o landmarks_rpi_cross3x3_straight.nii.gz') # Remove labels that do not correspond with each others. sct.printv('\nRemove labels that do not correspond with each others.', verbose) sct.run('sct_label_utils -t remove-symm -i landmarks_rpi_cross3x3_straight.nii.gz -o landmarks_rpi_cross3x3_straight.nii.gz,template_label_cross.nii.gz -r template_label_cross.nii.gz') # Estimate affine transfo: straight --> template (landmark-based)' sct.printv('\nEstimate affine transfo: straight anat --> template (landmark-based)...', verbose) # converting landmarks straight and curved to physical coordinates image_straight = Image('landmarks_rpi_cross3x3_straight.nii.gz') landmark_straight = image_straight.getNonZeroCoordinates(sorting='value') image_template = Image('template_label_cross.nii.gz') landmark_template = image_template.getNonZeroCoordinates(sorting='value') # Reorganize landmarks points_fixed, points_moving = [], [] landmark_straight_mean = [] for coord in landmark_straight: if coord.value not in [c.value for c in landmark_straight_mean]: temp_landmark = coord temp_number = 1 for other_coord in landmark_straight: if coord.hasEqualValue(other_coord) and coord != other_coord: temp_landmark += other_coord temp_number += 1 landmark_straight_mean.append(temp_landmark / temp_number) for coord in landmark_straight_mean: point_straight = image_straight.transfo_pix2phys([[coord.x, coord.y, coord.z]]) points_moving.append([point_straight[0][0], point_straight[0][1], point_straight[0][2]]) for coord in landmark_template: point_template = image_template.transfo_pix2phys([[coord.x, coord.y, coord.z]]) points_fixed.append([point_template[0][0], point_template[0][1], point_template[0][2]]) # Register curved landmarks on straight landmarks based on python implementation sct.printv('\nComputing rigid transformation (algo=translation-scaling-z) ...', verbose) import msct_register_landmarks (rotation_matrix, translation_array, points_moving_reg, points_moving_barycenter) = \ msct_register_landmarks.getRigidTransformFromLandmarks( points_fixed, points_moving, constraints='translation-scaling-z', show=False) # writing rigid transformation file text_file = open("straight2templateAffine.txt", "w") text_file.write("#Insight Transform File V1.0\n") text_file.write("#Transform 0\n") text_file.write("Transform: FixedCenterOfRotationAffineTransform_double_3_3\n") text_file.write("Parameters: %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f %.9f\n" % ( 1.0/rotation_matrix[0, 0], rotation_matrix[0, 1], rotation_matrix[0, 2], rotation_matrix[1, 0], 1.0/rotation_matrix[1, 1], rotation_matrix[1, 2], rotation_matrix[2, 0], rotation_matrix[2, 1], 1.0/rotation_matrix[2, 2], translation_array[0, 0], translation_array[0, 1], -translation_array[0, 2])) text_file.write("FixedParameters: %.9f %.9f %.9f\n" % (points_moving_barycenter[0], points_moving_barycenter[1], points_moving_barycenter[2])) text_file.close() # Apply affine transformation: straight --> template sct.printv('\nApply affine transformation: straight --> template...', verbose) sct.run('sct_concat_transfo -w warp_curve2straight.nii.gz,straight2templateAffine.txt -d template.nii -o warp_curve2straightAffine.nii.gz') sct.run('sct_apply_transfo -i data_rpi.nii -o data_rpi_straight2templateAffine.nii -d template.nii -w warp_curve2straightAffine.nii.gz') sct.run('sct_apply_transfo -i segmentation_rpi.nii.gz -o segmentation_rpi_straight2templateAffine.nii.gz -d template.nii -w warp_curve2straightAffine.nii.gz -x linear') # threshold to 0.5 nii = Image('segmentation_rpi_straight2templateAffine.nii.gz') data = nii.data data[data < 0.5] = 0 nii.data = data nii.setFileName('segmentation_rpi_straight2templateAffine_th.nii.gz') nii.save() # find min-max of anat2template (for subsequent cropping) zmin_template, zmax_template = find_zmin_zmax('segmentation_rpi_straight2templateAffine_th.nii.gz') # crop template in z-direction (for faster processing) sct.printv('\nCrop data in template space (for faster processing)...', verbose) sct.run('sct_crop_image -i template.nii -o template_crop.nii -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template)) sct.run('sct_crop_image -i template_seg.nii.gz -o template_seg_crop.nii.gz -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template)) sct.run('sct_crop_image -i data_rpi_straight2templateAffine.nii -o data_rpi_straight2templateAffine_crop.nii -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template)) sct.run('sct_crop_image -i segmentation_rpi_straight2templateAffine.nii.gz -o segmentation_rpi_straight2templateAffine_crop.nii.gz -dim 2 -start '+str(zmin_template)+' -end '+str(zmax_template)) # sub-sample in z-direction sct.printv('\nSub-sample in z-direction (for faster processing)...', verbose) sct.run('sct_resample -i template_crop.nii -o template_crop_r.nii -f 1x1x'+zsubsample, verbose) sct.run('sct_resample -i template_seg_crop.nii.gz -o template_seg_crop_r.nii.gz -f 1x1x'+zsubsample, verbose) sct.run('sct_resample -i data_rpi_straight2templateAffine_crop.nii -o data_rpi_straight2templateAffine_crop_r.nii -f 1x1x'+zsubsample, verbose) sct.run('sct_resample -i segmentation_rpi_straight2templateAffine_crop.nii.gz -o segmentation_rpi_straight2templateAffine_crop_r.nii.gz -f 1x1x'+zsubsample, verbose) # Registration straight spinal cord to template sct.printv('\nRegister straight spinal cord to template...', verbose) # loop across registration steps warp_forward = [] warp_inverse = [] for i_step in range(1, len(paramreg.steps)+1): sct.printv('\nEstimate transformation for step #'+str(i_step)+'...', verbose) # identify which is the src and dest if paramreg.steps[str(i_step)].type == 'im': src = 'data_rpi_straight2templateAffine_crop_r.nii' dest = 'template_crop_r.nii' interp_step = 'linear' elif paramreg.steps[str(i_step)].type == 'seg': src = 'segmentation_rpi_straight2templateAffine_crop_r.nii.gz' dest = 'template_seg_crop_r.nii.gz' interp_step = 'nn' else: sct.printv('ERROR: Wrong image type.', 1, 'error') # if step>1, apply warp_forward_concat to the src image to be used if i_step > 1: # sct.run('sct_apply_transfo -i '+src+' -d '+dest+' -w '+','.join(warp_forward)+' -o '+sct.add_suffix(src, '_reg')+' -x '+interp_step, 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.append(warp_inverse_out) # Concatenate transformations: sct.printv('\nConcatenate transformations: anat --> template...', verbose) sct.run('sct_concat_transfo -w warp_curve2straightAffine.nii.gz,'+','.join(warp_forward)+' -d template.nii -o warp_anat2template.nii.gz', verbose) # sct.run('sct_concat_transfo -w warp_curve2straight.nii.gz,straight2templateAffine.txt,'+','.join(warp_forward)+' -d template.nii -o warp_anat2template.nii.gz', verbose) warp_inverse.reverse() sct.run('sct_concat_transfo -w '+','.join(warp_inverse)+',-straight2templateAffine.txt,warp_straight2curve.nii.gz -d data.nii -o warp_template2anat.nii.gz', verbose) # Apply warping fields to anat and template if output_type == 1: sct.run('sct_apply_transfo -i template.nii -o template2anat.nii.gz -d data.nii -w warp_template2anat.nii.gz -c 1', verbose) sct.run('sct_apply_transfo -i data.nii -o anat2template.nii.gz -d template.nii -w warp_anat2template.nii.gz -c 1', verbose) # come back to parent folder os.chdir('..') # Generate output files sct.printv('\nGenerate output files...', verbose) sct.generate_output_file(path_tmp+'/warp_template2anat.nii.gz', 'warp_template2anat.nii.gz', verbose) sct.generate_output_file(path_tmp+'/warp_anat2template.nii.gz', 'warp_anat2template.nii.gz', verbose) if output_type == 1: sct.generate_output_file(path_tmp+'/template2anat.nii.gz', 'template2anat'+ext_data, verbose) sct.generate_output_file(path_tmp+'/anat2template.nii.gz', 'anat2template'+ext_data, verbose) # Delete temporary files if remove_temp_files: sct.printv('\nDelete temporary files...', verbose) 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', verbose) # to view results sct.printv('\nTo view results, type:', verbose) sct.printv('fslview '+fname_data+' template2anat -b 0,4000 &', verbose, 'info') sct.printv('fslview '+fname_template+' -b 0,5000 anat2template &\n', verbose, 'info')
def __init__(self, fname_src, fname_transfo, warp_atlas, warp_spinal_levels, folder_out, path_template, verbose, qc): # Initialization self.fname_src = fname_src self.fname_transfo = fname_transfo self.warp_atlas = warp_atlas self.warp_spinal_levels = warp_spinal_levels self.folder_out = folder_out self.path_template = path_template self.folder_template = param.folder_template self.folder_atlas = param.folder_atlas self.folder_spinal_levels = param.folder_spinal_levels self.verbose = verbose self.qc = qc start_time = time.time() # Check file existence sct.printv('\nCheck file existence...', self.verbose) sct.check_file_exist(self.fname_src) sct.check_file_exist(self.fname_transfo) # add slash at the end of folder name (in case there is no slash) self.path_template = sct.slash_at_the_end(self.path_template, 1) self.folder_out = sct.slash_at_the_end(self.folder_out, 1) self.folder_template = sct.slash_at_the_end(self.folder_template, 1) self.folder_atlas = sct.slash_at_the_end(self.folder_atlas, 1) self.folder_spinal_levels = sct.slash_at_the_end(self.folder_spinal_levels, 1) # print arguments print '\nCheck parameters:' print ' Destination image ........ '+self.fname_src print ' Warping field ............ '+self.fname_transfo print ' Path template ............ '+self.path_template print ' Output folder ............ '+self.folder_out+'\n' # Extract path, file and extension path_src, file_src, ext_src = sct.extract_fname(self.fname_src) # create output folder if os.path.exists(self.folder_out): sct.printv('WARNING: Output folder already exists. Deleting it...', self.verbose, 'warning') sct.run('rm -rf '+self.folder_out) sct.run('mkdir '+self.folder_out) # Warp template objects sct.printv('\nWarp template objects...', self.verbose) warp_label(self.path_template, self.folder_template, param.file_info_label, self.fname_src, self.fname_transfo, self.folder_out) # Warp atlas if self.warp_atlas == 1: sct.printv('\nWarp atlas of white matter tracts...', self.verbose) warp_label(self.path_template, self.folder_atlas, param.file_info_label, self.fname_src, self.fname_transfo, self.folder_out) # Warp spinal levels if self.warp_spinal_levels == 1: sct.printv('\nWarp spinal levels...', self.verbose) warp_label(self.path_template, self.folder_spinal_levels, param.file_info_label, self.fname_src, self.fname_transfo, self.folder_out) # to view results sct.printv('\nDone! To view results, type:', self.verbose) sct.printv('fslview '+self.fname_src+' '+self.folder_out+self.folder_template+'MNI-Poly-AMU_T2.nii.gz -b 0,4000 '+self.folder_out+self.folder_template+'MNI-Poly-AMU_level.nii.gz -l MGH-Cortical -t 0.5 '+self.folder_out+self.folder_template+'MNI-Poly-AMU_GM.nii.gz -l Red-Yellow -b 0.5,1 '+self.folder_out+self.folder_template+'MNI-Poly-AMU_WM.nii.gz -l Blue-Lightblue -b 0.5,1 &\n', self.verbose, 'info') if self.qc: from msct_image import Image # output QC image im = Image(self.fname_src) im_wm = Image(self.folder_out+self.folder_template+'MNI-Poly-AMU_WM.nii.gz') im.save_quality_control(plane='axial', n_slices=4, seg=im_wm, thr=0.5, cmap_col='blue-cyan', path_output=self.folder_out)
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 get_or_set_orientation(): 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 == '': sct.printv('ERROR: All mandatory arguments are not provided. See usage.', 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) # find what to do if param.orientation == '': todo = 'get_orientation' else: todo = 'set_orientation' # check if orientation is correct if check_orientation_input(): sct.printv('\nERROR in '+os.path.basename(__file__)+': orientation is not recognized. Use one of the following orientation: '+param.list_of_correct_orientation+'\n', 1, 'error') sys.exit(2) # display input parameters sct.printv('\nInput parameters:', param.verbose) sct.printv(' data ..................'+param.fname_data, param.verbose) # Extract path/file/extension path_data, file_data, ext_data = sct.extract_fname(param.fname_data) if param.fname_out == '': # path_out, file_out, ext_out = '', file_data+'_'+param.orientation, ext_data fname_out = path_data+file_data+'_'+param.orientation+ext_data else: fname_out = param.fname_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) sct.run('cp '+param.fname_data+' '+path_tmp+'data'+ext_data, param.verbose) # go to tmp folder os.chdir(path_tmp) # convert to nii format sct.run('fslchfiletype NIFTI data', param.verbose) # Get dimensions of data sct.printv('\nGet dimensions of data...', param.verbose) nx, ny, nz, nt, px, py, pz, pt = sct.get_dimension('data.nii') sct.printv(' ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz)+ ' x ' + str(nt), param.verbose) # if 4d, loop across the data if nt == 1: if todo == 'set_orientation': # set orientation sct.printv('\nChange orientation...', param.verbose) set_orientation('data.nii', param.orientation, 'data_orient.nii') elif todo == 'get_orientation': # get orientation sct.printv('\nGet orientation...', param.verbose) sct.printv(get_orientation('data.nii'), 1) else: # split along T dimension sct.printv('\nSplit along T dimension...', param.verbose) sct.run(fsloutput+'fslsplit data data_T', param.verbose) if todo == 'set_orientation': # set orientation sct.printv('\nChange orientation...', param.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, param.orientation, file_data_split_orient) # Merge files back sct.printv('\nMerge file back...', param.verbose) cmd = fsloutput+'fslmerge -t data_orient' for it in range(nt): file_data_split_orient = 'data_orient_T'+str(it).zfill(4)+'.nii' cmd = cmd+' '+file_data_split_orient sct.run(cmd, param.verbose) elif todo == 'get_orientation': sct.printv('\nGet orientation...', param.verbose) sct.printv(get_orientation('data_T0000.nii'), 1) # come back to parent folder os.chdir('..') # Generate output files if todo == 'set_orientation': sct.printv('\nGenerate output files...', param.verbose) sct.generate_output_file(path_tmp+'data_orient.nii', 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 if todo == 'set_orientation': sct.printv('\nDone! To view results, type:', param.verbose) sct.printv('fslview '+fname_out+' &', param.verbose, 'code') print
def main(): # Initialization fname_src = '' fname_transfo = '' folder_out = param.folder_out path_template = param.path_template folder_template = param.folder_template folder_atlas = param.folder_atlas folder_spinal_levels = param.folder_spinal_levels file_info_label = param.file_info_label warp_template = param.warp_template warp_atlas = param.warp_atlas warp_spinal_levels = param.warp_spinal_levels verbose = param.verbose start_time = time.time() # Parameters for debug mode if param.debug: print '\n*** WARNING: DEBUG MODE ON ***\n' fname_src = path_sct+'/testing/sct_testing_data/data/mt/mtr.nii.gz' fname_transfo = path_sct+'/testing/sct_testing_data/data/mt/warp_template2mt.nii.gz' warp_atlas = 1 warp_spinal_levels = 1 verbose = 1 else: # Check input parameters try: opts, args = getopt.getopt(sys.argv[1:], 'ha:d:w:o:s:t:v:') except getopt.GetoptError: usage() for opt, arg in opts: if opt == '-h': usage() elif opt in ("-a"): warp_atlas = int(arg) elif opt in ("-d"): fname_src = arg elif opt in ("-o"): folder_out = arg elif opt in ("-t"): path_template = arg elif opt in ("-s"): warp_spinal_levels = int(arg) elif opt in ('-v'): verbose = int(arg) elif opt in ("-w"): fname_transfo = arg # display usage if a mandatory argument is not provided if fname_src == '' or fname_transfo == '': usage() # Check file existence sct.printv('\nCheck file existence...', verbose) sct.check_file_exist(fname_src) sct.check_file_exist(fname_transfo) # add slash at the end of folder name (in case there is no slash) path_template = sct.slash_at_the_end(path_template, 1) folder_out = sct.slash_at_the_end(folder_out, 1) folder_template = sct.slash_at_the_end(folder_template, 1) folder_atlas = sct.slash_at_the_end(folder_atlas, 1) folder_spinal_levels = sct.slash_at_the_end(folder_spinal_levels, 1) # print arguments print '\nCheck parameters:' print ' Destination image ........ '+fname_src print ' Warping field ............ '+fname_transfo print ' Path template ............ '+path_template print ' Output folder ............ '+folder_out+'\n' # Extract path, file and extension path_src, file_src, ext_src = sct.extract_fname(fname_src) # create output folder if os.path.exists(folder_out): sct.printv('WARNING: Output folder already exists. Deleting it...', verbose) sct.run('rm -rf '+folder_out) sct.run('mkdir '+folder_out) # Warp template objects if warp_template == 1: sct.printv('\nWarp template objects...', verbose) warp_label(path_template, folder_template, param.file_info_label, fname_src, fname_transfo, folder_out) # Warp atlas if warp_atlas == 1: sct.printv('\nWarp atlas of white matter tracts...', verbose) warp_label(path_template, folder_atlas, param.file_info_label, fname_src, fname_transfo, folder_out) # Warp spinal levels if warp_spinal_levels == 1: sct.printv('\nWarp spinal levels...', verbose) warp_label(path_template, folder_spinal_levels, param.file_info_label, fname_src, fname_transfo, folder_out) # to view results sct.printv('\nDone! To view results, type:', verbose) sct.printv('fslview '+fname_src+' '+folder_out+folder_template+'MNI-Poly-AMU_T2.nii.gz -b 0,4000 '+folder_out+folder_template+'MNI-Poly-AMU_level.nii.gz -l MGH-Cortical -t 0.5 '+folder_out+folder_template+'MNI-Poly-AMU_GM.nii.gz -l Red-Yellow -b 0.5,1 '+folder_out+folder_template+'MNI-Poly-AMU_WM.nii.gz -l Blue-Lightblue -b 0.5,1 &\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(): # 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() # Check input param try: opts, args = getopt.getopt(sys.argv[1:], 'hi:c:r:s:v:') 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 ('-c'): fname_centerline = arg elif opt in ('-i'): fname_anat = arg elif opt in ('-r'): remove_temp_files = arg elif opt in ('-s'): sigma = arg elif opt in ('-v'): verbose = int(arg) # Display usage if a mandatory argument is not provided if fname_anat == '' or fname_centerline == '': usage() # Display arguments print '\nCheck input arguments...' print ' Volume to smooth .................. ' + fname_anat print ' Centerline ........................ ' + fname_centerline print ' FWHM .............................. '+str(sigma) print ' Verbose ........................... '+str(verbose) # Check existence of input files print('\nCheck existence of input files...') sct.check_file_exist(fname_anat, verbose) sct.check_file_exist(fname_centerline, verbose) # 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...' set_orientation('anat.nii', 'RPI', 'anat_rpi.nii') # Change orientation of the input image into RPI print '\nOrient centerline to RPI orientation...' set_orientation('centerline.nii', 'RPI', 'centerline_rpi.nii') # ## new # # ### Make sure that centerline file does not have halls # file_c = load('centerline_rpi.nii') # data_c = file_c.get_data() # hdr_c = file_c.get_header() # # data_temp = copy(data_c) # data_temp *= 0 # data_output = copy(data_c) # data_output *= 0 # nx, ny, nz, nt, px, py, pz, pt = sct.get_dimension('centerline_rpi.nii') # # ## Change seg to centerline if it is a segmentation # sct.printv('\nChange segmentation to centerline if it is a centerline...\n') # z_centerline = [iz for iz in range(0, nz, 1) if data_c[:,:,iz].any() ] # nz_nonz = len(z_centerline) # if nz_nonz==0 : # print '\nERROR: Centerline is empty' # sys.exit() # x_centerline = [0 for iz in range(0, nz_nonz, 1)] # y_centerline = [0 for iz in range(0, nz_nonz, 1)] # #print("z_centerline", z_centerline,nz_nonz,len(x_centerline)) # print '\nGet center of mass of the centerline ...' # for iz in xrange(len(z_centerline)): # x_centerline[iz], y_centerline[iz] = ndimage.measurements.center_of_mass(array(data_c[:,:,z_centerline[iz]])) # data_temp[x_centerline[iz], y_centerline[iz], z_centerline[iz]] = 1 # # ## Complete centerline # sct.printv('\nComplete the halls of the centerline if there are any...\n') # X,Y,Z = data_temp.nonzero() # # x_centerline_extended = [0 for i in range(0, nz, 1)] # y_centerline_extended = [0 for i in range(0, nz, 1)] # for iz in range(len(Z)): # x_centerline_extended[Z[iz]] = X[iz] # y_centerline_extended[Z[iz]] = Y[iz] # # X_centerline_extended = nonzero(x_centerline_extended) # X_centerline_extended = transpose(X_centerline_extended) # Y_centerline_extended = nonzero(y_centerline_extended) # Y_centerline_extended = transpose(Y_centerline_extended) # # # initialization: we set the extrem values to avoid edge effects # x_centerline_extended[0] = x_centerline_extended[X_centerline_extended[0]] # x_centerline_extended[-1] = x_centerline_extended[X_centerline_extended[-1]] # y_centerline_extended[0] = y_centerline_extended[Y_centerline_extended[0]] # y_centerline_extended[-1] = y_centerline_extended[Y_centerline_extended[-1]] # # # Add two rows to the vector X_means_smooth_extended: # # one before as means_smooth_extended[0] is now diff from 0 # # one after as means_smooth_extended[-1] is now diff from 0 # X_centerline_extended = append(X_centerline_extended, len(x_centerline_extended)-1) # X_centerline_extended = insert(X_centerline_extended, 0, 0) # Y_centerline_extended = append(Y_centerline_extended, len(y_centerline_extended)-1) # Y_centerline_extended = insert(Y_centerline_extended, 0, 0) # # #recurrence # count_zeros_x=0 # count_zeros_y=0 # for i in range(1,nz-1): # if x_centerline_extended[i]==0: # x_centerline_extended[i] = 0.5*(x_centerline_extended[X_centerline_extended[i-1-count_zeros_x]] + x_centerline_extended[X_centerline_extended[i-count_zeros_x]]) # count_zeros_x += 1 # if y_centerline_extended[i]==0: # y_centerline_extended[i] = 0.5*(y_centerline_extended[Y_centerline_extended[i-1-count_zeros_y]] + y_centerline_extended[Y_centerline_extended[i-count_zeros_y]]) # count_zeros_y += 1 # # # Save image centerline completed to be used after # sct.printv('\nSave image completed: centerline_rpi_completed.nii...\n') # for i in range(nz): # data_output[x_centerline_extended[i],y_centerline_extended[i],i] = 1 # img = Nifti1Image(data_output, None, hdr_c) # save(img, 'centerline_rpi_completed.nii') # # #end new # Straighten the spinal cord print '\nStraighten the spinal cord...' sct.run('sct_straighten_spinalcord -i anat_rpi.nii -c centerline_rpi.nii -x spline -v '+str(verbose)) # Smooth the straightened image along z print '\nSmooth the straightened image along z...' sct.run('isct_c3d anat_rpi_straight.nii -smooth 0x0x'+str(sigma)+'vox -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) # 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.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')