def check_if_rpi(fname): from sct_image import get_orientation_3d if not get_orientation_3d(fname, filename=True) == 'RPI': printv( '\nERROR: ' + fname + ' is not in RPI orientation. Use sct_image -setorient to reorient your data. Exit program.\n', 1, 'error')
def resample_image(fname, suffix='_resampled.nii.gz', binary=False, npx=0.3, npy=0.3, thr=0.0, interpolation='spline'): """ Resampling function: add a padding, resample, crop the padding :param fname: name of the image file to be resampled :param suffix: suffix added to the original fname after resampling :param binary: boolean, image is binary or not :param npx: new pixel size in the x direction :param npy: new pixel size in the y direction :param thr: if the image is binary, it will be thresholded at thr (default=0) after the resampling :param interpolation: type of interpolation used for the resampling :return: file name after resampling (or original fname if it was already in the correct resolution) """ im_in = Image(fname) orientation = get_orientation_3d(im_in) if orientation != 'RPI': im_in = set_orientation(im_in, 'RPI') im_in.save() fname = im_in.absolutepath nx, ny, nz, nt, px, py, pz, pt = im_in.dim if round(px, 2) != round(npx, 2) or round(py, 2) != round(npy, 2): name_resample = sct.extract_fname(fname)[1] + suffix if binary: interpolation = 'nn' sct.run('sct_resample -i ' + fname + ' -mm ' + str(npx) + 'x' + str(npy) + 'x' + str(pz) + ' -o ' + name_resample + ' -x ' + interpolation) if binary: # sct.run('sct_maths -i ' + name_resample + ' -thr ' + str(thr) + ' -o ' + name_resample) sct.run('sct_maths -i ' + name_resample + ' -bin ' + str(thr) + ' -o ' + name_resample) if orientation != 'RPI': im_resample = Image(name_resample) im_resample = set_orientation(im_resample, orientation) im_resample.save() name_resample = im_resample.absolutepath return name_resample else: if orientation != 'RPI': im_in = set_orientation(im_in, orientation) im_in.save() fname = im_in.absolutepath sct.printv('Image resolution already ' + str(npx) + 'x' + str(npy) + 'xpz') return fname
def resample_image(fname, suffix='_resampled.nii.gz', binary=False, npx=0.3, npy=0.3, thr=0.0, interpolation='spline'): """ Resampling function: add a padding, resample, crop the padding :param fname: name of the image file to be resampled :param suffix: suffix added to the original fname after resampling :param binary: boolean, image is binary or not :param npx: new pixel size in the x direction :param npy: new pixel size in the y direction :param thr: if the image is binary, it will be thresholded at thr (default=0) after the resampling :param interpolation: type of interpolation used for the resampling :return: file name after resampling (or original fname if it was already in the correct resolution) """ im_in = Image(fname) orientation = get_orientation_3d(im_in) if orientation != 'RPI': im_in = set_orientation(im_in, 'RPI') im_in.save() fname = im_in.absolutepath nx, ny, nz, nt, px, py, pz, pt = im_in.dim if round(px, 2) != round(npx, 2) or round(py, 2) != round(npy, 2): name_resample = sct.extract_fname(fname)[1] + suffix if binary: interpolation = 'nn' sct.run('sct_resample -i '+fname+' -mm '+str(npx)+'x'+str(npy)+'x'+str(pz)+' -o '+name_resample+' -x '+interpolation) if binary: # sct.run('sct_maths -i ' + name_resample + ' -thr ' + str(thr) + ' -o ' + name_resample) sct.run('sct_maths -i ' + name_resample + ' -bin ' + str(thr) + ' -o ' + name_resample) if orientation != 'RPI': im_resample = Image(name_resample) im_resample = set_orientation(im_resample, orientation) im_resample.save() name_resample = im_resample.absolutepath return name_resample else: if orientation != 'RPI': im_in = set_orientation(im_in, orientation) im_in.save() fname = im_in.absolutepath sct.printv('Image resolution already ' + str(npx) + 'x' + str(npy) + 'xpz') return fname
def get_centerline_from_point(input_image, point_file, gap=4, gaussian_kernel=4, remove_tmp_files=1): # Initialization fname_anat = input_image fname_point = point_file slice_gap = gap remove_tmp_files = remove_tmp_files gaussian_kernel = gaussian_kernel start_time = time() verbose = 1 # get path of the toolbox status, path_sct = commands.getstatusoutput("echo $SCT_DIR") path_sct = sct.slash_at_the_end(path_sct, 1) # Parameters for debug mode if param.debug == 1: sct.printv("\n*** WARNING: DEBUG MODE ON ***\n\t\t\tCurrent working directory: " + os.getcwd(), "warning") status, path_sct_testing_data = commands.getstatusoutput("echo $SCT_TESTING_DATA_DIR") fname_anat = path_sct_testing_data + "/t2/t2.nii.gz" fname_point = path_sct_testing_data + "/t2/t2_centerline_init.nii.gz" slice_gap = 5 # check existence of input files sct.check_file_exist(fname_anat) sct.check_file_exist(fname_point) # extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) path_point, file_point, ext_point = sct.extract_fname(fname_point) # extract path of schedule file # TODO: include schedule file in sct # TODO: check existence of schedule file file_schedule = path_sct + param.schedule_file # Get input image orientation input_image_orientation = get_orientation_3d(fname_anat, filename=True) # Display arguments print "\nCheck input arguments..." print " Anatomical image: " + fname_anat print " Orientation: " + input_image_orientation print " Point in spinal cord: " + fname_point print " Slice gap: " + str(slice_gap) print " Gaussian kernel: " + str(gaussian_kernel) print " Degree of polynomial: " + str(param.deg_poly) # create temporary folder print ("\nCreate temporary folder...") path_tmp = "tmp." + strftime("%y%m%d%H%M%S") sct.create_folder(path_tmp) print "\nCopy input data..." sct.run("cp " + fname_anat + " " + path_tmp + "/tmp.anat" + ext_anat) sct.run("cp " + fname_point + " " + path_tmp + "/tmp.point" + ext_point) # go to temporary folder os.chdir(path_tmp) # convert to nii im_anat = convert("tmp.anat" + ext_anat, "tmp.anat.nii") im_point = convert("tmp.point" + ext_point, "tmp.point.nii") # Reorient input anatomical volume into RL PA IS orientation print "\nReorient input volume to RL PA IS orientation..." set_orientation(im_anat, "RPI") im_anat.setFileName("tmp.anat_orient.nii") # Reorient binary point into RL PA IS orientation print "\nReorient binary point into RL PA IS orientation..." # sct.run(sct.fsloutput + 'fslswapdim tmp.point RL PA IS tmp.point_orient') set_orientation(im_point, "RPI") im_point.setFileName("tmp.point_orient.nii") # Get image dimensions print "\nGet image dimensions..." nx, ny, nz, nt, px, py, pz, pt = Image("tmp.anat_orient.nii").dim print ".. matrix size: " + str(nx) + " x " + str(ny) + " x " + str(nz) print ".. voxel size: " + str(px) + "mm x " + str(py) + "mm x " + str(pz) + "mm" # Split input volume print "\nSplit input volume..." im_anat_split_list = split_data(im_anat, 2) file_anat_split = [] for im in im_anat_split_list: file_anat_split.append(im.absolutepath) im.save() im_point_split_list = split_data(im_point, 2) file_point_split = [] for im in im_point_split_list: file_point_split.append(im.absolutepath) im.save() # Extract coordinates of input point data_point = Image("tmp.point_orient.nii").data x_init, y_init, z_init = unravel_index(data_point.argmax(), data_point.shape) sct.printv("Coordinates of input point: (" + str(x_init) + ", " + str(y_init) + ", " + str(z_init) + ")", verbose) # Create 2D gaussian mask sct.printv("\nCreate gaussian mask from point...", verbose) xx, yy = mgrid[:nx, :ny] mask2d = zeros((nx, ny)) radius = round(float(gaussian_kernel + 1) / 2) # add 1 because the radius includes the center. sigma = float(radius) mask2d = exp(-(((xx - x_init) ** 2) / (2 * (sigma ** 2)) + ((yy - y_init) ** 2) / (2 * (sigma ** 2)))) # Save mask to 2d file file_mask_split = ["tmp.mask_orient_Z" + str(z).zfill(4) for z in range(0, nz, 1)] nii_mask2d = Image("tmp.anat_orient_Z0000.nii") nii_mask2d.data = mask2d nii_mask2d.setFileName(file_mask_split[z_init] + ".nii") nii_mask2d.save() # initialize variables file_mat = ["tmp.mat_Z" + str(z).zfill(4) for z in range(0, nz, 1)] file_mat_inv = ["tmp.mat_inv_Z" + str(z).zfill(4) for z in range(0, nz, 1)] file_mat_inv_cumul = ["tmp.mat_inv_cumul_Z" + str(z).zfill(4) for z in range(0, nz, 1)] # create identity matrix for initial transformation matrix fid = open(file_mat_inv_cumul[z_init], "w") fid.write("%i %i %i %i\n" % (1, 0, 0, 0)) fid.write("%i %i %i %i\n" % (0, 1, 0, 0)) fid.write("%i %i %i %i\n" % (0, 0, 1, 0)) fid.write("%i %i %i %i\n" % (0, 0, 0, 1)) fid.close() # initialize centerline: give value corresponding to initial point x_centerline = [x_init] y_centerline = [y_init] z_centerline = [z_init] warning_count = 0 # go up (1), then down (2) in reference to the binary point for iUpDown in range(1, 3): if iUpDown == 1: # z increases slice_gap_signed = slice_gap elif iUpDown == 2: # z decreases slice_gap_signed = -slice_gap # reverse centerline (because values will be appended at the end) x_centerline.reverse() y_centerline.reverse() z_centerline.reverse() # initialization before looping z_dest = z_init # point given by user z_src = z_dest + slice_gap_signed # continue looping if 0 <= z < nz while 0 <= z_src < nz: # print current z: print "z=" + str(z_src) + ":" # estimate transformation sct.run( fsloutput + "flirt -in " + file_anat_split[z_src] + " -ref " + file_anat_split[z_dest] + " -schedule " + file_schedule + " -verbose 0 -omat " + file_mat[z_src] + " -cost normcorr -forcescaling -inweight " + file_mask_split[z_dest] + " -refweight " + file_mask_split[z_dest] ) # display transfo status, output = sct.run("cat " + file_mat[z_src]) print output # check if transformation is bigger than 1.5x slice_gap tx = float(output.split()[3]) ty = float(output.split()[7]) norm_txy = linalg.norm([tx, ty], ord=2) if norm_txy > 1.5 * slice_gap: print "WARNING: Transformation is too large --> using previous one." warning_count = warning_count + 1 # if previous transformation exists, replace current one with previous one if os.path.isfile(file_mat[z_dest]): sct.run("cp " + file_mat[z_dest] + " " + file_mat[z_src]) # estimate inverse transformation matrix sct.run("convert_xfm -omat " + file_mat_inv[z_src] + " -inverse " + file_mat[z_src]) # compute cumulative transformation sct.run( "convert_xfm -omat " + file_mat_inv_cumul[z_src] + " -concat " + file_mat_inv[z_src] + " " + file_mat_inv_cumul[z_dest] ) # apply inverse cumulative transformation to initial gaussian mask (to put it in src space) sct.run( fsloutput + "flirt -in " + file_mask_split[z_init] + " -ref " + file_mask_split[z_init] + " -applyxfm -init " + file_mat_inv_cumul[z_src] + " -out " + file_mask_split[z_src] ) # open inverse cumulative transformation file and generate centerline fid = open(file_mat_inv_cumul[z_src]) mat = fid.read().split() x_centerline.append(x_init + float(mat[3])) y_centerline.append(y_init + float(mat[7])) z_centerline.append(z_src) # z_index = z_index+1 # define new z_dest (target slice) and new z_src (moving slice) z_dest = z_dest + slice_gap_signed z_src = z_src + slice_gap_signed # Reconstruct centerline # ==================================================================================================== # reverse back centerline (because it's been reversed once, so now all values are in the right order) x_centerline.reverse() y_centerline.reverse() z_centerline.reverse() # fit centerline in the Z-X plane using polynomial function print "\nFit centerline in the Z-X plane using polynomial function..." coeffsx = polyfit(z_centerline, x_centerline, deg=param.deg_poly) polyx = poly1d(coeffsx) x_centerline_fit = polyval(polyx, z_centerline) # calculate RMSE rmse = linalg.norm(x_centerline_fit - x_centerline) / sqrt(len(x_centerline)) # calculate max absolute error max_abs = max(abs(x_centerline_fit - x_centerline)) print ".. RMSE (in mm): " + str(rmse * px) print ".. Maximum absolute error (in mm): " + str(max_abs * px) # fit centerline in the Z-Y plane using polynomial function print "\nFit centerline in the Z-Y plane using polynomial function..." coeffsy = polyfit(z_centerline, y_centerline, deg=param.deg_poly) polyy = poly1d(coeffsy) y_centerline_fit = polyval(polyy, z_centerline) # calculate RMSE rmse = linalg.norm(y_centerline_fit - y_centerline) / sqrt(len(y_centerline)) # calculate max absolute error max_abs = max(abs(y_centerline_fit - y_centerline)) print ".. RMSE (in mm): " + str(rmse * py) print ".. Maximum absolute error (in mm): " + str(max_abs * py) # display if param.debug == 1: import matplotlib.pyplot as plt plt.figure() plt.plot(z_centerline, x_centerline, ".", z_centerline, x_centerline_fit, "r") plt.legend(["Data", "Polynomial Fit"]) plt.title("Z-X plane polynomial interpolation") plt.show() plt.figure() plt.plot(z_centerline, y_centerline, ".", z_centerline, y_centerline_fit, "r") plt.legend(["Data", "Polynomial Fit"]) plt.title("Z-Y plane polynomial interpolation") plt.show() # generate full range z-values for centerline z_centerline_full = [iz for iz in range(0, nz, 1)] # calculate X and Y values for the full centerline x_centerline_fit_full = polyval(polyx, z_centerline_full) y_centerline_fit_full = polyval(polyy, z_centerline_full) # Generate fitted transformation matrices and write centerline coordinates in text file print "\nGenerate fitted transformation matrices and write centerline coordinates in text file..." file_mat_inv_cumul_fit = ["tmp.mat_inv_cumul_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] file_mat_cumul_fit = ["tmp.mat_cumul_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] fid_centerline = open("tmp.centerline_coordinates.txt", "w") for iz in range(0, nz, 1): # compute inverse cumulative fitted transformation matrix fid = open(file_mat_inv_cumul_fit[iz], "w") fid.write("%i %i %i %f\n" % (1, 0, 0, x_centerline_fit_full[iz] - x_init)) fid.write("%i %i %i %f\n" % (0, 1, 0, y_centerline_fit_full[iz] - y_init)) fid.write("%i %i %i %i\n" % (0, 0, 1, 0)) fid.write("%i %i %i %i\n" % (0, 0, 0, 1)) fid.close() # compute forward cumulative fitted transformation matrix sct.run("convert_xfm -omat " + file_mat_cumul_fit[iz] + " -inverse " + file_mat_inv_cumul_fit[iz]) # write centerline coordinates in x, y, z format fid_centerline.write( "%f %f %f\n" % (x_centerline_fit_full[iz], y_centerline_fit_full[iz], z_centerline_full[iz]) ) fid_centerline.close() # Prepare output data # ==================================================================================================== # write centerline as text file for iz in range(0, nz, 1): # compute inverse cumulative fitted transformation matrix fid = open(file_mat_inv_cumul_fit[iz], "w") fid.write("%i %i %i %f\n" % (1, 0, 0, x_centerline_fit_full[iz] - x_init)) fid.write("%i %i %i %f\n" % (0, 1, 0, y_centerline_fit_full[iz] - y_init)) fid.write("%i %i %i %i\n" % (0, 0, 1, 0)) fid.write("%i %i %i %i\n" % (0, 0, 0, 1)) fid.close() # write polynomial coefficients savetxt("tmp.centerline_polycoeffs_x.txt", coeffsx) savetxt("tmp.centerline_polycoeffs_y.txt", coeffsy) # apply transformations to data print "\nApply fitted transformation matrices..." file_anat_split_fit = ["tmp.anat_orient_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] file_mask_split_fit = ["tmp.mask_orient_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] file_point_split_fit = ["tmp.point_orient_fit_z" + str(z).zfill(4) for z in range(0, nz, 1)] for iz in range(0, nz, 1): # forward cumulative transformation to data sct.run( fsloutput + "flirt -in " + file_anat_split[iz] + " -ref " + file_anat_split[iz] + " -applyxfm -init " + file_mat_cumul_fit[iz] + " -out " + file_anat_split_fit[iz] ) # inverse cumulative transformation to mask sct.run( fsloutput + "flirt -in " + file_mask_split[z_init] + " -ref " + file_mask_split[z_init] + " -applyxfm -init " + file_mat_inv_cumul_fit[iz] + " -out " + file_mask_split_fit[iz] ) # inverse cumulative transformation to point sct.run( fsloutput + "flirt -in " + file_point_split[z_init] + " -ref " + file_point_split[z_init] + " -applyxfm -init " + file_mat_inv_cumul_fit[iz] + " -out " + file_point_split_fit[iz] + " -interp nearestneighbour" ) # Merge into 4D volume print "\nMerge into 4D volume..." # im_anat_list = [Image(fname) for fname in glob.glob('tmp.anat_orient_fit_z*.nii')] fname_anat_list = glob.glob("tmp.anat_orient_fit_z*.nii") im_anat_concat = concat_data(fname_anat_list, 2) im_anat_concat.setFileName("tmp.anat_orient_fit.nii") im_anat_concat.save() # im_mask_list = [Image(fname) for fname in glob.glob('tmp.mask_orient_fit_z*.nii')] fname_mask_list = glob.glob("tmp.mask_orient_fit_z*.nii") im_mask_concat = concat_data(fname_mask_list, 2) im_mask_concat.setFileName("tmp.mask_orient_fit.nii") im_mask_concat.save() # im_point_list = [Image(fname) for fname in glob.glob('tmp.point_orient_fit_z*.nii')] fname_point_list = glob.glob("tmp.point_orient_fit_z*.nii") im_point_concat = concat_data(fname_point_list, 2) im_point_concat.setFileName("tmp.point_orient_fit.nii") im_point_concat.save() # Copy header geometry from input data print "\nCopy header geometry from input data..." im_anat = Image("tmp.anat_orient.nii") im_anat_orient_fit = Image("tmp.anat_orient_fit.nii") im_mask_orient_fit = Image("tmp.mask_orient_fit.nii") im_point_orient_fit = Image("tmp.point_orient_fit.nii") im_anat_orient_fit = copy_header(im_anat, im_anat_orient_fit) im_mask_orient_fit = copy_header(im_anat, im_mask_orient_fit) im_point_orient_fit = copy_header(im_anat, im_point_orient_fit) for im in [im_anat_orient_fit, im_mask_orient_fit, im_point_orient_fit]: im.save() # Reorient outputs into the initial orientation of the input image print "\nReorient the centerline into the initial orientation of the input image..." set_orientation("tmp.point_orient_fit.nii", input_image_orientation, "tmp.point_orient_fit.nii") set_orientation("tmp.mask_orient_fit.nii", input_image_orientation, "tmp.mask_orient_fit.nii") # Generate output file (in current folder) print "\nGenerate output file (in current folder)..." os.chdir("..") # come back to parent folder fname_output_centerline = sct.generate_output_file( path_tmp + "/tmp.point_orient_fit.nii", file_anat + "_centerline" + ext_anat ) # Delete temporary files if remove_tmp_files == 1: print "\nRemove temporary files..." sct.run("rm -rf " + path_tmp, error_exit="warning") # print number of warnings print "\nNumber of warnings: " + str( warning_count ) + " (if >10, you should probably reduce the gap and/or increase the kernel size" # display elapsed time elapsed_time = time() - start_time print "\nFinished! \n\tGenerated file: " + fname_output_centerline + "\n\tElapsed time: " + str( int(round(elapsed_time)) ) + "s\n"
def get_centerline_from_labels( fname_in, list_fname_labels, param, output_file_name=None, remove_temp_files=1, verbose=0 ): path, file, ext = sct.extract_fname(fname_in) # create temporary folder path_tmp = sct.slash_at_the_end("tmp." + strftime("%y%m%d%H%M%S"), 1) sct.run("mkdir " + path_tmp) # Copying input data to tmp folder sct.printv("\nCopying input data to tmp folder...", verbose) sct.run("sct_convert -i " + fname_in + " -o " + path_tmp + "data.nii") file_labels = [] for i in range(len(list_fname_labels)): file_labels.append("labels_" + str(i) + ".nii.gz") sct.run("sct_convert -i " + list_fname_labels[i] + " -o " + path_tmp + file_labels[i]) # go to tmp folder os.chdir(path_tmp) ## Concatenation of the files # Concatenation : sum of matrices file_0 = Image("data.nii") data_concatenation = file_0.data hdr_0 = file_0.hdr orientation_file_0 = get_orientation_3d(file_0) if len(list_fname_labels) > 0: for i in range(0, len(list_fname_labels)): orientation_file_temp = get_orientation_3d(file_labels[i], filename=True) if orientation_file_0 != orientation_file_temp: print "ERROR: The files ", fname_in, " and ", file_labels[ i ], " are not in the same orientation. Use sct_image -setorient to change the orientation of a file." sys.exit(2) file_temp = load(file_labels[i]) data_temp = file_temp.get_data() data_concatenation = data_concatenation + data_temp # Save concatenation as a file print "\nWrite NIFTI volumes..." img = Nifti1Image(data_concatenation, None, hdr_0) save(img, "concatenation_file.nii.gz") # Applying nurbs to the concatenation and save file as binary file fname_output = extract_centerline( "concatenation_file.nii.gz", remove_temp_files=remove_temp_files, verbose=verbose, algo_fitting=param.algo_fitting, type_window=param.type_window, window_length=param.window_length, ) # Rename files after processing if output_file_name != None: output_file_name = output_file_name else: output_file_name = "generated_centerline.nii.gz" os.rename(fname_output, output_file_name) path_binary, file_binary, ext_binary = sct.extract_fname(output_file_name) os.rename("concatenation_file_centerline.txt", file_binary + ".txt") # Process for a binary file as output: sct.run("cp " + output_file_name + " ../") # Process for a text file as output: sct.run("cp " + file_binary + ".txt" + " ../") os.chdir("../") # Remove temporary files if remove_temp_files: print ("\nRemove temporary files...") sct.run("rm -rf " + path_tmp, error_exit="warning")
def main(): # initialization fname_mask = '' # Get parser info parser = get_parser() arguments = parser.parse(sys.argv[1:]) fname_data = arguments['-i'] fname_mask = arguments['-m'] vert_label_fname = arguments["-vertfile"] vert_levels = arguments["-vert"] slices_of_interest = arguments["-z"] method = arguments["-method"] verbose = int(arguments['-v']) # Check if data are in RPI input_im = Image(fname_data) input_orient = get_orientation_3d(input_im) # If orientation is not RPI, change to RPI if input_orient != 'RPI': sct.printv('\nCreate temporary folder to change the orientation of the NIFTI files into RPI...', verbose) path_tmp = sct.tmp_create() # change orientation and load data sct.printv('\nChange input image orientation and load it...', verbose) input_im_rpi = set_orientation(input_im, 'RPI', fname_out=path_tmp+'input_RPI.nii') input_data = input_im_rpi.data # Do the same for the mask sct.printv('\nChange mask orientation and load it...', verbose) mask_im_rpi = set_orientation(Image(fname_mask), 'RPI', fname_out=path_tmp+'mask_RPI.nii') mask_data = mask_im_rpi.data # Do the same for vertebral labeling if present if vert_levels != 'None': sct.printv('\nChange vertebral labeling file orientation and load it...', verbose) vert_label_im_rpi = set_orientation(Image(vert_label_fname), 'RPI', fname_out=path_tmp+'vert_labeling_RPI.nii') vert_labeling_data = vert_label_im_rpi.data # Remove the temporary folder used to change the NIFTI files orientation into RPI sct.printv('\nRemove the temporary folder...', verbose) rmdir(path_tmp) else: # Load data sct.printv('\nLoad data...', verbose) input_data = input_im.data mask_data = Image(fname_mask).data if vert_levels != 'None': vert_labeling_data = Image(vert_label_fname).data sct.printv('\tDone.', verbose) # Get slices corresponding to vertebral levels if vert_levels != 'None': from sct_extract_metric import get_slices_matching_with_vertebral_levels slices_of_interest, actual_vert_levels, warning_vert_levels = get_slices_matching_with_vertebral_levels(mask_data, vert_levels, vert_labeling_data, verbose) # Remove slices that were not selected if slices_of_interest == 'None': slices_of_interest = '0:'+str(mask_data.shape[2]-1) slices_boundary = slices_of_interest.split(':') slices_of_interest_list = range(int(slices_boundary[0]), int(slices_boundary[1])+1) # Crop input_data = input_data[:, :, slices_of_interest_list, :] mask_data = mask_data[:, :, slices_of_interest_list] # Get signal and noise indexes_roi = np.where(mask_data == 1) if method == 'mult': signal = np.mean(input_data[indexes_roi]) std_input_temporal = np.std(input_data, 3) noise = np.mean(std_input_temporal[indexes_roi]) elif method == 'diff': data_1 = input_data[:, :, :, 0] data_2 = input_data[:, :, :, 1] signal = np.mean(np.add(b0_1[indexes_roi], b0_2[indexes_roi])) noise = np.sqrt(2)*np.std(np.subtract(b0_1[indexes_roi], b0_2[indexes_roi])) elif method == 'background': sct.printv('ERROR: Sorry, method is not implemented yet.', 1, 'error') elif method == 'nema': sct.printv('ERROR: Sorry, method is not implemented yet.', 1, 'error') # compute SNR SNR = signal/noise # Display result sct.printv('\nSNR_'+method+' = '+str(SNR)+'\n', type='info')
def main(fname_anat, fname_centerline, degree_poly, centerline_fitting, interp, remove_temp_files, verbose): # extract path of the script path_script = os.path.dirname(__file__) + '/' # Parameters for debug mode if param.debug == 1: print '\n*** WARNING: DEBUG MODE ON ***\n' status, path_sct_data = commands.getstatusoutput( 'echo $SCT_TESTING_DATA_DIR') fname_anat = path_sct_data + '/t2/t2.nii.gz' fname_centerline = path_sct_data + '/t2/t2_seg.nii.gz' # extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) # Display arguments print '\nCheck input arguments...' print ' Input volume ...................... ' + fname_anat print ' Centerline ........................ ' + fname_centerline print '' # Get input image orientation im_anat = Image(fname_anat) input_image_orientation = get_orientation_3d(im_anat) # Reorient input data into RL PA IS orientation im_centerline = Image(fname_centerline) im_anat_orient = set_orientation(im_anat, 'RPI') im_anat_orient.setFileName('tmp.anat_orient.nii') im_centerline_orient = set_orientation(im_centerline, 'RPI') im_centerline_orient.setFileName('tmp.centerline_orient.nii') # Open centerline #========================================================================================== print '\nGet dimensions of input centerline...' nx, ny, nz, nt, px, py, pz, pt = im_centerline_orient.dim print '.. matrix size: ' + str(nx) + ' x ' + str(ny) + ' x ' + str(nz) print '.. voxel size: ' + str(px) + 'mm x ' + str(py) + 'mm x ' + str( pz) + 'mm' print '\nOpen centerline volume...' data = im_centerline_orient.data X, Y, Z = (data > 0).nonzero() min_z_index, max_z_index = min(Z), max(Z) # loop across z and associate x,y coordinate with the point having maximum intensity x_centerline = [0 for iz in range(min_z_index, max_z_index + 1, 1)] y_centerline = [0 for iz in range(min_z_index, max_z_index + 1, 1)] z_centerline = [iz for iz in range(min_z_index, max_z_index + 1, 1)] # Two possible scenario: # 1. the centerline is probabilistic: each slices contains voxels with the probability of containing the centerline [0:...:1] # We only take the maximum value of the image to aproximate the centerline. # 2. The centerline/segmentation image contains many pixels per slice with values {0,1}. # We take all the points and approximate the centerline on all these points. X, Y, Z = ((data < 1) * (data > 0)).nonzero() # X is empty if binary image if (len(X) > 0): # Scenario 1 for iz in range(min_z_index, max_z_index + 1, 1): x_centerline[iz - min_z_index], y_centerline[ iz - min_z_index] = numpy.unravel_index( data[:, :, iz].argmax(), data[:, :, iz].shape) else: # Scenario 2 for iz in range(min_z_index, max_z_index + 1, 1): x_seg, y_seg = (data[:, :, iz] > 0).nonzero() if len(x_seg) > 0: x_centerline[iz - min_z_index] = numpy.mean(x_seg) y_centerline[iz - min_z_index] = numpy.mean(y_seg) # TODO: find a way to do the previous loop with this, which is more neat: # [numpy.unravel_index(data[:,:,iz].argmax(), data[:,:,iz].shape) for iz in range(0,nz,1)] # clear variable del data # Fit the centerline points with the kind of curve given as argument of the script and return the new smoothed coordinates if centerline_fitting == 'nurbs': try: x_centerline_fit, y_centerline_fit = b_spline_centerline( x_centerline, y_centerline, z_centerline) except ValueError: print "splines fitting doesn't work, trying with polynomial fitting...\n" x_centerline_fit, y_centerline_fit = polynome_centerline( x_centerline, y_centerline, z_centerline) elif centerline_fitting == 'polynome': x_centerline_fit, y_centerline_fit = polynome_centerline( x_centerline, y_centerline, z_centerline) #========================================================================================== # Split input volume print '\nSplit input volume...' im_anat_orient_split_list = split_data(im_anat_orient, 2) file_anat_split = [] for im in im_anat_orient_split_list: file_anat_split.append(im.absolutepath) im.save() # initialize variables file_mat_inv_cumul = [ 'tmp.mat_inv_cumul_Z' + str(z).zfill(4) for z in range(0, nz, 1) ] z_init = min_z_index displacement_max_z_index = x_centerline_fit[ z_init - min_z_index] - x_centerline_fit[max_z_index - min_z_index] # write centerline as text file print '\nGenerate fitted transformation matrices...' file_mat_inv_cumul_fit = [ 'tmp.mat_inv_cumul_fit_Z' + str(z).zfill(4) for z in range(0, nz, 1) ] for iz in range(min_z_index, max_z_index + 1, 1): # compute inverse cumulative fitted transformation matrix fid = open(file_mat_inv_cumul_fit[iz], 'w') if (x_centerline[iz - min_z_index] == 0 and y_centerline[iz - min_z_index] == 0): displacement = 0 else: displacement = x_centerline_fit[ z_init - min_z_index] - x_centerline_fit[iz - min_z_index] fid.write('%i %i %i %f\n' % (1, 0, 0, displacement)) fid.write('%i %i %i %f\n' % (0, 1, 0, 0)) fid.write('%i %i %i %i\n' % (0, 0, 1, 0)) fid.write('%i %i %i %i\n' % (0, 0, 0, 1)) fid.close() # we complete the displacement matrix in z direction for iz in range(0, min_z_index, 1): fid = open(file_mat_inv_cumul_fit[iz], 'w') fid.write('%i %i %i %f\n' % (1, 0, 0, 0)) fid.write('%i %i %i %f\n' % (0, 1, 0, 0)) fid.write('%i %i %i %i\n' % (0, 0, 1, 0)) fid.write('%i %i %i %i\n' % (0, 0, 0, 1)) fid.close() for iz in range(max_z_index + 1, nz, 1): fid = open(file_mat_inv_cumul_fit[iz], 'w') fid.write('%i %i %i %f\n' % (1, 0, 0, displacement_max_z_index)) fid.write('%i %i %i %f\n' % (0, 1, 0, 0)) fid.write('%i %i %i %i\n' % (0, 0, 1, 0)) fid.write('%i %i %i %i\n' % (0, 0, 0, 1)) fid.close() # apply transformations to data print '\nApply fitted transformation matrices...' file_anat_split_fit = [ 'tmp.anat_orient_fit_Z' + str(z).zfill(4) for z in range(0, nz, 1) ] for iz in range(0, nz, 1): # forward cumulative transformation to data sct.run(fsloutput + 'flirt -in ' + file_anat_split[iz] + ' -ref ' + file_anat_split[iz] + ' -applyxfm -init ' + file_mat_inv_cumul_fit[iz] + ' -out ' + file_anat_split_fit[iz] + ' -interp ' + interp) # Merge into 4D volume print '\nMerge into 4D volume...' from glob import glob im_to_concat_list = [ Image(fname) for fname in glob('tmp.anat_orient_fit_Z*.nii') ] im_concat_out = concat_data(im_to_concat_list, 2) im_concat_out.setFileName('tmp.anat_orient_fit.nii') im_concat_out.save() # sct.run(fsloutput+'fslmerge -z tmp.anat_orient_fit tmp.anat_orient_fit_z*') # Reorient data as it was before print '\nReorient data back into native orientation...' fname_anat_fit_orient = set_orientation(im_concat_out.absolutepath, input_image_orientation, filename=True) move(fname_anat_fit_orient, 'tmp.anat_orient_fit_reorient.nii') # Generate output file (in current folder) print '\nGenerate output file (in current folder)...' sct.generate_output_file('tmp.anat_orient_fit_reorient.nii', file_anat + '_flatten' + ext_anat) # Delete temporary files if remove_temp_files == 1: print '\nDelete temporary files...' sct.run('rm -rf tmp.*') # to view results print '\nDone! To view results, type:' print 'fslview ' + file_anat + ext_anat + ' ' + file_anat + '_flatten' + ext_anat + ' &\n'
def check_if_rpi(fname): from sct_image import get_orientation_3d if not get_orientation_3d(fname, filename=True) == 'RPI': printv('\nERROR: '+fname+' is not in RPI orientation. Use sct_image -setorient to reorient your data. Exit program.\n', 1, 'error')
def main(fname_anat, fname_centerline, degree_poly, centerline_fitting, interp, remove_temp_files, verbose): # extract path of the script path_script = os.path.dirname(__file__)+'/' # Parameters for debug mode if param.debug == 1: print '\n*** WARNING: DEBUG MODE ON ***\n' status, path_sct_data = commands.getstatusoutput('echo $SCT_TESTING_DATA_DIR') fname_anat = path_sct_data+'/t2/t2.nii.gz' fname_centerline = path_sct_data+'/t2/t2_seg.nii.gz' # extract path/file/extension path_anat, file_anat, ext_anat = sct.extract_fname(fname_anat) # Display arguments print '\nCheck input arguments...' print ' Input volume ...................... '+fname_anat print ' Centerline ........................ '+fname_centerline print '' # Get input image orientation im_anat = Image(fname_anat) input_image_orientation = get_orientation_3d(im_anat) # Reorient input data into RL PA IS orientation im_centerline = Image(fname_centerline) im_anat_orient = set_orientation(im_anat, 'RPI') im_anat_orient.setFileName('tmp.anat_orient.nii') im_centerline_orient = set_orientation(im_centerline, 'RPI') im_centerline_orient.setFileName('tmp.centerline_orient.nii') # Open centerline #========================================================================================== print '\nGet dimensions of input centerline...' nx, ny, nz, nt, px, py, pz, pt = im_centerline_orient.dim print '.. matrix size: '+str(nx)+' x '+str(ny)+' x '+str(nz) print '.. voxel size: '+str(px)+'mm x '+str(py)+'mm x '+str(pz)+'mm' print '\nOpen centerline volume...' data = im_centerline_orient.data X, Y, Z = (data>0).nonzero() min_z_index, max_z_index = min(Z), max(Z) # loop across z and associate x,y coordinate with the point having maximum intensity x_centerline = [0 for iz in range(min_z_index, max_z_index+1, 1)] y_centerline = [0 for iz in range(min_z_index, max_z_index+1, 1)] z_centerline = [iz for iz in range(min_z_index, max_z_index+1, 1)] # Two possible scenario: # 1. the centerline is probabilistic: each slices contains voxels with the probability of containing the centerline [0:...:1] # We only take the maximum value of the image to aproximate the centerline. # 2. The centerline/segmentation image contains many pixels per slice with values {0,1}. # We take all the points and approximate the centerline on all these points. X, Y, Z = ((data<1)*(data>0)).nonzero() # X is empty if binary image if (len(X) > 0): # Scenario 1 for iz in range(min_z_index, max_z_index+1, 1): x_centerline[iz-min_z_index], y_centerline[iz-min_z_index] = numpy.unravel_index(data[:,:,iz].argmax(), data[:,:,iz].shape) else: # Scenario 2 for iz in range(min_z_index, max_z_index+1, 1): x_seg, y_seg = (data[:,:,iz]>0).nonzero() if len(x_seg) > 0: x_centerline[iz-min_z_index] = numpy.mean(x_seg) y_centerline[iz-min_z_index] = numpy.mean(y_seg) # TODO: find a way to do the previous loop with this, which is more neat: # [numpy.unravel_index(data[:,:,iz].argmax(), data[:,:,iz].shape) for iz in range(0,nz,1)] # clear variable del data # Fit the centerline points with the kind of curve given as argument of the script and return the new smoothed coordinates if centerline_fitting == 'nurbs': try: x_centerline_fit, y_centerline_fit = b_spline_centerline(x_centerline,y_centerline,z_centerline) except ValueError: print "splines fitting doesn't work, trying with polynomial fitting...\n" x_centerline_fit, y_centerline_fit = polynome_centerline(x_centerline,y_centerline,z_centerline) elif centerline_fitting == 'polynome': x_centerline_fit, y_centerline_fit = polynome_centerline(x_centerline,y_centerline,z_centerline) #========================================================================================== # Split input volume print '\nSplit input volume...' im_anat_orient_split_list = split_data(im_anat_orient, 2) file_anat_split = [] for im in im_anat_orient_split_list: file_anat_split.append(im.absolutepath) im.save() # initialize variables file_mat_inv_cumul = ['tmp.mat_inv_cumul_Z'+str(z).zfill(4) for z in range(0,nz,1)] z_init = min_z_index displacement_max_z_index = x_centerline_fit[z_init-min_z_index]-x_centerline_fit[max_z_index-min_z_index] # write centerline as text file print '\nGenerate fitted transformation matrices...' file_mat_inv_cumul_fit = ['tmp.mat_inv_cumul_fit_Z'+str(z).zfill(4) for z in range(0,nz,1)] for iz in range(min_z_index, max_z_index+1, 1): # compute inverse cumulative fitted transformation matrix fid = open(file_mat_inv_cumul_fit[iz], 'w') if (x_centerline[iz-min_z_index] == 0 and y_centerline[iz-min_z_index] == 0): displacement = 0 else: displacement = x_centerline_fit[z_init-min_z_index]-x_centerline_fit[iz-min_z_index] fid.write('%i %i %i %f\n' %(1, 0, 0, displacement) ) fid.write('%i %i %i %f\n' %(0, 1, 0, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 1, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 0, 1) ) fid.close() # we complete the displacement matrix in z direction for iz in range(0, min_z_index, 1): fid = open(file_mat_inv_cumul_fit[iz], 'w') fid.write('%i %i %i %f\n' %(1, 0, 0, 0) ) fid.write('%i %i %i %f\n' %(0, 1, 0, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 1, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 0, 1) ) fid.close() for iz in range(max_z_index+1, nz, 1): fid = open(file_mat_inv_cumul_fit[iz], 'w') fid.write('%i %i %i %f\n' %(1, 0, 0, displacement_max_z_index) ) fid.write('%i %i %i %f\n' %(0, 1, 0, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 1, 0) ) fid.write('%i %i %i %i\n' %(0, 0, 0, 1) ) fid.close() # apply transformations to data print '\nApply fitted transformation matrices...' file_anat_split_fit = ['tmp.anat_orient_fit_Z'+str(z).zfill(4) for z in range(0,nz,1)] for iz in range(0, nz, 1): # forward cumulative transformation to data sct.run(fsloutput+'flirt -in '+file_anat_split[iz]+' -ref '+file_anat_split[iz]+' -applyxfm -init '+file_mat_inv_cumul_fit[iz]+' -out '+file_anat_split_fit[iz]+' -interp '+interp) # Merge into 4D volume print '\nMerge into 4D volume...' from glob import glob im_to_concat_list = [Image(fname) for fname in glob('tmp.anat_orient_fit_Z*.nii')] im_concat_out = concat_data(im_to_concat_list, 2) im_concat_out.setFileName('tmp.anat_orient_fit.nii') im_concat_out.save() # sct.run(fsloutput+'fslmerge -z tmp.anat_orient_fit tmp.anat_orient_fit_z*') # Reorient data as it was before print '\nReorient data back into native orientation...' fname_anat_fit_orient = set_orientation(im_concat_out.absolutepath, input_image_orientation, filename=True) move(fname_anat_fit_orient, 'tmp.anat_orient_fit_reorient.nii') # Generate output file (in current folder) print '\nGenerate output file (in current folder)...' sct.generate_output_file('tmp.anat_orient_fit_reorient.nii', file_anat+'_flatten'+ext_anat) # Delete temporary files if remove_temp_files == 1: print '\nDelete temporary files...' sct.run('rm -rf tmp.*') # to view results print '\nDone! To view results, type:' print 'fslview '+file_anat+ext_anat+' '+file_anat+'_flatten'+ext_anat+' &\n'