예제 #1
0
    def from_slice(cls, slice_to_copy):
        slice = cls()

        if not isinstance(slice_to_copy, Slice):
            raise ValueError("Input must be of type Slice. Given: %s" %
                             type(slice_to_copy))

        # Copy image slice and mask
        slice.sitk = sitk.Image(slice_to_copy.sitk)
        slice.itk = sitkh.get_itk_from_sitk_image(slice.sitk)

        slice.sitk_mask = sitk.Image(slice_to_copy.sitk_mask)
        slice.itk_mask = sitkh.get_itk_from_sitk_image(slice.sitk_mask)

        slice._filename = slice_to_copy.get_filename()
        slice._slice_number = slice_to_copy.get_slice_number()
        slice._dir_input = slice_to_copy.get_directory()

        # slice._history_affine_transforms, slice._history_motion_corrections = slice_to_copy.get_registration_history()

        # Store current affine transform of image
        slice._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            slice.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of slice, and rigid motion estimates of slice
        #  obtained in the course of the registration/reconstruction process

        slice._history_affine_transforms, slice._history_motion_corrections = slice_to_copy.get_registration_history(
        )

        return slice
예제 #2
0
    def test_computation_point_physical_space_via_affine_transform(self):

        # Get indices with intensities greater than 0
        #  indices \in \R^{dim, N_points}
        indices = np.array(
            np.where(sitk.GetArrayFromImage(self.image_sitk)[::-1] > 0))
        N_points = indices.shape[1]

        # Get sitk affine transform from image first
        affine_transform_sitk = \
            sitkh.get_sitk_affine_transform_from_sitk_image(self.image_sitk)

        dim = self.image_sitk.GetDimension()
        A = np.array(affine_transform_sitk.GetMatrix()).reshape(dim, dim)
        t = np.array(affine_transform_sitk.GetTranslation()).reshape(3, 1)

        for i in range(0, N_points):
            index = indices[:, i].reshape(dim, 1)

            # Check Alignment
            self.assertEqual(
                np.around(np.linalg.norm(
                    (A.dot(index) + t).flatten() -
                    self.image_sitk.TransformIndexToPhysicalPoint(
                        index.flatten())),
                          decimals=self.accuracy), 0)
예제 #3
0
    def from_sitk_image(cls,
                        slice_sitk,
                        slice_number,
                        filename="unknown",
                        slice_sitk_mask=None):

        slice = cls()

        # Directory
        # dir_input = "/".join(filename.split("/")[0:-1]) + "/"

        # Filename without extension
        # filename = filename.split("/")[-1:][0].split(".")[0]

        slice._dir_input = None
        slice._filename = filename
        slice._slice_number = slice_number

        # Append stacks as SimpleITK and ITK Image objects
        slice.sitk = slice_sitk
        slice.itk = sitkh.get_itk_from_sitk_image(slice_sitk)

        # Append masks (if provided)
        if slice_sitk_mask is not None:
            slice.sitk_mask = slice_sitk_mask
            slice.itk_mask = sitkh.get_itk_from_sitk_image(slice_sitk_mask)
        else:
            slice.sitk_mask = slice._generate_identity_mask()
            slice.itk_mask = sitkh.get_itk_from_sitk_image(slice.sitk_mask)

        # slice._sitk_upsampled = None

        # HACK (for current Slice-to-Volume Registration)
        #  See class SliceToVolumeRegistration
        # slice._sitk_upsampled = slice._get_upsampled_isotropic_resolution_slice(slice_sitk)
        # slice._itk_upsampled = sitkh.get_itk_from_sitk_image(slice._sitk_upsampled)

        # if slice_sitk_mask is not None:
        #     slice._sitk_mask_upsampled = slice._get_upsampled_isotropic_resolution_slice(slice_sitk_mask)
        #     slice._itk_mask_upsampled = sitkh.get_itk_from_sitk_image(slice._sitk_mask_upsampled)
        # else:
        #     slice._sitk_mask_upsampled = None
        #     slice._itk_mask_upsampled = None

        # Store current affine transform of image
        slice._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            slice.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of slice, and rigid motion estimates of slice
        #  obtained in the course of the registration/reconstruction process
        slice._history_affine_transforms = []
        slice._history_affine_transforms.append(slice._affine_transform_sitk)

        slice._history_motion_corrections = []
        slice._history_motion_corrections.append(sitk.Euler3DTransform())

        return slice
