def transform_image_to_standard_space( reg_dir, image_to_transform_fname="downsampled.nii", output_fname="background_channel_reg_to_filtered_brain.nii", log_file_path=None, error_file_path=None, ): reg_dir = Path(reg_dir) image_to_transform = reg_dir / image_to_transform_fname image_with_desired_coordinate_space = reg_dir / "brain_filtered.nii" control_point_file = reg_dir / "inverse_control_point_file.nii" output_path = reg_dir / output_fname nifty_reg_binaries_folder = ( imlib.source.niftyreg_binaries.get_niftyreg_binaries()) program_path = get_binary(nifty_reg_binaries_folder, PROGRAM_NAME) reg_cmd = get_registration_cmd( program_path, image_to_transform, output_path, image_with_desired_coordinate_space, control_point_file, ) if log_file_path is None: log_file_path = output_path.parent / "roi_transform_log.txt" if error_file_path is None: error_file_path = output_path.parent / "roi_transform_error.txt" safely_execute_amap_registration(error_file_path, log_file_path, reg_cmd) print(f"Registered ROI image can be found at {output_path}")
def prepare_transformation_cmd( floating_image_path, output_file_name, destination_image_filename, control_point_file, program_name="reg_resample", program_path=None, nifty_reg_binaries_folder=None, ): if program_path is None: if nifty_reg_binaries_folder is None: nifty_reg_binaries_folder = get_niftyreg_binaries() program_path = get_binary(nifty_reg_binaries_folder, program_name) cmd = "{} -cpp {} -flo {} -ref {} -res {}".format( program_path, control_point_file, floating_image_path, destination_image_filename, output_file_name, ) return cmd
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 """ 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)