def main(): time_start = ph.start_timing() # Set print options for numpy np.set_printoptions(precision=3) # Read input input_parser = InputArgparser( description="Script to study reconstruction parameters and their " "impact on the volumetric reconstruction quality. " "This script can only be used to sweep through one single parameter, " "e.g. the regularization parameter 'alpha'. ") input_parser.add_filenames(required=True) input_parser.add_filenames_masks() input_parser.add_suffix_mask(default="_mask") input_parser.add_dir_input_mc() input_parser.add_dir_output(required=True) input_parser.add_reconstruction_space() input_parser.add_reference( help="Path to reference NIfTI image file. If given the volumetric " "reconstructed is performed in this physical space. " "Either a reconstruction space or a reference must be provided", required=False) input_parser.add_reference_mask(default=None) input_parser.add_study_name() input_parser.add_reconstruction_type(default="TK1L2") input_parser.add_measures( default=["PSNR", "MAE", "RMSE", "SSIM", "NCC", "NMI"]) input_parser.add_tv_solver(default="PD") input_parser.add_iterations(default=50) input_parser.add_rho(default=0.1) input_parser.add_iter_max(default=10) input_parser.add_minimizer(default="lsmr") input_parser.add_log_config(default=1) input_parser.add_use_masks_srr(default=0) input_parser.add_verbose(default=1) input_parser.add_slice_thicknesses(default=None) input_parser.add_argument( "--append", "-append", action='store_true', help="If given, results are appended to previously executed parameter " "study with identical parameters and study name store in the output " "directory.") # Range for parameter sweeps input_parser.add_alphas(default=list(np.linspace(0.01, 0.5, 5))) input_parser.add_data_losses(default=["linear"] # default=["linear", "arctan"] ) input_parser.add_data_loss_scales(default=[1] # default=[0.1, 0.5, 1.5] ) args = input_parser.parse_args() input_parser.print_arguments(args) if args.reference is None and args.reconstruction_space is None: raise IOError("Either reference (--reference) or reconstruction space " "(--reconstruction-space) must be provided.") if args.log_config: input_parser.log_config(os.path.abspath(__file__)) # --------------------------------Read Data-------------------------------- ph.print_title("Read Data") data_reader = dr.MultipleImagesReader( file_paths=args.filenames, file_paths_masks=args.filenames_masks, suffix_mask=args.suffix_mask, dir_motion_correction=args.dir_input_mc, stacks_slice_thicknesses=args.slice_thicknesses, ) data_reader.read_data() stacks = data_reader.get_data() ph.print_info("%d input stacks read for further processing" % len(stacks)) if args.reference is not None: reference = st.Stack.from_filename(file_path=args.reference, file_path_mask=args.reference_mask, extract_slices=False) reconstruction_space = stacks[0].get_resampled_stack(reference.sitk) reconstruction_space = \ reconstruction_space.get_stack_multiplied_with_mask() x_ref = sitk.GetArrayFromImage(reference.sitk).flatten() x_ref_mask = sitk.GetArrayFromImage(reference.sitk_mask).flatten() else: reconstruction_space = st.Stack.from_filename( file_path=args.reconstruction_space, extract_slices=False) reconstruction_space = stacks[0].get_resampled_stack( reconstruction_space.sitk) reconstruction_space = \ reconstruction_space.get_stack_multiplied_with_mask() x_ref = None x_ref_mask = None # ----------------------------Set Up Parameters---------------------------- parameters = {} parameters["alpha"] = args.alphas if len(args.data_losses) > 1: parameters["data_loss"] = args.data_losses if len(args.data_loss_scales) > 1: parameters["data_loss_scale"] = args.data_loss_scales # --------------------------Set Up Parameter Study------------------------- ph.print_title("Run Parameter Study") if args.study_name is None: name = args.reconstruction_type else: name = args.study_name reconstruction_info = { "shape": reconstruction_space.sitk.GetSize()[::-1], "origin": reconstruction_space.sitk.GetOrigin(), "spacing": reconstruction_space.sitk.GetSpacing(), "direction": reconstruction_space.sitk.GetDirection(), } # Create Tikhonov solver from which all information can be extracted # (also for other reconstruction types) tmp = tk.TikhonovSolver( stacks=stacks, reconstruction=reconstruction_space, alpha=args.alphas[0], iter_max=args.iter_max, data_loss=args.data_losses[0], data_loss_scale=args.data_loss_scales[0], reg_type="TK1", minimizer=args.minimizer, verbose=args.verbose, use_masks=args.use_masks_srr, ) solver = tmp.get_solver() parameter_study_interface = \ deconv_interface.DeconvolutionParameterStudyInterface( A=solver.get_A(), A_adj=solver.get_A_adj(), D=solver.get_B(), D_adj=solver.get_B_adj(), b=solver.get_b(), x0=solver.get_x0(), alpha=solver.get_alpha(), x_scale=solver.get_x_scale(), data_loss=solver.get_data_loss(), data_loss_scale=solver.get_data_loss_scale(), iter_max=solver.get_iter_max(), minimizer=solver.get_minimizer(), iterations=args.iterations, measures=args.measures, dimension=3, L2=16. / reconstruction_space.sitk.GetSpacing()[0]**2, reconstruction_type=args.reconstruction_type, rho=args.rho, dir_output=args.dir_output, parameters=parameters, name=name, reconstruction_info=reconstruction_info, x_ref=x_ref, x_ref_mask=x_ref_mask, tv_solver=args.tv_solver, verbose=args.verbose, append=args.append, ) parameter_study_interface.set_up_parameter_study() parameter_study = parameter_study_interface.get_parameter_study() # Run parameter study parameter_study.run() print("\nComputational time for Deconvolution Parameter Study %s: %s" % (name, parameter_study.get_computational_time())) return 0
def main(): # Set print options np.set_printoptions(precision=3) pd.set_option('display.width', 1000) input_parser = InputArgparser(description=".", ) input_parser.add_filenames(required=True) input_parser.add_reference(required=True) input_parser.add_reference_mask() input_parser.add_dir_output(required=False) input_parser.add_measures( default=["PSNR", "RMSE", "MAE", "SSIM", "NCC", "NMI"]) input_parser.add_verbose(default=0) args = input_parser.parse_args() input_parser.print_arguments(args) ph.print_title("Image similarity") data_reader = dr.MultipleImagesReader(args.filenames) data_reader.read_data() stacks = data_reader.get_data() reference = st.Stack.from_filename(args.reference, args.reference_mask) for stack in stacks: try: stack.sitk - reference.sitk except RuntimeError as e: raise IOError( "All provided images must be at the same image space") x_ref = sitk.GetArrayFromImage(reference.sitk) if args.reference_mask is None: indices = np.where(x_ref != np.inf) else: x_ref_mask = sitk.GetArrayFromImage(reference.sitk_mask) indices = np.where(x_ref_mask > 0) measures_dic = { m: lambda x, m=m: SimilarityMeasures.similarity_measures[m] (x[indices], x_ref[indices]) # SimilarityMeasures.similarity_measures[m](x, x_ref) for m in args.measures } observer = obs.Observer() observer.set_measures(measures_dic) for stack in stacks: nda = sitk.GetArrayFromImage(stack.sitk) observer.add_x(nda) if args.verbose: stacks_comparison = [s for s in stacks] stacks_comparison.insert(0, reference) sitkh.show_stacks( stacks_comparison, segmentation=reference, ) observer.compute_measures() measures = observer.get_measures() # Store information in array error = np.zeros((len(stacks), len(measures))) cols = measures rows = [] for i_stack, stack in enumerate(stacks): error[i_stack, :] = np.array([measures[m][i_stack] for m in measures]) rows.append(stack.get_filename()) header = "# Ref: %s, Ref-Mask: %d, %s \n" % ( reference.get_filename(), args.reference_mask is None, ph.get_time_stamp(), ) header += "# %s\n" % ("\t").join(measures) path_to_file_filenames = os.path.join(args.dir_output, "filenames.txt") path_to_file_similarities = os.path.join(args.dir_output, "similarities.txt") # Write to files ph.write_to_file(path_to_file_similarities, header) ph.write_array_to_file(path_to_file_similarities, error, verbose=False) text = header text += "%s\n" % "\n".join(rows) ph.write_to_file(path_to_file_filenames, text) # Print to screen ph.print_subtitle("Computed Similarities") df = pd.DataFrame(error, rows, cols) print(df) return 0
def main(): time_start = ph.start_timing() # Set print options for numpy np.set_printoptions(precision=3) # Read input input_parser = InputArgparser( description="Script to study reconstruction parameters and their " "impact on the volumetric reconstruction quality.", ) input_parser.add_dir_input() input_parser.add_filenames() input_parser.add_image_selection() input_parser.add_dir_output(required=True) input_parser.add_suffix_mask(default="_mask") input_parser.add_reconstruction_space() input_parser.add_reference( help="Path to reference NIfTI image file. If given the volumetric " "reconstructed is performed in this physical space. " "Either a reconstruction space or a reference must be provided", required=False) input_parser.add_reference_mask(default=None) input_parser.add_study_name() input_parser.add_reconstruction_type(default="TK1L2") input_parser.add_measures(default=["PSNR", "RMSE", "SSIM", "NCC", "NMI"]) input_parser.add_tv_solver(default="PD") input_parser.add_iterations(default=50) input_parser.add_rho(default=0.1) input_parser.add_iter_max(default=10) input_parser.add_minimizer(default="lsmr") input_parser.add_alpha(default=0.01) input_parser.add_data_loss(default="linear") input_parser.add_data_loss_scale(default=1) input_parser.add_log_script_execution(default=1) input_parser.add_verbose(default=1) # Range for parameter sweeps input_parser.add_alpha_range(default=[0.001, 0.05, 20]) # TK1L2 # input_parser.add_alpha_range(default=[0.001, 0.003, 10]) # TVL2, HuberL2 input_parser.add_data_losses( # default=["linear", "arctan"] ) input_parser.add_data_loss_scale_range( # default=[0.1, 1.5, 2] ) args = input_parser.parse_args() input_parser.print_arguments(args) if args.reference is None and args.reconstruction_space is None: raise IOError("Either reference (--reference) or reconstruction space " "(--reconstruction-space) must be provided.") # Write script execution call if args.log_script_execution: input_parser.write_performed_script_execution( os.path.abspath(__file__)) # --------------------------------Read Data-------------------------------- ph.print_title("Read Data") # Neither '--dir-input' nor '--filenames' was specified if args.filenames is not None and args.dir_input is not None: raise IOError( "Provide input by either '--dir-input' or '--filenames' " "but not both together") # '--dir-input' specified elif args.dir_input is not None: data_reader = dr.ImageSlicesDirectoryReader( path_to_directory=args.dir_input, suffix_mask=args.suffix_mask, image_selection=args.image_selection) # '--filenames' specified elif args.filenames is not None: data_reader = dr.MultipleImagesReader( args.filenames, suffix_mask=args.suffix_mask) else: raise IOError( "Provide input by either '--dir-input' or '--filenames'") data_reader.read_data() stacks = data_reader.get_data() ph.print_info("%d input stacks read for further processing" % len(stacks)) if args.reference is not None: reference = st.Stack.from_filename( file_path=args.reference, file_path_mask=args.reference_mask, extract_slices=False) reconstruction_space = stacks[0].get_resampled_stack(reference.sitk) reconstruction_space = \ reconstruction_space.get_stack_multiplied_with_mask() x_ref = sitk.GetArrayFromImage(reference.sitk).flatten() x_ref_mask = sitk.GetArrayFromImage(reference.sitk_mask).flatten() else: reconstruction_space = st.Stack.from_filename( file_path=args.reconstruction_space, extract_slices=False) reconstruction_space = stacks[0].get_resampled_stack( reconstruction_space.sitk) reconstruction_space = \ reconstruction_space.get_stack_multiplied_with_mask() x_ref = None x_ref_mask = None # ----------------------------Set Up Parameters---------------------------- parameters = {} parameters["alpha"] = np.linspace( args.alpha_range[0], args.alpha_range[1], int(args.alpha_range[2])) if args.data_losses is not None: parameters["data_loss"] = args.data_losses if args.data_loss_scale_range is not None: parameters["data_loss_scale"] = np.linspace( args.data_loss_scale_range[0], args.data_loss_scale_range[1], int(args.data_loss_scale_range[2])) # --------------------------Set Up Parameter Study------------------------- if args.study_name is None: name = args.reconstruction_type else: name = args.study_name reconstruction_info = { "shape": reconstruction_space.sitk.GetSize()[::-1], "origin": reconstruction_space.sitk.GetOrigin(), "spacing": reconstruction_space.sitk.GetSpacing(), "direction": reconstruction_space.sitk.GetDirection(), } # Create Tikhonov solver from which all information can be extracted # (also for other reconstruction types) tmp = tk.TikhonovSolver( stacks=stacks, reconstruction=reconstruction_space, alpha=args.alpha, iter_max=args.iter_max, data_loss=args.data_loss, data_loss_scale=args.data_loss_scale, reg_type="TK1", minimizer=args.minimizer, verbose=args.verbose, ) solver = tmp.get_solver() parameter_study_interface = \ deconv_interface.DeconvolutionParameterStudyInterface( A=solver.get_A(), A_adj=solver.get_A_adj(), D=solver.get_B(), D_adj=solver.get_B_adj(), b=solver.get_b(), x0=solver.get_x0(), alpha=solver.get_alpha(), x_scale=solver.get_x_scale(), data_loss=solver.get_data_loss(), data_loss_scale=solver.get_data_loss_scale(), iter_max=solver.get_iter_max(), minimizer=solver.get_minimizer(), iterations=args.iterations, measures=args.measures, dimension=3, L2=16./reconstruction_space.sitk.GetSpacing()[0]**2, reconstruction_type=args.reconstruction_type, rho=args.rho, dir_output=args.dir_output, parameters=parameters, name=name, reconstruction_info=reconstruction_info, x_ref=x_ref, x_ref_mask=x_ref_mask, tv_solver=args.tv_solver, verbose=args.verbose, ) parameter_study_interface.set_up_parameter_study() parameter_study = parameter_study_interface.get_parameter_study() # Run parameter study parameter_study.run() print("\nComputational time for Deconvolution Parameter Study %s: %s" % (name, parameter_study.get_computational_time())) return 0
def main(): # Read input input_parser = InputArgparser( description="Script to evaluate the similarity of simulated stack " "from obtained reconstruction against the original stack. " "This function takes the result of " "simulate_stacks_from_reconstruction.py as input.", ) input_parser.add_filenames(required=True) input_parser.add_filenames_masks() input_parser.add_dir_output(required=True) input_parser.add_suffix_mask(default="_mask") input_parser.add_measures(default=["NCC", "SSIM"]) input_parser.add_option( option_string="--prefix-simulated", type=str, help="Specify the prefix of the simulated stacks to distinguish them " "from the original data.", default="Simulated_", ) input_parser.add_option( option_string="--dir-input-simulated", type=str, help="Specify the directory where the simulated stacks are. " "If not given, it is assumed that they are in the same directory " "as the original ones.", default=None) input_parser.add_slice_thicknesses(default=None) args = input_parser.parse_args() input_parser.print_arguments(args) # --------------------------------Read Data-------------------------------- ph.print_title("Read Data") # Read original data filenames_original = args.filenames data_reader = dr.MultipleImagesReader( file_paths=filenames_original, file_paths_masks=args.filenames_masks, suffix_mask=args.suffix_mask, stacks_slice_thicknesses=args.slice_thicknesses, ) data_reader.read_data() stacks_original = data_reader.get_data() # Read data simulated from obtained reconstruction if args.dir_input_simulated is None: dir_input_simulated = os.path.dirname(filenames_original[0]) else: dir_input_simulated = args.dir_input_simulated filenames_simulated = [ os.path.join("%s", "%s%s") % (dir_input_simulated, args.prefix_simulated, os.path.basename(f)) for f in filenames_original ] data_reader = dr.MultipleImagesReader(filenames_simulated, suffix_mask=args.suffix_mask) data_reader.read_data() stacks_simulated = data_reader.get_data() for i in range(len(stacks_original)): try: stacks_original[i].sitk - stacks_simulated[i].sitk except: raise IOError( "Images '%s' and '%s' do not occupy the same space!" % (filenames_original[i], filenames_simulated[i])) similarity_measures = { m: SimilarityMeasures.similarity_measures[m] for m in args.measures } similarities = np.zeros(len(args.measures)) for i in range(len(stacks_original)): nda_3D_original = sitk.GetArrayFromImage(stacks_original[i].sitk) nda_3D_simulated = sitk.GetArrayFromImage(stacks_simulated[i].sitk) nda_3D_mask = sitk.GetArrayFromImage(stacks_original[i].sitk_mask) path_to_file = os.path.join( args.dir_output, "Similarity_%s.txt" % stacks_original[i].get_filename()) text = "# Similarity: %s vs %s (%s)." % (os.path.basename( filenames_original[i]), os.path.basename( filenames_simulated[i]), ph.get_time_stamp()) text += "\n#\t" + ("\t").join(args.measures) text += "\n" ph.write_to_file(path_to_file, text, "w") for k in range(nda_3D_original.shape[0]): x_2D_original = nda_3D_original[k, :, :] x_2D_simulated = nda_3D_simulated[k, :, :] # zero slice, i.e. rejected during motion correction if np.abs(x_2D_simulated).sum() < 1e-6: x_2D_simulated[:] = np.nan x_2D_mask = nda_3D_mask[k, :, :] indices = np.where(x_2D_mask > 0) for m, measure in enumerate(args.measures): if len(indices[0]) > 0: similarities[m] = similarity_measures[measure]( x_2D_original[indices], x_2D_simulated[indices]) else: similarities[m] = np.nan ph.write_array_to_file(path_to_file, similarities.reshape(1, -1)) return 0
def main(): time_start = ph.start_timing() # Set print options np.set_printoptions(precision=3) pd.set_option('display.width', 1000) input_parser = InputArgparser(description=".", ) input_parser.add_filenames() input_parser.add_filenames_masks() input_parser.add_dir_input_mc() input_parser.add_suffix_mask(default="_mask") input_parser.add_reference(required=True) input_parser.add_reference_mask() input_parser.add_dir_output(required=False) input_parser.add_log_config(default=1) input_parser.add_measures(default=["PSNR", "RMSE", "SSIM", "NCC", "NMI"]) input_parser.add_verbose(default=0) input_parser.add_slice_thicknesses(default=None) input_parser.add_option(option_string="--use-reference-mask", type=int, default=1) input_parser.add_option(option_string="--use-slice-masks", type=int, default=1) args = input_parser.parse_args() input_parser.print_arguments(args) if args.log_config: input_parser.log_config(os.path.abspath(__file__)) # --------------------------------Read Data-------------------------------- ph.print_title("Read Data") data_reader = dr.MultipleImagesReader( file_paths=args.filenames, file_paths_masks=args.filenames_masks, suffix_mask=args.suffix_mask, dir_motion_correction=args.dir_input_mc, stacks_slice_thicknesses=args.slice_thicknesses, ) data_reader.read_data() stacks = data_reader.get_data() ph.print_info("%d input stacks read for further processing" % len(stacks)) reference = st.Stack.from_filename(args.reference, args.reference_mask) ph.print_title("Slice Residual Similarity") residual_evaluator = res_ev.ResidualEvaluator( stacks=stacks, reference=reference, measures=args.measures, use_reference_mask=args.use_reference_mask, use_slice_masks=args.use_slice_masks, ) residual_evaluator.compute_slice_projections() residual_evaluator.evaluate_slice_similarities() residual_evaluator.write_slice_similarities(args.dir_output) elapsed_time = ph.stop_timing(time_start) ph.print_title("Summary") print("Computational Time for Slice Residual Evaluation: %s" % (elapsed_time)) return 0
def main(): time_start = ph.start_timing() # Set print options np.set_printoptions(precision=3) pd.set_option('display.width', 1000) input_parser = InputArgparser( description=".", ) input_parser.add_filenames() input_parser.add_filenames_masks() input_parser.add_dir_input_mc() input_parser.add_suffix_mask(default="_mask") input_parser.add_reference(required=True) input_parser.add_reference_mask() input_parser.add_dir_output(required=False) input_parser.add_log_config(default=1) input_parser.add_measures( default=["PSNR", "MAE", "RMSE", "SSIM", "NCC", "NMI"]) input_parser.add_verbose(default=0) input_parser.add_target_stack(default=None) input_parser.add_intensity_correction(default=1) input_parser.add_slice_thicknesses(default=None) input_parser.add_option( option_string="--use-reference-mask", type=int, default=1) input_parser.add_option( option_string="--use-slice-masks", type=int, default=1) args = input_parser.parse_args() input_parser.print_arguments(args) if args.log_config: input_parser.log_config(os.path.abspath(__file__)) # --------------------------------Read Data-------------------------------- ph.print_title("Read Data") data_reader = dr.MultipleImagesReader( file_paths=args.filenames, file_paths_masks=args.filenames_masks, suffix_mask=args.suffix_mask, dir_motion_correction=args.dir_input_mc, stacks_slice_thicknesses=args.slice_thicknesses, ) data_reader.read_data() stacks = data_reader.get_data() ph.print_info("%d input stacks read for further processing" % len(stacks)) # Specify target stack for intensity correction and reconstruction space if args.target_stack is None: target_stack_index = 0 else: filenames = ["%s.nii.gz" % s.get_filename() for s in stacks] filename_target_stack = os.path.basename(args.target_stack) try: target_stack_index = filenames.index(filename_target_stack) except ValueError as e: raise ValueError( "--target-stack must correspond to an image as provided by " "--filenames") # ---------------------------Intensity Correction-------------------------- if args.intensity_correction: ph.print_title("Intensity Correction") intensity_corrector = ic.IntensityCorrection() intensity_corrector.use_individual_slice_correction(False) intensity_corrector.use_stack_mask(True) intensity_corrector.use_reference_mask(True) intensity_corrector.use_verbose(False) for i, stack in enumerate(stacks): if i == target_stack_index: ph.print_info("Stack %d (%s): Reference image. Skipped." % ( i + 1, stack.get_filename())) continue else: ph.print_info("Stack %d (%s): Intensity Correction ... " % ( i + 1, stack.get_filename()), newline=False) intensity_corrector.set_stack(stack) intensity_corrector.set_reference( stacks[target_stack_index].get_resampled_stack( resampling_grid=stack.sitk, interpolator="NearestNeighbor", )) intensity_corrector.run_linear_intensity_correction() stacks[i] = intensity_corrector.get_intensity_corrected_stack() print("done (c1 = %g) " % intensity_corrector.get_intensity_correction_coefficients()) # ----------------------- Slice Residual Similarity ----------------------- reference = st.Stack.from_filename(args.reference, args.reference_mask) ph.print_title("Slice Residual Similarity") residual_evaluator = res_ev.ResidualEvaluator( stacks=stacks, reference=reference, measures=args.measures, use_reference_mask=args.use_reference_mask, use_slice_masks=args.use_slice_masks, ) residual_evaluator.compute_slice_projections() residual_evaluator.evaluate_slice_similarities() residual_evaluator.write_slice_similarities(args.dir_output) elapsed_time = ph.stop_timing(time_start) ph.print_title("Summary") print("Computational Time for Slice Residual Evaluation: %s" % (elapsed_time)) return 0