예제 #4
0
    def from_filename(cls,
                      file_path,
                      slice_number,
                      slice_thickness,
                      file_path_mask=None,
                      verbose=False,
                      ):

        slice = cls()

        if not ph.file_exists(file_path):
            raise exceptions.FileNotExistent(file_path)

        slice._dir_input = os.path.dirname(file_path)
        slice._filename = os.path.basename(file_path).split(".")[0]
        slice._slice_number = slice_number
        slice._slice_thickness = slice_thickness

        # Append stacks as SimpleITK and ITK Image objects
        slice.sitk = sitkh.read_nifti_image_sitk(file_path, sitk.sitkFloat64)
        slice.itk = sitkh.get_itk_from_sitk_image(slice.sitk)

        # Append masks (if provided)
        if file_path_mask is None:
            slice.sitk_mask = slice._generate_identity_mask()
            if verbose:
                ph.print_info(
                    "Identity mask created for '%s'." % (file_path))

        else:
            if not ph.file_exists(file_path_mask):
                raise exceptions.FileNotExistent(file_path_mask)
            slice.sitk_mask = sitkh.read_nifti_image_sitk(
                file_path_mask, sitk.sitkUInt8)
            try:
                # ensure mask occupies the same physical space
                slice.sitk_mask.CopyInformation(slice.sitk)
            except RuntimeError as e:
                raise IOError(
                    "Given image and its mask do not occupy the same space: %s" %
                    e.message)

        slice.itk_mask = sitkh.get_itk_from_sitk_image(slice.sitk_mask)

        # Store current affine transform of image
        slice._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            slice.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of slice, and motion estimates of slice
        #  obtained in the course of the registration/reconstruction process
        slice._history_affine_transforms = []
        slice._history_affine_transforms.append(slice._affine_transform_sitk)

        slice._history_motion_corrections = []
        slice._history_motion_corrections.append(sitk.Euler3DTransform())

        return slice
예제 #5
0
    def from_filename(cls,
                      file_path,
                      slice_number,
                      file_path_mask=None,
                      verbose=False):

        slice = cls()

        if not ph.file_exists(file_path):
            raise exceptions.FileNotExistent(file_path)

        slice._dir_input = os.path.dirname(file_path)
        slice._filename = os.path.basename(file_path).split(".")[0]
        slice._slice_number = slice_number

        # Append stacks as SimpleITK and ITK Image objects
        slice.sitk = sitk.ReadImage(file_path, sitk.sitkFloat64)
        slice.itk = sitkh.get_itk_from_sitk_image(slice.sitk)

        # Append masks (if provided)
        if file_path_mask is None:
            slice.sitk_mask = slice._generate_identity_mask()
            if verbose:
                ph.print_info("Identity mask created for '%s'." % (file_path))

        else:
            if not ph.file_exists(file_path_mask):
                raise exceptions.FileNotExistent(file_path_mask)
            slice.sitk_mask = sitk.ReadImage(file_path_mask, sitk.sitkUInt8)

        slice.itk_mask = sitkh.get_itk_from_sitk_image(slice.sitk_mask)

        # Store current affine transform of image
        slice._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            slice.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of slice, and motion estimates of slice
        #  obtained in the course of the registration/reconstruction process
        slice._history_affine_transforms = []
        slice._history_affine_transforms.append(slice._affine_transform_sitk)

        slice._history_motion_corrections = []
        slice._history_motion_corrections.append(sitk.Euler3DTransform())

        return slice
