def main(): input_parser = InputArgparser( description="Create and write random motion transforms.", ) input_parser.add_dir_output(required=True) input_parser.add_option( option_string="--simulations", type=int, required=True) input_parser.add_option(option_string="--angle-max", default=10) input_parser.add_option(option_string="--translation-max", default=10) input_parser.add_option(option_string="--seed", type=int, default=1) input_parser.add_option(option_string="--dimension", type=int, default=3) input_parser.add_option( option_string="--write-settings", type=int, default=1) input_parser.add_prefix_output(default="Euler3DTransform_") input_parser.add_verbose(default=0) args = input_parser.parse_args() input_parser.print_arguments(args) motion_simulator = ms.RandomRigidMotionSimulator( dimension=args.dimension, angle_max_deg=args.angle_max, translation_max=args.translation_max, verbose=args.verbose) motion_simulator.simulate_motion( seed=args.seed, simulations=args.simulations) prefix = "%sAngle%gTranslation%gSeed%d_" % ( args.prefix_output, args.angle_max, args.translation_max, args.seed) prefix = prefix.replace(".", "p") motion_simulator.write_transforms_sitk( directory=args.dir_output, prefix_filename=prefix) return 0
def main(): input_parser = InputArgparser( description="Create and write random rigid motion transformations. " "Simulated transformations are exported as (Simple)ITK transforms. ", ) input_parser.add_dir_output(required=True) input_parser.add_option( option_string="--simulations", type=int, required=True, help="Number of simulated motion transformations." ) input_parser.add_option( option_string="--angle-max", default=10, help="random angles (in degree) are drawn such " "that |angle| <= angle_max." ) input_parser.add_option( option_string="--translation-max", default=10, help="random translations (in millimetre) are drawn such " "that |translation| <= translation_max." ) input_parser.add_option( option_string="--seed", type=int, default=1, help="Seed for pseudo-random data generation" ) input_parser.add_option( option_string="--dimension", type=int, default=3, help="Spatial dimension for transformations." ) input_parser.add_prefix_output(default="EulerTransform_slice") input_parser.add_verbose(default=1) args = input_parser.parse_args() input_parser.print_arguments(args) motion_simulator = ms.RandomRigidMotionSimulator( dimension=args.dimension, angle_max_deg=args.angle_max, translation_max=args.translation_max, verbose=args.verbose) motion_simulator.simulate_motion( seed=args.seed, simulations=args.simulations, ) motion_simulator.write_transforms_sitk( directory=args.dir_output, prefix_filename=args.prefix_output, ) 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(): input_parser = InputArgparser( description="Simulate stacks from obtained reconstruction. " "Script simulates/projects the slices at estimated positions " "within reconstructed volume. Ideally, if motion correction was " "correct, the resulting stack of such obtained projected slices, " "corresponds to the originally acquired (motion corrupted) data.", ) input_parser.add_filenames(required=True) input_parser.add_filenames_masks() input_parser.add_dir_input_mc(required=True) input_parser.add_reconstruction(required=True) input_parser.add_dir_output(required=True) input_parser.add_suffix_mask(default="_mask") input_parser.add_prefix_output(default="Simulated_") input_parser.add_option( option_string="--copy-data", type=int, help="Turn on/off copying of original data (including masks) to " "output folder.", default=0) input_parser.add_option( option_string="--reconstruction-mask", type=str, help="If given, reconstruction image mask is propagated to " "simulated stack(s) of slices as well", default=None) input_parser.add_interpolator( option_string="--interpolator-mask", help="Choose the interpolator type to propagate the reconstruction " "mask (%s)." % (INTERPOLATOR_TYPES), default="NearestNeighbor") input_parser.add_log_config(default=0) input_parser.add_verbose(default=0) input_parser.add_slice_thicknesses(default=None) args = input_parser.parse_args() input_parser.print_arguments(args) if args.interpolator_mask not in ALLOWED_INTERPOLATORS: raise IOError( "Unknown interpolator provided. Possible choices are %s" % ( INTERPOLATOR_TYPES)) if args.log_config: input_parser.log_config(os.path.abspath(__file__)) # Read motion corrected 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() reconstruction = st.Stack.from_filename( args.reconstruction, args.reconstruction_mask, extract_slices=False) linear_operators = lin_op.LinearOperators() for i, stack in enumerate(stacks): # initialize image data array(s) nda = np.zeros_like(sitk.GetArrayFromImage(stack.sitk)) nda[:] = np.nan if args.reconstruction_mask: nda_mask = np.zeros_like(sitk.GetArrayFromImage(stack.sitk_mask)) slices = stack.get_slices() kept_indices = [s.get_slice_number() for s in slices] # Fill stack information "as if slice was acquired consecutively" # Therefore, simulated stack slices correspond to acquired slices # (in case motion correction was correct) for j in range(nda.shape[0]): if j in kept_indices: index = kept_indices.index(j) simulated_slice = linear_operators.A( reconstruction, slices[index], interpolator_mask=args.interpolator_mask ) nda[j, :, :] = sitk.GetArrayFromImage(simulated_slice.sitk) if args.reconstruction_mask: nda_mask[j, :, :] = sitk.GetArrayFromImage( simulated_slice.sitk_mask) # Create nifti image with same image header as original stack simulated_stack_sitk = sitk.GetImageFromArray(nda) simulated_stack_sitk.CopyInformation(stack.sitk) if args.reconstruction_mask: simulated_stack_sitk_mask = sitk.GetImageFromArray(nda_mask) simulated_stack_sitk_mask.CopyInformation(stack.sitk_mask) else: simulated_stack_sitk_mask = None simulated_stack = st.Stack.from_sitk_image( image_sitk=simulated_stack_sitk, image_sitk_mask=simulated_stack_sitk_mask, filename=args.prefix_output + stack.get_filename(), extract_slices=False, slice_thickness=stack.get_slice_thickness(), ) if args.verbose: sitkh.show_stacks([ stack, simulated_stack], segmentation=stack) simulated_stack.write( args.dir_output, write_mask=False, write_slices=False, suffix_mask=args.suffix_mask) if args.copy_data: stack.write( args.dir_output, write_mask=True, write_slices=False, suffix_mask="_mask") return 0
def main(): time_start = ph.start_timing() np.set_printoptions(precision=3) input_parser = InputArgparser( description="Perform (linear) intensity correction across " "stacks/images given a reference stack/image", ) input_parser.add_filenames(required=True) input_parser.add_dir_output(required=True) input_parser.add_reference(required=True) input_parser.add_suffix_mask(default="_mask") input_parser.add_search_angle(default=180) input_parser.add_prefix_output(default="IC_") input_parser.add_log_config(default=1) input_parser.add_option( option_string="--registration", type=int, help="Turn on/off registration from image to reference prior to " "intensity correction.", default=0) input_parser.add_verbose(default=0) args = input_parser.parse_args() input_parser.print_arguments(args) if args.log_config: input_parser.log_config(os.path.abspath(__file__)) if args.reference in args.filenames: args.filenames.remove(args.reference) # Read data data_reader = dr.MultipleImagesReader(args.filenames, suffix_mask=args.suffix_mask, extract_slices=False) data_reader.read_data() stacks = data_reader.get_data() data_reader = dr.MultipleImagesReader([args.reference], suffix_mask=args.suffix_mask, extract_slices=False) data_reader.read_data() reference = data_reader.get_data()[0] if args.registration: # Define search angle ranges for FLIRT in all three dimensions search_angles = [ "-searchr%s -%d %d" % (x, args.search_angle, args.search_angle) for x in ["x", "y", "z"] ] search_angles = (" ").join(search_angles) registration = regflirt.FLIRT( moving=reference, registration_type="Rigid", use_fixed_mask=True, use_moving_mask=True, options=search_angles, use_verbose=False, ) # Perform Intensity Correction ph.print_title("Perform Intensity Correction") intensity_corrector = ic.IntensityCorrection( use_reference_mask=True, use_individual_slice_correction=False, prefix_corrected=args.prefix_output, use_verbose=False, ) stacks_corrected = [None] * len(stacks) for i, stack in enumerate(stacks): if args.registration: ph.print_info("Image %d/%d: Registration ... " % (i + 1, len(stacks)), newline=False) registration.set_fixed(stack) registration.run() transform_sitk = registration.get_registration_transform_sitk() stack.update_motion_correction(transform_sitk) print("done") ph.print_info("Image %d/%d: Intensity Correction ... " % (i + 1, len(stacks)), newline=False) ref = reference.get_resampled_stack(stack.sitk) ref = st.Stack.from_sitk_image(image_sitk=ref.sitk, image_sitk_mask=stack.sitk_mask * ref.sitk_mask, filename=reference.get_filename()) intensity_corrector.set_stack(stack) intensity_corrector.set_reference(ref) intensity_corrector.run_linear_intensity_correction() # intensity_corrector.run_affine_intensity_correction() stacks_corrected[i] = \ intensity_corrector.get_intensity_corrected_stack() print("done (c1 = %g) " % intensity_corrector.get_intensity_correction_coefficients()) # Write Data stacks_corrected[i].write(args.dir_output, write_mask=True, suffix_mask=args.suffix_mask) if args.verbose: sitkh.show_stacks( [ reference, stacks_corrected[i], # stacks[i], ], segmentation=stacks_corrected[i]) # ph.pause() # Write reference too (although not intensity corrected) reference.write(args.dir_output, filename=args.prefix_output + reference.get_filename(), write_mask=True, suffix_mask=args.suffix_mask) elapsed_time = ph.stop_timing(time_start) ph.print_title("Summary") print("Computational Time for Intensity Correction(s): %s" % (elapsed_time)) 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="Volumetric MRI reconstruction framework to reconstruct " "an isotropic, high-resolution 3D volume from multiple " "motion-corrected (or static) stacks of low-resolution slices.", ) input_parser.add_dir_input() input_parser.add_filenames() input_parser.add_image_selection() input_parser.add_dir_output(required=True) input_parser.add_prefix_output(default="SRR_") input_parser.add_suffix_mask(default="_mask") input_parser.add_target_stack_index(default=0) input_parser.add_extra_frame_target(default=10) input_parser.add_isotropic_resolution(default=None) input_parser.add_reconstruction_space(default=None) input_parser.add_minimizer(default="lsmr") input_parser.add_iter_max(default=10) input_parser.add_reconstruction_type(default="TK1L2") input_parser.add_data_loss(default="linear") input_parser.add_data_loss_scale(default=1) input_parser.add_alpha(default=0.02 # TK1L2 # default=0.006 #TVL2, HuberL2 ) input_parser.add_rho(default=0.5) input_parser.add_tv_solver(default="PD") input_parser.add_pd_alg_type(default="ALG2") input_parser.add_iterations(default=15) input_parser.add_subfolder_comparison() input_parser.add_provide_comparison(default=0) input_parser.add_log_script_execution(default=1) input_parser.add_verbose(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__)) # --------------------------------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'") if args.reconstruction_type not in ["TK1L2", "TVL2", "HuberL2"]: raise IOError("Reconstruction type unknown") data_reader.read_data() stacks = data_reader.get_data() ph.print_info("%d input stacks read for further processing" % len(stacks)) # Reconstruction space is given isotropically resampled target stack if args.reconstruction_space is None: recon0 = \ stacks[args.target_stack_index].get_isotropically_resampled_stack( resolution=args.isotropic_resolution, extra_frame=args.extra_frame_target) # Reconstruction space was provided by user else: recon0 = st.Stack.from_filename(args.reconstruction_space, extract_slices=False) # Change resolution for isotropic resolution if provided by user if args.isotropic_resolution is not None: recon0 = recon0.get_isotropically_resampled_stack( args.isotropic_resolution) # Use image information of selected target stack as recon0 serves # as initial value for reconstruction recon0 = \ stacks[args.target_stack_index].get_resampled_stack(recon0.sitk) recon0 = recon0.get_stack_multiplied_with_mask() if args.reconstruction_type in ["TVL2", "HuberL2"]: ph.print_title("Compute Initial value for %s" % args.reconstruction_type) SRR0 = tk.TikhonovSolver( stacks=stacks, reconstruction=recon0, alpha=args.alpha, iter_max=args.iter_max, reg_type="TK1", minimizer=args.minimizer, data_loss=args.data_loss, data_loss_scale=args.data_loss_scale, # verbose=args.verbose, ) SRR0.run() recon = SRR0.get_reconstruction() recon.set_filename(SRR0.get_setting_specific_filename(args.prefix_output)) recon.write(args.dir_output) # List to store SRRs recons = [] for i in range(0, len(stacks)): recons.append(stacks[i]) recons.insert(0, recon) if args.reconstruction_type in ["TVL2", "HuberL2"]: ph.print_title("Compute %s reconstruction" % args.reconstruction_type) if args.tv_solver == "ADMM": SRR = admm.ADMMSolver( stacks=stacks, reconstruction=st.Stack.from_stack(SRR0.get_reconstruction()), minimizer=args.minimizer, alpha=args.alpha, iter_max=args.iter_max, rho=args.rho, data_loss=args.data_loss, iterations=args.iterations, verbose=args.verbose, ) SRR.run() recon = SRR.get_reconstruction() recon.set_filename( SRR.get_setting_specific_filename(args.prefix_output)) recons.insert(0, recon) recon.write(args.dir_output) else: SRR = pd.PrimalDualSolver( stacks=stacks, reconstruction=st.Stack.from_stack(SRR0.get_reconstruction()), minimizer=args.minimizer, alpha=args.alpha, iter_max=args.iter_max, iterations=args.iterations, alg_type=args.pd_alg_type, reg_type="TV" if args.reconstruction_type == "TVL2" else "huber", data_loss=args.data_loss, verbose=args.verbose, ) SRR.run() recon = SRR.get_reconstruction() recon.set_filename( SRR.get_setting_specific_filename(args.prefix_output)) recons.insert(0, recon) recon.write(args.dir_output) if args.verbose and not args.provide_comparison: sitkh.show_stacks(recons) # Show SRR together with linearly resampled input data. # Additionally, a script is generated to open files if args.provide_comparison: sitkh.show_stacks( recons, show_comparison_file=args.provide_comparison, dir_output=os.path.join(args.dir_output, args.subfolder_comparison), ) ph.print_line_separator() elapsed_time = ph.stop_timing(time_start) ph.print_title("Summary") print("Computational Time for Volumetric Reconstruction: %s" % (elapsed_time)) return 0
def main(): time_start = ph.start_timing() np.set_printoptions(precision=3) input_parser = InputArgparser( description="Perform Bias Field correction on images based on N4ITK.", ) input_parser.add_filenames(required=True) input_parser.add_dir_output(required=True) input_parser.add_suffix_mask(default="_mask") input_parser.add_prefix_output(default="N4ITK_") input_parser.add_option( option_string="--convergence-threshold", type=float, help="Specify the convergence threshold.", default=1e-6, ) input_parser.add_option( option_string="--spline-order", type=int, help="Specify the spline order defining the bias field estimate.", default=3, ) input_parser.add_option( option_string="--wiener-filter-noise", type=float, help="Specify the noise estimate defining the Wiener filter.", default=0.11, ) input_parser.add_option( option_string="--bias-field-fwhm", type=float, help="Specify the full width at half maximum parameter characterizing " "the width of the Gaussian deconvolution.", default=0.15, ) input_parser.add_log_script_execution(default=1) input_parser.add_verbose(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__)) # Read data data_reader = dr.MultipleImagesReader(args.filenames, suffix_mask=args.suffix_mask) data_reader.read_data() stacks = data_reader.get_data() # Perform Bias Field Correction ph.print_title("Perform Bias Field Correction") bias_field_corrector = n4itk.N4BiasFieldCorrection( convergence_threshold=args.convergence_threshold, spline_order=args.spline_order, wiener_filter_noise=args.wiener_filter_noise, bias_field_fwhm=args.bias_field_fwhm, prefix_corrected=args.prefix_output, ) stacks_corrected = [None] * len(stacks) for i, stack in enumerate(stacks): ph.print_info("Image %d/%d: N4ITK Bias Field Correction ... " % (i + 1, len(stacks)), newline=False) bias_field_corrector.set_stack(stack) bias_field_corrector.run_bias_field_correction() stacks_corrected[i] = \ bias_field_corrector.get_bias_field_corrected_stack() print("done") ph.print_info("Image %d/%d: Computational time = %s" % (i + 1, len(stacks), bias_field_corrector.get_computational_time())) # Write Data stacks_corrected[i].write(args.dir_output, write_mask=True, suffix_mask=args.suffix_mask) if args.verbose: sitkh.show_stacks([stacks[i], stacks_corrected[i]], segmentation=stacks[i]) elapsed_time = ph.stop_timing(time_start) ph.print_title("Summary") print("Computational Time for Bias Field Correction(s): %s" % (elapsed_time)) 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, " "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) 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