Esempio n. 1
0
    def register_freeform(self):
        """
        Performs freeform (elastic) registration of the average brain of the
        atlas to the sample brain using nifty_reg reg_f3d

        :return:
        :raises RegistrationError: If any error was detected during
            registration.
        """
        try:
            safe_execute_command(
                self._prepare_freeform_reg_cmd(),
                self.paths.freeform_log_file_path,
                self.paths.freeform_error_file_path,
            )
        except SafeExecuteCommandError as err:
            raise RegistrationError(
                "Freeform registration failed; {}".format(err)
            )
Esempio n. 2
0
    def register_affine(self):
        """
        Performs affine registration of the average brain of the atlas to the
        sample using nifty_reg reg_aladin

        :return:
        :raises RegistrationError: If any error was detected during
            registration.
        """
        try:
            safe_execute_command(
                self._prepare_affine_reg_cmd(),
                self.paths.affine_log_file_path,
                self.paths.affine_error_path,
            )
        except SafeExecuteCommandError as err:
            raise RegistrationError(
                "Affine registration failed; {}".format(err)
            )
    def register_inverse_freeform(self):
        """
        Performs freeform (elastic) registration of the sample to the
        atlas using nifty_reg reg_f3d

        :return:
        :raises RegistrationError: If any error was detected during
            registration.
        """
        logging.debug("Registering sample to atlas")

        try:
            safe_execute_command(
                self._prepare_inverse_freeform_reg_cmd(),
                self.paths.tmp__inverse_freeform_log_file_path,
                self.paths.tmp__inverse_freeform_error_file_path,
            )
        except SafeExecuteCommandError as err:
            raise RegistrationError(
                "Inverse freeform registration failed; {}".format(err))
    def generate_inverse_affine(self):
        """
        Inverts the affine transform to allow for quick registration of the
        sample onto the atlas
        :return:
        :raises RegistrationError: If any error was detected during
            registration.

        """
        logging.debug("Generating inverse affine transform")
        try:
            safe_execute_command(
                self._prepare_invert_affine_cmd(),
                self.paths.tmp__invert_affine_log_file,
                self.paths.tmp__invert_affine_error_file,
            )
        except SafeExecuteCommandError as err:
            raise RegistrationError(
                "Generation of inverted affine transform failed; "
                "{}".format(err))
Esempio n. 5
0
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)