예제 #6
0
    def test_get_sitk_affine_transform_from_sitk_direction_and_origin(self):

        origin = self.image_sitk.GetOrigin()
        direction = self.image_sitk.GetDirection()

        affine_transform_ref = sitkh.get_sitk_affine_transform_from_sitk_image(
            self.image_sitk)
        affine_transform = \
            sitkh.get_sitk_affine_transform_from_sitk_direction_and_origin(
                direction, origin, self.image_sitk)

        # Check Fixed Parameters
        self.assertEqual(np.around(np.linalg.norm(
            np.array(affine_transform_ref.GetFixedParameters()) -
            affine_transform.GetFixedParameters()), decimals=self.accuracy), 0)

        # Check Parameters
        self.assertEqual(np.around(np.linalg.norm(
            np.array(affine_transform_ref.GetParameters()) -
            affine_transform.GetParameters()), decimals=self.accuracy), 0)
예제 #7
0
    def test_get_sitk_affine_transform_from_sitk_image(self):

        # Get indices with intensities greater than 0
        #  indices \in \R^{dim, N_points}
        indices = np.array(
            np.where(sitk.GetArrayFromImage(self.image_sitk)[::-1] > 0))
        N_points = indices.shape[1]

        # Get sitk affine transform from image first (the way it is used in
        # slice.py)
        affine_transform_sitk = \
            sitkh.get_sitk_affine_transform_from_sitk_image(self.image_sitk)

        for i in range(0, N_points):
            index = [int(j) for j in indices[:, i]]

            # Check Alignment
            self.assertEqual(np.around(np.linalg.norm(np.array(
                affine_transform_sitk.TransformPoint(index)) -
                self.image_sitk.TransformIndexToPhysicalPoint(index)),
                decimals=self.accuracy), 0)
예제 #8
0
    def from_filename(
        cls,
        file_path,
        file_path_mask=None,
        extract_slices=True,
        verbose=False,
        slice_thickness=None,
    ):

        stack = cls()

        if not ph.file_exists(file_path):
            raise exceptions.FileNotExistent(file_path)

            path_to_directory = os.path.dirname(file_path)

        # Strip extension from filename and remove potentially included "."
        filename = [
            re.sub("." + ext, "", os.path.basename(file_path))
            for ext in ALLOWED_EXTENSIONS if file_path.endswith(ext)
        ][0]
        # filename = filename.replace(".", "p")

        stack._dir = os.path.dirname(file_path)
        stack._filename = filename

        # Append stacks as SimpleITK and ITK Image objects
        stack.sitk = sitkh.read_nifti_image_sitk(file_path, sitk.sitkFloat64)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        # Set slice thickness of acquisition
        if slice_thickness is None:
            stack._slice_thickness = stack.sitk.GetSpacing()[-1]
        else:
            stack._slice_thickness = slice_thickness

        # Append masks (either provided or binary mask)
        if file_path_mask is None:
            stack.sitk_mask = stack._generate_identity_mask()
            if verbose:
                ph.print_info("Identity mask created for '%s'." % (file_path))

        else:
            if not ph.file_exists(file_path_mask):
                raise exceptions.FileNotExistent(file_path_mask)
            stack.sitk_mask = sitkh.read_nifti_image_sitk(
                file_path_mask, sitk.sitkUInt8)
            try:
                # ensure masks occupy same physical space
                stack.sitk_mask.CopyInformation(stack.sitk)
            except RuntimeError as e:
                raise IOError(
                    "Given image and its mask do not occupy the same space: %s"
                    % e.message)
            stack._is_unity_mask = False

        # Append itk object
        stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)

        # Store current affine transform of image
        stack._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            stack.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of stack, and motion estimates of stack
        #  obtained in the course of the registration/reconstruction process
        stack._history_affine_transforms = []
        stack._history_affine_transforms.append(stack._affine_transform_sitk)

        stack._history_motion_corrections = []
        stack._history_motion_corrections.append(sitk.Euler3DTransform())

        # Extract all slices and their masks from the stack and store them
        if extract_slices:
            dimenson = stack.sitk.GetDimension()
            if dimenson == 3:
                stack._N_slices = stack.sitk.GetSize()[-1]
                stack._slices = stack._extract_slices(
                    slice_thickness=stack.get_slice_thickness())
            elif dimenson == 2:
                stack._N_slices = 1
                stack._slices = [stack.sitk[:, :]]
        else:
            stack._N_slices = 0
            stack._slices = None

        if verbose:
            ph.print_info(
                "Stack (image + mask) associated to '%s' successfully read." %
                (file_path))

        return stack
