def main(): time_start = ph.start_timing() np.set_printoptions(precision=3) input_parser = InputArgparser( description="Run reconstruction pipeline including " "(i) bias field correction, " "(ii) volumetric reconstruction in subject space, " "and (iii) volumetric reconstruction in template space.", ) input_parser.add_filenames(required=True) input_parser.add_filenames_masks(required=True) input_parser.add_target_stack(required=False) input_parser.add_suffix_mask(default="''") input_parser.add_dir_output(required=True) input_parser.add_alpha(default=0.01) input_parser.add_verbose(default=0) input_parser.add_gestational_age(required=False) input_parser.add_prefix_output(default="") input_parser.add_search_angle(default=180) input_parser.add_multiresolution(default=0) input_parser.add_log_config(default=1) input_parser.add_isotropic_resolution() input_parser.add_reference() input_parser.add_reference_mask() input_parser.add_bias_field_correction(default=1) input_parser.add_intensity_correction(default=1) input_parser.add_iter_max(default=10) input_parser.add_two_step_cycles(default=3) input_parser.add_option( option_string="--run-bias-field-correction", type=int, help="Turn on/off bias field correction. " "If off, it is assumed that this step was already performed", default=1) input_parser.add_option( option_string="--run-recon-subject-space", type=int, help="Turn on/off reconstruction in subject space. " "If off, it is assumed that this step was already performed", default=1) input_parser.add_option( option_string="--run-recon-template-space", type=int, help="Turn on/off reconstruction in template space. " "If off, it is assumed that this step was already performed", default=1) input_parser.add_option( option_string="--run-data-vs-simulated-data", type=int, help="Turn on/off comparison of data vs data simulated from the " "obtained volumetric reconstruction. " "If off, it is assumed that this step was already performed", default=0) input_parser.add_option( option_string="--initial-transform", type=str, help="Set initial transform to be used for register_image.", default=None) input_parser.add_outlier_rejection(default=1) input_parser.add_argument( "--sda", "-sda", action='store_true', help="If given, the volume is reconstructed using " "Scattered Data Approximation (Vercauteren et al., 2006). " "--alpha is considered the value for the standard deviation then. " "Recommended value is, e.g., --alpha 0.8") args = input_parser.parse_args() input_parser.print_arguments(args) if args.log_config: input_parser.log_config(os.path.abspath(__file__)) filename_srr = "srr" dir_output_preprocessing = os.path.join(args.dir_output, "preprocessing_n4itk") dir_output_recon_subject_space = os.path.join(args.dir_output, "recon_subject_space") dir_output_recon_template_space = os.path.join(args.dir_output, "recon_template_space") dir_output_data_vs_simulatd_data = os.path.join(args.dir_output, "data_vs_simulated_data") srr_subject = os.path.join(dir_output_recon_subject_space, "%s_subject.nii.gz" % filename_srr) srr_subject_mask = ph.append_to_filename(srr_subject, "_mask") srr_template = os.path.join(dir_output_recon_template_space, "%s_template.nii.gz" % filename_srr) srr_template_mask = ph.append_to_filename(srr_template, "_mask") trafo_template = os.path.join(dir_output_recon_template_space, "registration_transform_sitk.txt") if args.target_stack is None: target_stack = args.filenames[0] else: target_stack = args.target_stack if args.bias_field_correction and args.run_bias_field_correction: for i, f in enumerate(args.filenames): output = os.path.join(dir_output_preprocessing, os.path.basename(f)) cmd_args = [] cmd_args.append("--filename %s" % f) cmd_args.append("--filename-mask %s" % args.filenames_masks[i]) cmd_args.append("--output %s" % output) # cmd_args.append("--verbose %d" % args.verbose) cmd = "niftymic_correct_bias_field %s" % (" ").join(cmd_args) time_start_bias = ph.start_timing() exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Bias field correction failed") elapsed_time_bias = ph.stop_timing(time_start_bias) filenames = [ os.path.join(dir_output_preprocessing, os.path.basename(f)) for f in args.filenames ] elif args.bias_field_correction and not args.run_bias_field_correction: elapsed_time_bias = ph.get_zero_time() filenames = [ os.path.join(dir_output_preprocessing, os.path.basename(f)) for f in args.filenames ] else: elapsed_time_bias = ph.get_zero_time() filenames = args.filenames if args.run_recon_subject_space: target_stack_index = args.filenames.index(target_stack) cmd_args = [] cmd_args.append("--filenames %s" % (" ").join(filenames)) if args.filenames_masks is not None: cmd_args.append("--filenames-masks %s" % (" ").join(args.filenames_masks)) cmd_args.append("--multiresolution %d" % args.multiresolution) cmd_args.append("--target-stack-index %d" % target_stack_index) cmd_args.append("--output %s" % srr_subject) cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) cmd_args.append("--intensity-correction %d" % args.intensity_correction) cmd_args.append("--alpha %s" % args.alpha) cmd_args.append("--iter-max %d" % args.iter_max) cmd_args.append("--two-step-cycles %d" % args.two_step_cycles) cmd_args.append("--outlier-rejection %d" % args.outlier_rejection) cmd_args.append("--verbose %d" % args.verbose) if args.isotropic_resolution is not None: cmd_args.append("--isotropic-resolution %f" % args.isotropic_resolution) if args.reference is not None: cmd_args.append("--reference %s" % args.reference) if args.reference_mask is not None: cmd_args.append("--reference-mask %s" % args.reference_mask) if args.sda: cmd_args.append("--sda") cmd = "niftymic_reconstruct_volume %s" % (" ").join(cmd_args) time_start_volrec = ph.start_timing() exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Reconstruction in subject space failed") # Compute SRR mask in subject space # (Approximated using SDA within reconstruct_volume) if 0: dir_motion_correction = os.path.join( dir_output_recon_subject_space, "motion_correction") cmd_args = ["niftymic_reconstruct_volume_from_slices"] cmd_args.append("--filenames %s" % " ".join(args.filenames_masks)) cmd_args.append("--dir-input-mc %s" % dir_motion_correction) cmd_args.append("--output %s" % srr_subject_mask) cmd_args.append("--reconstruction-space %s" % srr_subject) cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) cmd_args.append("--mask") if args.sda: cmd_args.append("--sda") cmd_args.append("--alpha 1") else: cmd_args.append("--alpha 0.1") cmd_args.append("--iter-max 5") cmd = (" ").join(cmd_args) ph.execute_command(cmd) elapsed_time_volrec = ph.stop_timing(time_start_volrec) else: elapsed_time_volrec = ph.get_zero_time() if args.run_recon_template_space: if args.gestational_age is None: template_stack_estimator = \ tse.TemplateStackEstimator.from_mask(srr_subject_mask) gestational_age = template_stack_estimator.get_estimated_gw() ph.print_info("Estimated gestational age: %d" % gestational_age) else: gestational_age = args.gestational_age template = os.path.join(DIR_TEMPLATES, "STA%d.nii.gz" % gestational_age) template_mask = os.path.join(DIR_TEMPLATES, "STA%d_mask.nii.gz" % gestational_age) cmd_args = [] cmd_args.append("--fixed %s" % template) cmd_args.append("--moving %s" % srr_subject) cmd_args.append("--fixed-mask %s" % template_mask) cmd_args.append("--moving-mask %s" % srr_subject_mask) cmd_args.append( "--dir-input-mc %s" % os.path.join(dir_output_recon_subject_space, "motion_correction")) cmd_args.append("--output %s" % trafo_template) cmd_args.append("--verbose %s" % args.verbose) if args.initial_transform is not None: cmd_args.append("--initial-transform %s" % args.initial_transform) cmd_args.append("--use-flirt 0") cmd_args.append("--test-ap-flip 0") cmd = "niftymic_register_image %s" % (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Registration to template space failed") # reconstruct volume in template space # pattern = "[a-zA-Z0-9_.]+(ResamplingToTemplateSpace.nii.gz)" # p = re.compile(pattern) # reconstruction_space = [ # os.path.join(dir_output_recon_template_space, p.match(f).group(0)) # for f in os.listdir(dir_output_recon_template_space) # if p.match(f)][0] dir_input_mc = os.path.join(dir_output_recon_template_space, "motion_correction") cmd_args = ["niftymic_reconstruct_volume_from_slices"] cmd_args.append("--filenames %s" % (" ").join(filenames)) cmd_args.append("--dir-input-mc %s" % dir_input_mc) cmd_args.append("--output %s" % srr_template) cmd_args.append("--reconstruction-space %s" % template) cmd_args.append("--iter-max %d" % args.iter_max) cmd_args.append("--alpha %s" % args.alpha) cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) cmd_args.append("--verbose %s" % args.verbose) if args.sda: cmd_args.append("--sda") cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Reconstruction in template space failed") # Compute SRR mask in template space if 1: dir_motion_correction = os.path.join( dir_output_recon_template_space, "motion_correction") cmd_args = ["niftymic_reconstruct_volume_from_slices"] cmd_args.append("--filenames %s" % " ".join(args.filenames_masks)) cmd_args.append("--dir-input-mc %s" % dir_motion_correction) cmd_args.append("--output %s" % srr_template_mask) cmd_args.append("--reconstruction-space %s" % srr_template) cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) cmd_args.append("--mask") if args.sda: cmd_args.append("--sda") cmd_args.append("--alpha 1") else: cmd_args.append("--alpha 0.1") cmd_args.append("--iter-max 5") cmd = (" ").join(cmd_args) ph.execute_command(cmd) # Copy SRR to output directory output = "%sSRR_Stacks%d.nii.gz" % (args.prefix_output, len(args.filenames)) path_to_output = os.path.join(args.dir_output, output) cmd = "cp -p %s %s" % (srr_template, path_to_output) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Copy of SRR to output directory failed") # Multiply template mask with reconstruction cmd_args = ["niftymic_multiply"] fnames = [ srr_template, srr_template_mask, ] output_masked = "Masked_%s" % output path_to_output_masked = os.path.join(args.dir_output, output_masked) cmd_args.append("--filenames %s" % " ".join(fnames)) cmd_args.append("--output %s" % path_to_output_masked) cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("SRR brain masking failed") else: elapsed_time_template = ph.get_zero_time() if args.run_data_vs_simulated_data: dir_input_mc = os.path.join(dir_output_recon_template_space, "motion_correction") # Get simulated/projected slices cmd_args = [] cmd_args.append("--filenames %s" % (" ").join(filenames)) if args.filenames_masks is not None: cmd_args.append("--filenames-masks %s" % (" ").join(args.filenames_masks)) cmd_args.append("--dir-input-mc %s" % dir_input_mc) cmd_args.append("--dir-output %s" % dir_output_data_vs_simulatd_data) cmd_args.append("--reconstruction %s" % srr_template) cmd_args.append("--copy-data 1") cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) # cmd_args.append("--verbose %s" % args.verbose) exe = os.path.abspath(simulate_stacks_from_reconstruction.__file__) cmd = "python %s %s" % (exe, (" ").join(cmd_args)) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("SRR slice projections failed") filenames_simulated = [ os.path.join(dir_output_data_vs_simulatd_data, os.path.basename(f)) for f in filenames ] dir_output_evaluation = os.path.join(dir_output_data_vs_simulatd_data, "evaluation") dir_output_figures = os.path.join(dir_output_data_vs_simulatd_data, "figures") dir_output_side_by_side = os.path.join(dir_output_figures, "side-by-side") # Evaluate slice similarities to ground truth cmd_args = [] cmd_args.append("--filenames %s" % (" ").join(filenames_simulated)) if args.filenames_masks is not None: cmd_args.append("--filenames-masks %s" % (" ").join(args.filenames_masks)) cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) cmd_args.append("--measures NCC SSIM") cmd_args.append("--dir-output %s" % dir_output_evaluation) exe = os.path.abspath(evaluate_simulated_stack_similarity.__file__) cmd = "python %s %s" % (exe, (" ").join(cmd_args)) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Evaluation of slice similarities failed") # Generate figures showing the quantitative comparison cmd_args = [] cmd_args.append("--dir-input %s" % dir_output_evaluation) cmd_args.append("--dir-output %s" % dir_output_figures) exe = os.path.abspath( show_evaluated_simulated_stack_similarity.__file__) cmd = "python %s %s" % (exe, (" ").join(cmd_args)) exit_code = ph.execute_command(cmd) if exit_code != 0: ph.print_warning("Visualization of slice similarities failed") # Generate pdfs showing all the side-by-side comparisons cmd_args = [] cmd_args.append("--filenames %s" % (" ").join(filenames_simulated)) cmd_args.append("--dir-output %s" % dir_output_side_by_side) exe = os.path.abspath( export_side_by_side_simulated_vs_original_slice_comparison.__file__ ) cmd = "python %s %s" % (exe, (" ").join(cmd_args)) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Generation of PDF overview failed") ph.print_title("Summary") print("Computational Time for Bias Field Correction: %s" % elapsed_time_bias) print("Computational Time for Volumetric Reconstruction: %s" % elapsed_time_volrec) print("Computational Time for Pipeline: %s" % ph.stop_timing(time_start)) return 0
def main(): time_start = ph.start_timing() np.set_printoptions(precision=3) input_parser = InputArgparser( description="Run reconstruction pipeline including " "(i) bias field correction, " "(ii) volumetric reconstruction in subject space, " "(iii) volumetric reconstruction in template space, " "and (iv) some diagnostics to assess the obtained reconstruction.", ) input_parser.add_filenames(required=True) input_parser.add_filenames_masks(required=True) input_parser.add_target_stack(required=False) input_parser.add_suffix_mask(default="") input_parser.add_dir_output(required=True) input_parser.add_alpha(default=0.01) input_parser.add_verbose(default=0) input_parser.add_gestational_age(required=False) input_parser.add_prefix_output(default="") input_parser.add_search_angle(default=180) input_parser.add_multiresolution(default=0) input_parser.add_log_config(default=1) input_parser.add_isotropic_resolution() input_parser.add_reference() input_parser.add_reference_mask() input_parser.add_bias_field_correction(default=1) input_parser.add_intensity_correction(default=1) input_parser.add_iter_max(default=10) input_parser.add_two_step_cycles(default=3) input_parser.add_slice_thicknesses(default=None) input_parser.add_option( option_string="--run-bias-field-correction", type=int, help="Turn on/off bias field correction. " "If off, it is assumed that this step was already performed " "if --bias-field-correction is active.", default=1) input_parser.add_option( option_string="--run-recon-subject-space", type=int, help="Turn on/off reconstruction in subject space. " "If off, it is assumed that this step was already performed.", default=1) input_parser.add_option( option_string="--run-recon-template-space", type=int, help="Turn on/off reconstruction in template space. " "If off, it is assumed that this step was already performed.", default=1) input_parser.add_option( option_string="--run-diagnostics", type=int, help="Turn on/off diagnostics of the obtained volumetric " "reconstruction. ", default=0) input_parser.add_option( option_string="--initial-transform", type=str, help="Set initial transform to be used for register_image.", default=None) input_parser.add_outlier_rejection(default=1) input_parser.add_threshold_first(default=0.5) input_parser.add_threshold(default=0.8) input_parser.add_argument( "--sda", "-sda", action='store_true', help="If given, the volume is reconstructed using " "Scattered Data Approximation (Vercauteren et al., 2006). " "--alpha is considered the value for the standard deviation then. " "Recommended value is, e.g., --alpha 0.8") input_parser.add_argument( "--v2v-robust", "-v2v-robust", action='store_true', help="If given, a more robust volume-to-volume registration step is " "performed, i.e. four rigid registrations are performed using four " "rigid transform initializations based on " "principal component alignment of associated masks.") input_parser.add_interleave(default=3) input_parser.add_argument( "--s2v-hierarchical", "-s2v-hierarchical", action='store_true', help="If given, a hierarchical approach for the first slice-to-volume " "registration cycle is used, i.e. sub-packages defined by the " "specified interleave (--interleave) are registered until each " "slice is registered independently.") args = input_parser.parse_args() input_parser.print_arguments(args) if args.log_config: input_parser.log_config(os.path.abspath(__file__)) filename_srr = "srr" dir_output_preprocessing = os.path.join(args.dir_output, "preprocessing_n4itk") dir_output_recon_subject_space = os.path.join(args.dir_output, "recon_subject_space") dir_output_recon_template_space = os.path.join(args.dir_output, "recon_template_space") dir_output_diagnostics = os.path.join(args.dir_output, "diagnostics") srr_subject = os.path.join(dir_output_recon_subject_space, "%s_subject.nii.gz" % filename_srr) srr_subject_mask = ph.append_to_filename(srr_subject, "_mask") srr_template = os.path.join(dir_output_recon_template_space, "%s_template.nii.gz" % filename_srr) srr_template_mask = ph.append_to_filename(srr_template, "_mask") trafo_template = os.path.join(dir_output_recon_template_space, "registration_transform_sitk.txt") srr_slice_coverage = os.path.join( dir_output_diagnostics, "%s_template_slicecoverage.nii.gz" % filename_srr) if args.bias_field_correction and args.run_bias_field_correction: for i, f in enumerate(args.filenames): output = os.path.join(dir_output_preprocessing, os.path.basename(f)) cmd_args = [] cmd_args.append("--filename '%s'" % f) cmd_args.append("--filename-mask '%s'" % args.filenames_masks[i]) cmd_args.append("--output '%s'" % output) # cmd_args.append("--verbose %d" % args.verbose) cmd_args.append("--log-config %d" % args.log_config) cmd = "niftymic_correct_bias_field %s" % (" ").join(cmd_args) time_start_bias = ph.start_timing() exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Bias field correction failed") elapsed_time_bias = ph.stop_timing(time_start_bias) filenames = [ os.path.join(dir_output_preprocessing, os.path.basename(f)) for f in args.filenames ] elif args.bias_field_correction and not args.run_bias_field_correction: elapsed_time_bias = ph.get_zero_time() filenames = [ os.path.join(dir_output_preprocessing, os.path.basename(f)) for f in args.filenames ] else: elapsed_time_bias = ph.get_zero_time() filenames = args.filenames # Specify target stack for intensity correction and reconstruction space if args.target_stack is None: target_stack = filenames[0] else: try: target_stack_index = args.filenames.index(args.target_stack) except ValueError as e: raise ValueError( "--target-stack must correspond to an image as provided by " "--filenames") target_stack = filenames[target_stack_index] # Add single quotes around individual filenames to account for whitespaces filenames = ["'" + f + "'" for f in filenames] filenames_masks = ["'" + f + "'" for f in args.filenames_masks] if args.run_recon_subject_space: cmd_args = ["niftymic_reconstruct_volume"] cmd_args.append("--filenames %s" % (" ").join(filenames)) cmd_args.append("--filenames-masks %s" % (" ").join(filenames_masks)) cmd_args.append("--multiresolution %d" % args.multiresolution) cmd_args.append("--target-stack '%s'" % target_stack) cmd_args.append("--output '%s'" % srr_subject) cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) cmd_args.append("--intensity-correction %d" % args.intensity_correction) cmd_args.append("--alpha %s" % args.alpha) cmd_args.append("--iter-max %d" % args.iter_max) cmd_args.append("--two-step-cycles %d" % args.two_step_cycles) cmd_args.append("--outlier-rejection %d" % args.outlier_rejection) cmd_args.append("--threshold-first %f" % args.threshold_first) cmd_args.append("--threshold %f" % args.threshold) if args.slice_thicknesses is not None: cmd_args.append("--slice-thicknesses %s" % " ".join(map(str, args.slice_thicknesses))) cmd_args.append("--verbose %d" % args.verbose) cmd_args.append("--log-config %d" % args.log_config) if args.isotropic_resolution is not None: cmd_args.append("--isotropic-resolution %f" % args.isotropic_resolution) if args.reference is not None: cmd_args.append("--reference %s" % args.reference) if args.reference_mask is not None: cmd_args.append("--reference-mask %s" % args.reference_mask) if args.sda: cmd_args.append("--sda") if args.v2v_robust: cmd_args.append("--v2v-robust") if args.s2v_hierarchical: cmd_args.append("--s2v-hierarchical") cmd = (" ").join(cmd_args) time_start_volrec = ph.start_timing() exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Reconstruction in subject space failed") # Compute SRR mask in subject space # (Approximated using SDA within reconstruct_volume) if 0: dir_motion_correction = os.path.join( dir_output_recon_subject_space, "motion_correction") cmd_args = ["niftymic_reconstruct_volume_from_slices"] cmd_args.append("--filenames %s" % " ".join(filenames_masks)) cmd_args.append("--dir-input-mc '%s'" % dir_motion_correction) cmd_args.append("--output '%s'" % srr_subject_mask) cmd_args.append("--reconstruction-space '%s'" % srr_subject) cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) cmd_args.append("--mask") cmd_args.append("--log-config %d" % args.log_config) if args.slice_thicknesses is not None: cmd_args.append("--slice-thicknesses %s" % " ".join(map(str, args.slice_thicknesses))) if args.sda: cmd_args.append("--sda") cmd_args.append("--alpha 1") else: cmd_args.append("--alpha 0.1") cmd_args.append("--iter-max 5") cmd = (" ").join(cmd_args) ph.execute_command(cmd) elapsed_time_volrec = ph.stop_timing(time_start_volrec) else: elapsed_time_volrec = ph.get_zero_time() if args.run_recon_template_space: if args.gestational_age is None: template_stack_estimator = \ tse.TemplateStackEstimator.from_mask(srr_subject_mask) gestational_age = template_stack_estimator.get_estimated_gw() ph.print_info("Estimated gestational age: %d" % gestational_age) else: gestational_age = args.gestational_age template = os.path.join(DIR_TEMPLATES, "STA%d.nii.gz" % gestational_age) template_mask = os.path.join(DIR_TEMPLATES, "STA%d_mask.nii.gz" % gestational_age) # Register SRR to template space cmd_args = ["niftymic_register_image"] cmd_args.append("--fixed '%s'" % template) cmd_args.append("--moving '%s'" % srr_subject) cmd_args.append("--fixed-mask '%s'" % template_mask) cmd_args.append("--moving-mask '%s'" % srr_subject_mask) cmd_args.append( "--dir-input-mc '%s'" % os.path.join(dir_output_recon_subject_space, "motion_correction")) cmd_args.append("--output '%s'" % trafo_template) cmd_args.append("--verbose %s" % args.verbose) cmd_args.append("--log-config %d" % args.log_config) cmd_args.append("--refine-pca") if args.initial_transform is not None: cmd_args.append("--initial-transform '%s'" % args.initial_transform) cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Registration to template space failed") # Compute SRR in template space dir_input_mc = os.path.join(dir_output_recon_template_space, "motion_correction") cmd_args = ["niftymic_reconstruct_volume_from_slices"] cmd_args.append("--filenames %s" % (" ").join(filenames)) cmd_args.append("--filenames-masks %s" % (" ").join(filenames_masks)) cmd_args.append("--dir-input-mc '%s'" % dir_input_mc) cmd_args.append("--output '%s'" % srr_template) cmd_args.append("--reconstruction-space '%s'" % template) cmd_args.append("--target-stack '%s'" % target_stack) cmd_args.append("--iter-max %d" % args.iter_max) cmd_args.append("--alpha %s" % args.alpha) cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) cmd_args.append("--verbose %s" % args.verbose) cmd_args.append("--log-config %d" % args.log_config) if args.slice_thicknesses is not None: cmd_args.append("--slice-thicknesses %s" % " ".join(map(str, args.slice_thicknesses))) if args.sda: cmd_args.append("--sda") cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Reconstruction in template space failed") # Compute SRR mask in template space if 1: dir_motion_correction = os.path.join( dir_output_recon_template_space, "motion_correction") cmd_args = ["niftymic_reconstruct_volume_from_slices"] cmd_args.append("--filenames %s" % " ".join(filenames_masks)) cmd_args.append("--dir-input-mc '%s'" % dir_motion_correction) cmd_args.append("--output '%s'" % srr_template_mask) cmd_args.append("--reconstruction-space '%s'" % srr_template) cmd_args.append("--suffix-mask '%s'" % args.suffix_mask) cmd_args.append("--log-config %d" % args.log_config) cmd_args.append("--mask") if args.slice_thicknesses is not None: cmd_args.append("--slice-thicknesses %s" % " ".join(map(str, args.slice_thicknesses))) if args.sda: cmd_args.append("--sda") cmd_args.append("--alpha 1") else: cmd_args.append("--alpha 0.1") cmd_args.append("--iter-max 5") cmd = (" ").join(cmd_args) ph.execute_command(cmd) # Copy SRR to output directory if 0: output = "%sSRR_Stacks%d.nii.gz" % (args.prefix_output, len(args.filenames)) path_to_output = os.path.join(args.dir_output, output) cmd = "cp -p '%s' '%s'" % (srr_template, path_to_output) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Copy of SRR to output directory failed") # Multiply template mask with reconstruction if 0: cmd_args = ["niftymic_multiply"] fnames = [ srr_template, srr_template_mask, ] output_masked = "Masked_%s" % output path_to_output_masked = os.path.join(args.dir_output, output_masked) cmd_args.append("--filenames %s" % " ".join(fnames)) cmd_args.append("--output '%s'" % path_to_output_masked) cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("SRR brain masking failed") else: elapsed_time_template = ph.get_zero_time() if args.run_diagnostics: dir_input_mc = os.path.join(dir_output_recon_template_space, "motion_correction") dir_output_orig_vs_proj = os.path.join(dir_output_diagnostics, "original_vs_projected") dir_output_selfsimilarity = os.path.join(dir_output_diagnostics, "selfsimilarity") dir_output_orig_vs_proj_pdf = os.path.join(dir_output_orig_vs_proj, "pdf") # Show slice coverage over reconstruction space exe = os.path.abspath(show_slice_coverage.__file__) cmd_args = ["python %s" % exe] cmd_args.append("--filenames %s" % (" ").join(filenames)) cmd_args.append("--dir-input-mc '%s'" % dir_input_mc) cmd_args.append("--reconstruction-space '%s'" % srr_template) cmd_args.append("--output '%s'" % srr_slice_coverage) cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Slice coverage visualization failed") # Get simulated/projected slices exe = os.path.abspath(simulate_stacks_from_reconstruction.__file__) cmd_args = ["python %s" % exe] cmd_args.append("--filenames %s" % (" ").join(filenames)) if args.filenames_masks is not None: cmd_args.append("--filenames-masks %s" % (" ").join(filenames_masks)) cmd_args.append("--dir-input-mc '%s'" % dir_input_mc) cmd_args.append("--dir-output '%s'" % dir_output_orig_vs_proj) cmd_args.append("--reconstruction '%s'" % srr_template) cmd_args.append("--copy-data 1") if args.slice_thicknesses is not None: cmd_args.append("--slice-thicknesses %s" % " ".join(map(str, args.slice_thicknesses))) # cmd_args.append("--verbose %s" % args.verbose) cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("SRR slice projections failed") filenames_simulated = [ "'%s" % os.path.join(dir_output_orig_vs_proj, os.path.basename(f)) for f in filenames ] # Evaluate slice similarities to ground truth exe = os.path.abspath(evaluate_simulated_stack_similarity.__file__) cmd_args = ["python %s" % exe] cmd_args.append("--filenames %s" % (" ").join(filenames_simulated)) if args.filenames_masks is not None: cmd_args.append("--filenames-masks %s" % (" ").join(filenames_masks)) cmd_args.append("--measures NCC SSIM") cmd_args.append("--dir-output '%s'" % dir_output_selfsimilarity) cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Evaluation of stack similarities failed") # Generate figures showing the quantitative comparison exe = os.path.abspath( show_evaluated_simulated_stack_similarity.__file__) cmd_args = ["python %s" % exe] cmd_args.append("--dir-input '%s'" % dir_output_selfsimilarity) cmd_args.append("--dir-output '%s'" % dir_output_selfsimilarity) cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: ph.print_warning("Visualization of stack similarities failed") # Generate pdfs showing all the side-by-side comparisons if 0: exe = os.path.abspath( export_side_by_side_simulated_vs_original_slice_comparison. __file__) cmd_args = ["python %s" % exe] cmd_args.append("--filenames %s" % (" ").join(filenames_simulated)) cmd_args.append("--dir-output '%s'" % dir_output_orig_vs_proj_pdf) cmd = "python %s %s" % (exe, (" ").join(cmd_args)) cmd = (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Generation of PDF overview failed") ph.print_title("Summary") print("Computational Time for Bias Field Correction: %s" % elapsed_time_bias) print("Computational Time for Volumetric Reconstruction: %s" % elapsed_time_volrec) print("Computational Time for Pipeline: %s" % ph.stop_timing(time_start)) return 0
def main(): time_start = ph.start_timing() np.set_printoptions(precision=3) input_parser = InputArgparser( description="Run reconstruction pipeline including " "(i) preprocessing (bias field correction + intensity correction), " "(ii) volumetric reconstruction in subject space, " "and (iii) volumetric reconstruction in template space.", ) input_parser.add_dir_input(required=True) input_parser.add_dir_mask(required=True) input_parser.add_dir_output(required=True) input_parser.add_suffix_mask(default="_mask") input_parser.add_target_stack(required=False) input_parser.add_alpha(default=0.01) input_parser.add_verbose(default=0) input_parser.add_gestational_age(required=False) input_parser.add_prefix_output(default="") input_parser.add_search_angle(default=180) input_parser.add_multiresolution(default=0) input_parser.add_log_script_execution(default=1) input_parser.add_dir_input_templates(default=DIR_TEMPLATES) input_parser.add_isotropic_resolution() input_parser.add_reference() input_parser.add_reference_mask() input_parser.add_bias_field_correction(default=1) input_parser.add_intensity_correction(default=1) input_parser.add_iter_max(default=10) input_parser.add_two_step_cycles(default=3) input_parser.add_option( option_string="--run-recon-subject-space", type=int, help="Turn on/off reconstruction in subject space", default=1) input_parser.add_option( option_string="--run-recon-template-space", type=int, help="Turn on/off reconstruction in template space", default=1) input_parser.add_option( option_string="--run-data-vs-simulated-data", type=int, help="Turn on/off comparison of data vs data simulated from the " "obtained volumetric reconstruction", default=1) input_parser.add_outlier_rejection(default=0) input_parser.add_use_robust_registration(default=0) args = input_parser.parse_args() input_parser.print_arguments(args) # Write script execution call if args.log_script_execution: input_parser.write_performed_script_execution( os.path.abspath(__file__)) dir_output_recon_subject_space = os.path.join( args.dir_output, "recon_subject_space") dir_output_recon_template_space = os.path.join( args.dir_output, "recon_template_space") dir_output_data_vs_simulatd_data = os.path.join( args.dir_output, "data_vs_simulated_data") # if args.run_recon_template_space and args.gestational_age is None: # raise IOError("Gestational age must be set in order to pick the " # "right template") # get input stack names files = os.listdir(args.dir_input) input_files = [] mask_files = [] for file in files: if (".nii" in file): input_files.append("{0:}/{1:}".format(args.dir_input, file)) file_prefix = file[:-7] if (".nii.gz" in file) else file[:-4] mask_name = "{0:}/{1:}.nii.gz".format(args.dir_mask, file_prefix) if(not os.path.isfile(mask_name)): mask_name = "{0:}/{1:}.nii".format(args.dir_mask, file_prefix) assert(os.path.isfile(mask_name)) mask_files.append(mask_name) if args.target_stack is None: target_stack = input_files[0] else: target_stack = input_files if args.run_recon_subject_space: target_stack_index = input_files.index(target_stack) cmd_args = [] cmd_args.append("--filenames %s" % (" ").join(input_files)) cmd_args.append("--filenames-masks %s" % (" ").join(mask_files)) cmd_args.append("--multiresolution %d" % args.multiresolution) cmd_args.append("--target-stack-index %d" % target_stack_index) cmd_args.append("--dir-output %s" % dir_output_recon_subject_space) # cmd_args.append("--suffix-mask %s" % args.suffix_mask) cmd_args.append("--intensity-correction %d" % args.intensity_correction) cmd_args.append("--alpha %s" % args.alpha) cmd_args.append("--iter-max %d" % args.iter_max) cmd_args.append("--two-step-cycles %d" % args.two_step_cycles) cmd_args.append("--outlier-rejection %d" % args.outlier_rejection) cmd_args.append("--use-robust-registration %d" % args.use_robust_registration) cmd_args.append("--verbose %d" % args.verbose) if args.isotropic_resolution is not None: cmd_args.append("--isotropic-resolution %f" % args.isotropic_resolution) if args.reference is not None: cmd_args.append("--reference %s" % args.reference) if args.reference_mask is not None: cmd_args.append("--reference-mask %s" % args.reference_mask) cmd = "niftymic_reconstruct_volume %s" % (" ").join(cmd_args) time_start_volrec = ph.start_timing() exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Reconstruction in subject space failed") elapsed_time_volrec = ph.stop_timing(time_start_volrec) else: elapsed_time_volrec = ph.get_zero_time() if args.run_recon_template_space: # register recon to template space pattern = "[a-zA-Z0-9_]+(stacks)[a-zA-Z0-9_]+(.nii.gz)" p = re.compile(pattern) reconstruction = [ os.path.join( dir_output_recon_subject_space, p.match(f).group(0)) for f in os.listdir(dir_output_recon_subject_space) if p.match(f)][0] if('mask_manual' in args.dir_output): # find the corresponding template by volume matching reconstruction_mask = reconstruction if(not ("_mask" in reconstruction)): reconstruction_mask = ph.append_to_filename(reconstruction, "_mask") template_stack_estimator = \ tse.TemplateStackEstimator.from_mask( reconstruction_mask, args.dir_input_templates) template_mask = template_stack_estimator.get_path_to_template() template = template_mask.replace('_mask_dil.nii.gz', '.nii.gz') print('template name', template) # template = os.path.join( # args.dir_input_templates, # "STA%d.nii.gz" % args.gestational_age) # template_mask = os.path.join( # args.dir_input_templates, # "STA%d_mask.nii.gz" % args.gestational_age) else: template_folder = args.dir_output + "/../../mask_manual/reconstruct_outlier_gpr/" file_names = os.listdir(template_folder) template_names = [item for item in file_names if ("nii.gz" in item) and ("Masked" not in item)] mask_names = [item for item in file_names if ("nii.gz" in item) and ("Masked" in item)] template = os.path.join(template_folder, template_names[0]) template_mask = os.path.join(template_folder, mask_names[0]) cmd_args = [] cmd_args.append("--moving %s" % reconstruction) cmd_args.append("--fixed %s" % template) # if(use_spatiotemporal_template is False): # cmd_args.append("--use-fixed-mask 1") # added by Guotai # cmd_args.append("--template-mask %s" % template_mask) # micheal's code cmd_args.append("--dir-input %s" % os.path.join( dir_output_recon_subject_space, "motion_correction")) cmd_args.append("--dir-output %s" % dir_output_recon_template_space) cmd_args.append("--suffix-mask %s" % args.suffix_mask) cmd_args.append("--verbose %s" % args.verbose) cmd = "niftymic_register_image %s" % (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Registration to template space failed") # reconstruct volume in template space # pattern = "[a-zA-Z0-9_.]+(ResamplingToTemplateSpace.nii.gz)" # p = re.compile(pattern) # reconstruction_space = [ # os.path.join(dir_output_recon_template_space, p.match(f).group(0)) # for f in os.listdir(dir_output_recon_template_space) # if p.match(f)][0] dir_input = os.path.join( dir_output_recon_template_space, "motion_correction") cmd_args = [] cmd_args.append("--dir-input %s" % dir_input) cmd_args.append("--dir-output %s" % dir_output_recon_template_space) cmd_args.append("--reconstruction-space %s" % template) cmd_args.append("--iter-max %d" % args.iter_max) cmd_args.append("--alpha %s" % args.alpha) cmd_args.append("--suffix-mask %s" % args.suffix_mask) cmd = "niftymic_reconstruct_volume_from_slices %s" % \ (" ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Reconstruction in template space failed") pattern = "[a-zA-Z0-9_.]+(stacks[0-9]+).*(.nii.gz)" p = re.compile(pattern) reconstruction = { p.match(f).group(1): os.path.join( dir_output_recon_template_space, p.match(f).group(0)) for f in os.listdir(dir_output_recon_template_space) if p.match(f) and not p.match(f).group(0).endswith( "ResamplingToTemplateSpace.nii.gz")} key = reconstruction.keys()[0] path_to_recon = reconstruction[key] # Copy SRR to output directory output = "%sSRR_%s_GW%d.nii.gz" % ( args.prefix_output, key, args.gestational_age) path_to_output = os.path.join(args.dir_output, output) cmd = "cp -p %s %s" % (path_to_recon, path_to_output) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Copy of SRR to output directory failed") # Multiply template mask with reconstruction cmd_args = [] cmd_args.append("--filename %s" % path_to_output) cmd_args.append("--gestational-age %s" % args.gestational_age) cmd_args.append("--verbose %s" % args.verbose) cmd_args.append("--dir-input-templates %s " % args.dir_input_templates) cmd = "niftymic_multiply_stack_with_mask %s" % ( " ").join(cmd_args) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("SRR brain masking failed") else: elapsed_time_template = ph.get_zero_time() if args.run_data_vs_simulated_data: dir_input = os.path.join( dir_output_recon_template_space, "motion_correction") pattern = "[a-zA-Z0-9_.]+(stacks[0-9]+).*(.nii.gz)" # pattern = "Masked_[a-zA-Z0-9_.]+(stacks[0-9]+).*(.nii.gz)" p = re.compile(pattern) reconstruction = { p.match(f).group(1): os.path.join( dir_output_recon_template_space, p.match(f).group(0)) for f in os.listdir(dir_output_recon_template_space) if p.match(f) and not p.match(f).group(0).endswith( "ResamplingToTemplateSpace.nii.gz")} key = reconstruction.keys()[0] path_to_recon = reconstruction[key] # Get simulated/projected slices cmd_args = [] cmd_args.append("--dir-input %s" % dir_input) cmd_args.append("--dir-output %s" % dir_output_data_vs_simulatd_data) cmd_args.append("--reconstruction %s" % path_to_recon) cmd_args.append("--copy-data 1") cmd_args.append("--suffix-mask %s" % args.suffix_mask) # cmd_args.append("--verbose %s" % args.verbose) exe = os.path.abspath(simulate_stacks_from_reconstruction.__file__) cmd = "python %s %s" % (exe, (" ").join(cmd_args)) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("SRR slice projections failed") filenames_simulated = [ os.path.join(dir_output_data_vs_simulatd_data, os.path.basename(f)) for f in input_files] dir_output_evaluation = os.path.join( dir_output_data_vs_simulatd_data, "evaluation") dir_output_figures = os.path.join( dir_output_data_vs_simulatd_data, "figures") dir_output_side_by_side = os.path.join( dir_output_figures, "side-by-side") # Evaluate slice similarities to ground truth cmd_args = [] cmd_args.append("--filenames %s" % (" ").join(filenames_simulated)) cmd_args.append("--suffix-mask %s" % args.suffix_mask) cmd_args.append("--measures NCC SSIM") cmd_args.append("--dir-output %s" % dir_output_evaluation) exe = os.path.abspath(evaluate_simulated_stack_similarity.__file__) cmd = "python %s %s" % (exe, (" ").join(cmd_args)) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Evaluation of slice similarities failed") # Generate figures showing the quantitative comparison cmd_args = [] cmd_args.append("--dir-input %s" % dir_output_evaluation) cmd_args.append("--dir-output %s" % dir_output_figures) exe = os.path.abspath( show_evaluated_simulated_stack_similarity.__file__) cmd = "python %s %s" % (exe, (" ").join(cmd_args)) exit_code = ph.execute_command(cmd) if exit_code != 0: ph.print_warning("Visualization of slice similarities failed") # Generate pdfs showing all the side-by-side comparisons cmd_args = [] cmd_args.append("--filenames %s" % (" ").join(filenames_simulated)) cmd_args.append("--dir-output %s" % dir_output_side_by_side) exe = os.path.abspath( export_side_by_side_simulated_vs_original_slice_comparison.__file__) cmd = "python %s %s" % (exe, (" ").join(cmd_args)) exit_code = ph.execute_command(cmd) if exit_code != 0: raise RuntimeError("Generation of PDF overview failed") ph.print_title("Summary") print("Computational Time for Volumetric Reconstruction: %s" % elapsed_time_volrec) print("Computational Time for Pipeline: %s" % ph.stop_timing(time_start)) return 0