def get_registered_image(nii_path, registration_dir, logging, overwrite=False): # get binaries nifty_reg_binaries_folder = source_files.get_niftyreg_binaries() program_path = get_binary(nifty_reg_binaries_folder, PROGRAM_NAME) # get file paths basedir = os.path.split(nii_path)[0] output_filename = os.path.join( basedir, "{}_transformed.nii".format(os.path.split(nii_path)[1].split(".")[0]), ) if os.path.isfile(output_filename) and not overwrite: run = False else: run = True if run: destination_image = os.path.join(registration_dir, default_atlas_name) control_point_file = os.path.join(registration_dir, DEFAULT_CONTROL_POINT_FILE) log_file_path = os.path.join(basedir, "registration_log.txt") error_file_path = os.path.join(basedir, "registration_err.txt") reg_cmd = prepare_segmentation_cmd( program_path, nii_path, output_filename, destination_image, control_point_file, ) logging.info("Running registration") try: safe_execute_command(reg_cmd, log_file_path, error_file_path) except SafeExecuteCommandError as err: raise RegistrationError("Registration failed; {}".format(err)) else: logging.info("Skipping registration as output file already exists") return brainio.load_any(output_filename)
def __get_binary(self, program_type): """ Get the path to the registration (from nifty_reg) program based on the type :param str program_type: :return: The program path :rtype: str """ from amap.config.config import get_binary program_names = { "affine": "reg_aladin", "freeform": "reg_f3d", "segmentation": "reg_resample", "transform": "reg_transform", } program_name = program_names[program_type] nifty_reg_binaries_folder = get_niftyreg_binaries() program_path = get_binary(nifty_reg_binaries_folder, program_name) return program_path
def transform_rois( roi_file, source_image_filename, destination_image_filename, control_point_file, output_filename, temp_output_filename, log_file_path, error_file_path, roi_reference_image=None, selem_size=15, nii_scale=None, transformation_matrix=None, debug=False, print_value_round_decimals=2, z_filter_padding=2, ): """ Using a source image (e.g. downsampled stack), transform an ImageJ zipped collection of ROIs into the coordinate space of a destination image (e.g. an atlas), using the inverse control point file from an existing niftyreg registration :param roi_file: .zip collection of ImageJ ROIs :param source_image_filename: Image that the ROIs are defined in :param destination_image_filename: Image in the destination coordinate space :param control_point_file: Transformation from source to destination :param output_filename: output filename for the resulting nifti file :param temp_output_filename: Temporary file for registration :param log_file_path: Path to save niftyreg logs :param error_file_path: Path to save niftyreg errors :param roi_reference_image: Image on which the ROIs are defined (if not the downsampled image in the registration directory) :param selem_size: Structure element size for closing :param nii_scale: Scaling to correctly save the temporary nifti image :param transformation_matrix: Affine transform for the temporary nifti image :param print_value_round_decimals: How many decimal places to round values printed to console. :param z_filter_padding: Size of the filter in z when correcting for unlabled slices. :param debug: If True, don't delete temporary files """ print("Loading ROIs") rois = read_roi_zip(roi_file) number_rois = len(rois) print(f"{number_rois} rois found") x = [] y = [] z = [] for key in rois: for position in range(0, len(rois[key]["x"])): x.append(rois[key]["x"][position]) y.append(rois[key]["y"][position]) z.append(rois[key]["position"]) print("Loading downsampled image image") downsampled_source_image = brainio.load_any(str(source_image_filename)) print(f"Source image size: " f"x:{downsampled_source_image.shape[0]}, " f"y:{downsampled_source_image.shape[1]}, " f"y:{downsampled_source_image.shape[2]}") downsampled_source_image[:] = 0 if roi_reference_image is not None: print("Reference image flag used. Loading reference image") reference_image_shape = brainio.get_size_image_from_file_paths( roi_reference_image) print(f"Reference image shape is " f"x:{reference_image_shape['x']}, " f"y:{reference_image_shape['y']}, " f"z:{reference_image_shape['z']}") x_downsample_factor = (reference_image_shape["x"] / downsampled_source_image.shape[0]) y_downsample_factor = (reference_image_shape["y"] / downsampled_source_image.shape[1]) z_downsample_factor = (reference_image_shape["z"] / downsampled_source_image.shape[2]) print(f"ROIs will be downsampled by a factor of " f"x:{round(x_downsample_factor, print_value_round_decimals)}, " f"y:{round(y_downsample_factor, print_value_round_decimals)}, " f"z:{round(z_downsample_factor, print_value_round_decimals)}") # TODO: optimise this print("Creating temporary ROI image") for position in range(0, len(x)): if roi_reference_image is None: downsampled_source_image[x[position], y[position], z[position]] = 1 else: x_scale = int(round(x[position] / x_downsample_factor)) y_scale = int(round(y[position] / y_downsample_factor)) z_scale = int(round(z[position] / z_downsample_factor)) downsampled_source_image[x_scale, y_scale, z_scale] = 1 print("Cleaning up ROI image") # TODO speed this up - parallelise? selem = morphology.selem.square(selem_size) for plane in tqdm(range(0, downsampled_source_image.shape[2])): tmp = morphology.binary.binary_closing(downsampled_source_image[:, :, plane], selem=selem) tmp = morphology.convex_hull_object(tmp) downsampled_source_image[:, :, plane] = morphology.binary.binary_closing( tmp, selem=selem) if roi_reference_image is not None: if z_downsample_factor < 1: print("ROI was defined at a lower z-resolution than the atlas. " "Correcting with a maximum filter") z_filter_size = int(round(1 / z_scale)) + z_filter_padding downsampled_source_image = maximum_filter1d( downsampled_source_image, z_filter_size, axis=2) print(f"Saving temporary ROI image at: {temp_output_filename}") brainio.to_nii( downsampled_source_image, str(temp_output_filename), scale=nii_scale, affine_transform=transformation_matrix, ) print("Preparing ROI registration") nifty_reg_binaries_folder = get_niftyreg_binaries() program_path = get_binary(nifty_reg_binaries_folder, PROGRAM_NAME) reg_cmd = prepare_segmentation_cmd( program_path, temp_output_filename, output_filename, destination_image_filename, control_point_file, ) print("Running ROI registration") try: safe_execute_command(reg_cmd, log_file_path, error_file_path) except SafeExecuteCommandError as err: raise RegistrationError("ROI registration failed; {}".format(err)) print(f"Registered ROI image can be found at {output_filename}") if not debug: print("Deleting temporary files") remove(temp_output_filename) remove(log_file_path) remove(error_file_path)