예제 #9
0
    def from_sitk_image(
        cls,
        image_sitk,
        slice_thickness,
        filename="unknown",
        image_sitk_mask=None,
        extract_slices=True,
        slice_numbers=None,
    ):
        stack = cls()

        # Explicit cast (+ creation of other image instance)
        stack.sitk = sitk.Cast(image_sitk, sitk.sitkFloat64)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        # Set slice thickness of acquisition
        if not ph.is_float(slice_thickness):
            raise ValueError("Slice thickness must be of type float")
        stack._slice_thickness = float(slice_thickness)

        stack._filename = filename
        stack._dir = None

        # Append masks (if provided)
        if image_sitk_mask is not None:
            stack.sitk_mask = sitk.Cast(image_sitk_mask, sitk.sitkUInt8)
            try:
                # ensure mask occupies the same physical space
                stack.sitk_mask.CopyInformation(stack.sitk)
            except RuntimeError as e:
                raise IOError(
                    "Given image and its mask do not occupy the same space: %s"
                    % e.message)
            stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
            if sitk.GetArrayFromImage(stack.sitk_mask).prod() == 1:
                stack._is_unity_mask = True
            else:
                stack._is_unity_mask = False
        else:
            stack.sitk_mask = stack._generate_identity_mask()
            stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
            stack._is_unity_mask = True

        # Extract all slices and their masks from the stack and store them
        if extract_slices:
            stack._N_slices = stack.sitk.GetSize()[-1]
            stack._slices = stack._extract_slices(
                slice_numbers=slice_numbers,
                slice_thickness=slice_thickness,
            )
        else:
            stack._N_slices = 0
            stack._slices = None

        # Store current affine transform of image
        stack._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            stack.sitk)

        stack._history_affine_transforms = []
        stack._history_affine_transforms.append(stack._affine_transform_sitk)

        stack._history_motion_corrections = []
        stack._history_motion_corrections.append(sitk.Euler3DTransform())

        return stack
예제 #10
0
    def from_slice_filenames(
        cls,
        dir_input,
        prefix_stack,
        suffix_mask=None,
        dic_slice_filenames=None,
        prefix_slice="_slice",
        slice_thickness=None,
    ):

        stack = cls()

        if dir_input[-1] is not "/":
            dir_input += "/"

        stack._dir = dir_input
        stack._filename = prefix_stack

        # Get 3D images
        stack.sitk = sitkh.read_nifti_image_sitk(
            dir_input + prefix_stack + ".nii.gz", sitk.sitkFloat64)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        # Store current affine transform of image
        stack._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            stack.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of stack, and motion estimates of stack
        #  obtained in the course of the registration/reconstruction process
        stack._history_affine_transforms = []
        stack._history_affine_transforms.append(stack._affine_transform_sitk)

        stack._history_motion_corrections = []
        stack._history_motion_corrections.append(sitk.Euler3DTransform())

        # Set slice thickness of acquisition
        if slice_thickness is None:
            stack._slice_thickness = float(stack.sitk.GetSpacing()[-1])
        else:
            stack._slice_thickness = float(slice_thickness)

        # Append masks (either provided or binary mask)
        if suffix_mask is not None and \
            os.path.isfile(dir_input +
                           prefix_stack + suffix_mask + ".nii.gz"):
            stack.sitk_mask = sitkh.read_nifti_image_sitk(
                dir_input + prefix_stack + suffix_mask + ".nii.gz",
                sitk.sitkUInt8)
            stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
            stack._is_unity_mask = False
        else:
            stack.sitk_mask = stack._generate_identity_mask()
            stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
            stack._is_unity_mask = True

        # Get slices
        if dic_slice_filenames is None:
            stack._N_slices = stack.sitk.GetDepth()
            stack._slices = [None] * stack._N_slices

            # Append slices as Slice objects
            for i in range(0, stack._N_slices):
                path_to_slice = os.path.join(
                    dir_input,
                    prefix_stack + prefix_slice + str(i) + ".nii.gz")
                path_to_slice_mask = os.path.join(
                    dir_input, prefix_stack + prefix_slice + str(i) +
                    suffix_mask + ".nii.gz")

                if ph.file_exists(path_to_slice_mask):
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice,
                        slice_number=i,
                        file_path_mask=path_to_slice_mask)
                else:
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice, slice_number=i)
        else:
            slice_numbers = sorted(dic_slice_filenames.keys())
            stack._N_slices = len(slice_numbers)
            stack._slices = [None] * stack._N_slices

            for i, slice_number in enumerate(slice_numbers):
                path_to_slice = os.path.join(
                    dir_input, dic_slice_filenames[slice_number] + ".nii.gz")
                path_to_slice_mask = os.path.join(
                    dir_input, dic_slice_filenames[slice_number] +
                    suffix_mask + ".nii.gz")

                if ph.file_exists(path_to_slice_mask):
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice,
                        slice_number=slice_number,
                        file_path_mask=path_to_slice_mask,
                        slice_thickness=stack.get_slice_thickness(),
                    )
                else:
                    stack._slices[i] = sl.Slice.from_filename(
                        file_path=path_to_slice,
                        slice_number=slice_number,
                        slice_thickness=stack.get_slice_thickness(),
                    )

        return stack
예제 #11
0
    def from_sitk_image(
        cls,
        slice_sitk,
        slice_number,
        slice_thickness,
        filename="unknown",
        slice_sitk_mask=None,
    ):

        slice = cls()

        # Directory
        # dir_input = "/".join(filename.split("/")[0:-1]) + "/"

        # Filename without extension
        # filename = filename.split("/")[-1:][0].split(".")[0]

        slice._dir_input = None
        slice._filename = filename
        slice._slice_number = slice_number
        slice._slice_thickness = slice_thickness

        # Explicit cast (+ creation of other image instance)
        slice.sitk = sitk.Cast(slice_sitk, sitk.sitkFloat64)
        slice.itk = sitkh.get_itk_from_sitk_image(slice.sitk)

        # Append masks (if provided)
        if slice_sitk_mask is not None:
            slice.sitk_mask = sitk.Cast(slice_sitk_mask, sitk.sitkUInt8)
            try:
                # ensure mask occupies the same physical space
                slice.sitk_mask.CopyInformation(slice.sitk)
            except RuntimeError as e:
                raise IOError(
                    "Given image and its mask do not occupy the same space: %s"
                    % e.message)
            slice.itk_mask = sitkh.get_itk_from_sitk_image(slice.sitk_mask)
        else:
            slice.sitk_mask = slice._generate_identity_mask()
            slice.itk_mask = sitkh.get_itk_from_sitk_image(slice.sitk_mask)

        # slice._sitk_upsampled = None

        # HACK (for current Slice-to-Volume Registration)
        #  See class SliceToVolumeRegistration
        # slice._sitk_upsampled = slice._get_upsampled_isotropic_resolution_slice(slice_sitk)
        # slice._itk_upsampled =
        # sitkh.get_itk_from_sitk_image(slice._sitk_upsampled)

        # if slice_sitk_mask is not None:
        #     slice._sitk_mask_upsampled = slice._get_upsampled_isotropic_resolution_slice(slice_sitk_mask)
        #     slice._itk_mask_upsampled = sitkh.get_itk_from_sitk_image(slice._sitk_mask_upsampled)
        # else:
        #     slice._sitk_mask_upsampled = None
        #     slice._itk_mask_upsampled = None

        # Store current affine transform of image
        slice._affine_transform_sitk = sitkh.get_sitk_affine_transform_from_sitk_image(
            slice.sitk)

        # Prepare history of affine transforms, i.e. encoded spatial
        #  position+orientation of slice, and rigid motion estimates of slice
        #  obtained in the course of the registration/reconstruction process
        slice._history_affine_transforms = []
        slice._history_affine_transforms.append(slice._affine_transform_sitk)

        slice._history_motion_corrections = []
        slice._history_motion_corrections.append(sitk.Euler3DTransform())

        return slice