Esempio n. 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
Esempio n. 2
0
    def from_stack(cls, stack_to_copy, filename=None):
        stack = cls()

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

        # Copy image stack and mask
        stack.sitk = sitk.Image(stack_to_copy.sitk)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        stack.sitk_mask = sitk.Image(stack_to_copy.sitk_mask)
        stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
        stack._is_unity_mask = stack_to_copy.is_unity_mask()

        if filename is None:
            stack._filename = stack_to_copy.get_filename()
        else:
            stack._filename = filename
        stack._dir = stack_to_copy.get_directory()

        # Extract all slices and their masks from the stack and store them if
        # given
        if stack_to_copy.get_slices() is not None:
            stack._N_slices = stack_to_copy.get_number_of_slices()
            stack._slices = [None]*stack._N_slices
            slices_to_copy = stack_to_copy.get_slices()

            for i in range(0, stack._N_slices):
                stack._slices[i] = sl.Slice.from_slice(slices_to_copy[i])
        else:
            stack._N_slices = 0
            stack._slices = None

        return stack
Esempio n. 3
0
    def from_sitk_image(cls,
                        image_sitk,
                        filename="unknown",
                        image_sitk_mask=None,
                        extract_slices=True):
        stack = cls()

        stack.sitk = sitk.Image(image_sitk)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        stack._filename = filename
        stack._dir = None

        # Append masks (if provided)
        if image_sitk_mask is not None:
            stack.sitk_mask = image_sitk_mask
            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()
        else:
            stack._N_slices = 0
            stack._slices = None

        return stack
Esempio n. 4
0
    def from_slices(cls, slices, stack_sitk=None, mask_sitk=None):

        stack = cls()

        stack._dir = slices[0].get_directory()
        stack._filename = slices[0].get_filename()

        if stack_sitk is None:
            stack.sitk = None
            stack.itk = None
        else:
            stack.sitk = stack_sitk
            stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        stack._N_slices = len(slices)
        stack._slices = slices

        # Append masks (if provided)
        if mask_sitk is not None:
            stack.sitk_mask = mask_sitk
            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

        return stack
Esempio n. 5
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
Esempio n. 6
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
Esempio n. 7
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
Esempio n. 8
0
    def from_stack(cls, stack_to_copy, filename=None):
        stack = cls()

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

        # Copy image stack and mask
        stack.sitk = sitk.Image(stack_to_copy.sitk)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        stack._slice_thickness = stack_to_copy.get_slice_thickness()

        stack.sitk_mask = sitk.Image(stack_to_copy.sitk_mask)
        stack.itk_mask = sitkh.get_itk_from_sitk_image(stack.sitk_mask)
        stack._is_unity_mask = stack_to_copy.is_unity_mask()

        if filename is None:
            stack._filename = stack_to_copy.get_filename()
        else:
            stack._filename = filename
        stack._dir = stack_to_copy.get_directory()
        stack._deleted_slices = stack_to_copy.get_deleted_slice_numbers()

        # Store current affine transform of image
        stack.set_registration_history(
            stack_to_copy.get_registration_history())

        # Extract all slices and their masks from the stack and store them if
        # given
        if stack_to_copy.get_slices() is not None:
            stack._N_slices = stack_to_copy.get_number_of_slices()
            stack._slices = [None] * stack._N_slices
            slices_to_copy = stack_to_copy.get_slices()

            for j, slice_j in enumerate(slices_to_copy):
                stack._slices[j] = sl.Slice.from_slice(slice_j)
        else:
            stack._N_slices = 0
            stack._slices = None

        return stack
Esempio n. 9
0
    def setUp(self):

        self.accuracy = 10

        # ----------------------------------2D---------------------------------
        self.fixed_sitk_2D = sitk.ReadImage(
            os.path.join(DIR_DATA, "2D_Brain_Target.png"), sitk.sitkFloat64)
        self.moving_sitk_2D = sitk.ReadImage(
            os.path.join(DIR_DATA, "2D_Brain_Source.png"), sitk.sitkFloat64)

        self.fixed_sitk_mask_2D = sitk.ReadImage(
            os.path.join(DIR_DATA, "2D_Brain_Target_mask.png"), sitk.sitkUInt8)
        self.moving_sitk_mask_2D = sitk.ReadImage(
            os.path.join(DIR_DATA, "2D_Brain_Source_mask.png"), sitk.sitkUInt8)

        self.fixed_itk_2D = sitkh.get_itk_from_sitk_image(self.fixed_sitk_2D)
        self.moving_itk_2D = sitkh.get_itk_from_sitk_image(self.moving_sitk_2D)
        self.fixed_itk_mask_2D = sitkh.get_itk_from_sitk_image(
            self.fixed_sitk_mask_2D)
        self.moving_itk_mask_2D = sitkh.get_itk_from_sitk_image(
            self.moving_sitk_mask_2D)

        # ---------------------------------3D----------------------------------
        self.fixed_sitk_3D = sitk.ReadImage(
            os.path.join(DIR_DATA, "3D_Brain_Source.nii.gz"))

        self.moving_sitk_3D = sitk.ReadImage(
            os.path.join(DIR_DATA, "3D_Brain_Target.nii.gz"))

        self.fixed_itk_3D = sitkh.get_itk_from_sitk_image(self.fixed_sitk_3D)
        self.moving_itk_3D = sitkh.get_itk_from_sitk_image(self.moving_sitk_3D)
Esempio n. 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)

        # 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 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
Esempio n. 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
Esempio n. 12
0
    def from_filename(cls,
                      file_path,
                      file_path_mask=None,
                      extract_slices=True,
                      verbose=False):

        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 = sitk.ReadImage(file_path, sitk.sitkFloat64)
        stack.itk = sitkh.get_itk_from_sitk_image(stack.sitk)

        # 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 = sitk.ReadImage(file_path_mask, sitk.sitkUInt8)
            stack._is_unity_mask = False

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

        # 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()
            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
Esempio n. 13
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
Esempio n. 14
0
    def _run_discrete_shepard_reconstruction(self):

        shape = sitk.GetArrayFromImage(self._HR_volume.sitk).shape
        helper_N_nda = np.zeros(shape)
        helper_D_nda = np.zeros(shape)

        default_pixel_value = 0.0

        for i in range(0, self._N_stacks):
            if self._verbose:
                ph.print_info("Stack %s/%s" % (i + 1, self._N_stacks))
            stack = self._stacks[i]
            slices = stack.get_slices()
            N_slices = stack.get_number_of_slices()

            # for j in range(10, 11):
            for j in range(0, N_slices):
                # print("\t\tSlice %s/%s" %(j,N_slices-1))
                slice = slices[j]
                slice_sitk = self._get_slice[(bool(self._use_masks),
                                              bool(self._sda_mask))](slice)

                # Add intensity offset so that a "zero" intensity can be
                # identified as contribution of image slice (line 353/356)
                slice_sitk += 1

                # Nearest neighbour resampling of slice to target space (HR
                # volume)
                slice_resampled_sitk = sitk.Resample(
                    slice_sitk, self._HR_volume.sitk, sitk.Euler3DTransform(),
                    sitk.sitkNearestNeighbor, default_pixel_value,
                    self._HR_volume.sitk.GetPixelIDValue())

                # sitkh.show_sitk_image(slice_resampled_sitk)

                # Extract array of pixel intensities
                nda_slice = sitk.GetArrayFromImage(slice_resampled_sitk)

                # Get voxels in HR volume space which are struck by the slice
                ind_nonzero = nda_slice > 0

                # update numerator (correct previous intensity offset)
                helper_N_nda[ind_nonzero] += nda_slice[ind_nonzero] - 1

                # update denominator
                helper_D_nda[ind_nonzero] += 1

                # test = sitk.GetImageFromArray(helper_N_nda)
                # sitkh.show_sitk_image(test,title="N")

                # test = sitk.GetImageFromArray(helper_D_nda)
                # sitkh.show_sitk_image(test,title="D")

                # print("helper_N_nda: (min, max) = (%s, %s)" %(np.min(helper_N_nda), np.max(helper_N_nda)))
                # print("helper_D_nda: (min, max) = (%s, %s)" %(np.min(helper_D_nda), np.max(helper_D_nda)))

        # TODO: Set zero entries to one; Otherwise results are very weird!?
        helper_D_nda[helper_D_nda == 0] = 1

        # Create itk-images with correct header data
        pixel_type = itk.D
        dimension = 3
        image_type = itk.Image[pixel_type, dimension]

        itk2np = itk.PyBuffer[image_type]
        helper_N = itk2np.GetImageFromArray(helper_N_nda)
        helper_D = itk2np.GetImageFromArray(helper_D_nda)

        helper_N.SetSpacing(self._HR_volume.sitk.GetSpacing())
        helper_N.SetDirection(
            sitkh.get_itk_direction_from_sitk_image(self._HR_volume.sitk))
        helper_N.SetOrigin(self._HR_volume.sitk.GetOrigin())

        helper_D.SetSpacing(self._HR_volume.sitk.GetSpacing())
        helper_D.SetDirection(
            sitkh.get_itk_direction_from_sitk_image(self._HR_volume.sitk))
        helper_D.SetOrigin(self._HR_volume.sitk.GetOrigin())

        # Apply Recursive Gaussian YVV filter
        gaussian = itk.SmoothingRecursiveYvvGaussianImageFilter[
            image_type, image_type].New()  # YVV-based Filter
        # gaussian = itk.SmoothingRecursiveGaussianImageFilter[image_type,
        # image_type].New()    # Deriche-based Filter
        gaussian.SetSigmaArray(self._sigma_array)
        gaussian.SetInput(helper_N)
        gaussian.Update()
        HR_volume_update_N = gaussian.GetOutput()
        HR_volume_update_N.DisconnectPipeline()

        gaussian.SetInput(helper_D)
        gaussian.Update()
        HR_volume_update_D = gaussian.GetOutput()
        HR_volume_update_D.DisconnectPipeline()

        # Convert numerator and denominator back to data array
        nda_N = itk2np.GetArrayFromImage(HR_volume_update_N)
        nda_D = itk2np.GetArrayFromImage(HR_volume_update_D)

        # Compute data array of HR volume:
        # nda_D[nda_D==0]=1
        nda = nda_N / nda_D.astype(float)

        # Update HR volume image file within Stack-object HR_volume
        HR_volume_update = sitk.GetImageFromArray(nda)
        HR_volume_update.CopyInformation(self._HR_volume.sitk)

        if not self._sda_mask:
            self._HR_volume.sitk = HR_volume_update
            self._HR_volume.itk = sitkh.get_itk_from_sitk_image(
                HR_volume_update)
        else:
            # Approximate uint8 mask from float SDA outcome
            mask_estimator = bm.BinaryMaskFromMaskSRREstimator(
                HR_volume_update)
            mask_estimator.run()
            HR_volume_update = mask_estimator.get_mask_sitk()

            self._HR_volume.sitk_mask = HR_volume_update
            self._HR_volume.itk_mask = sitkh.get_itk_from_sitk_image(
                HR_volume_update)
Esempio n. 15
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
Esempio n. 16
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
Esempio n. 17
0
    def _run_discrete_shepard_based_on_Deriche_reconstruction(self):

        shape = sitk.GetArrayFromImage(self._HR_volume.sitk).shape
        helper_N_nda = np.zeros(shape)
        helper_D_nda = np.zeros(shape)

        default_pixel_value = 0.0

        for i in range(0, self._N_stacks):
            if self._verbose:
                ph.print_info("Stack %s/%s" % (i + 1, self._N_stacks))
            stack = self._stacks[i]
            slices = stack.get_slices()
            N_slices = stack.get_number_of_slices()

            for j in range(0, N_slices):

                slice = slices[j]
                slice_sitk = self._get_slice[(bool(self._use_masks),
                                              bool(self._sda_mask))](slice)

                # Nearest neighbour resampling of slice to target space (HR
                # volume)
                slice_resampled_sitk = sitk.Resample(
                    slice_sitk, self._HR_volume.sitk, sitk.Euler3DTransform(),
                    sitk.sitkNearestNeighbor, default_pixel_value,
                    self._HR_volume.sitk.GetPixelIDValue())

                # Extract array of pixel intensities
                nda_slice = sitk.GetArrayFromImage(slice_resampled_sitk)

                # Look for indices which are stroke by the slice in the
                # isotropic grid
                ind_nonzero = nda_slice > 0

                # update arrays of numerator and denominator
                helper_N_nda[ind_nonzero] += nda_slice[ind_nonzero]
                helper_D_nda[ind_nonzero] += 1

                # print("helper_N_nda: (min, max) = (%s, %s)" %(np.min(helper_N_nda), np.max(helper_N_nda)))
                # print("helper_D_nda: (min, max) = (%s, %s)" %(np.min(helper_D_nda), np.max(helper_D_nda)))

        # TODO: Set zero entries to one; Otherwise results are very weird!?
        helper_D_nda[helper_D_nda == 0] = 1

        # Create sitk-images with correct header data
        helper_N = sitk.GetImageFromArray(helper_N_nda)
        helper_D = sitk.GetImageFromArray(helper_D_nda)

        helper_N.CopyInformation(self._HR_volume.sitk)
        helper_D.CopyInformation(self._HR_volume.sitk)

        # Apply recursive Gaussian smoothing
        gaussian = sitk.SmoothingRecursiveGaussianImageFilter()
        gaussian.SetSigma(self._sigma_array[1])

        HR_volume_update_N = gaussian.Execute(helper_N)
        HR_volume_update_D = gaussian.Execute(helper_D)

        # ## Avoid undefined division by zero
        # """
        # HACK start
        # """
        # ## HACK for denominator
        # nda = sitk.GetArrayFromImage(HR_volume_update_D)
        # ind_min = np.unravel_index(np.argmin(nda), nda.shape)
        # # print(nda[nda<0])
        # # print(nda[ind_min])

        # eps = 1e-8
        # # nda[nda<=eps]=1
        # print("denominator min = %s" % np.min(nda))

        # HR_volume_update_D = sitk.GetImageFromArray(nda)
        # HR_volume_update_D.CopyInformation(self._HR_volume.sitk)

        # ## HACK for numerator given that some intensities are negative!?
        # nda = sitk.GetArrayFromImage(HR_volume_update_N)
        # ind_min = np.unravel_index(np.argmin(nda), nda.shape)
        # # nda[nda<=eps]=0
        # # print(nda[nda<0])
        # print("numerator min = %s" % np.min(nda))
        # """
        # HACK end
        # """

        # Compute HR volume based on scattered data approximation with correct
        # header (might be redundant):
        HR_volume_update = HR_volume_update_N / HR_volume_update_D
        HR_volume_update.CopyInformation(self._HR_volume.sitk)

        if not self._sda_mask:
            self._HR_volume.sitk = HR_volume_update
            self._HR_volume.itk = sitkh.get_itk_from_sitk_image(
                HR_volume_update)
        else:
            # Approximate uint8 mask from float SDA outcome
            mask_estimator = bm.BinaryMaskFromMaskSRREstimator(
                HR_volume_update)
            mask_estimator.run()
            HR_volume_update = mask_estimator.get_mask_sitk()

            self._HR_volume.sitk_mask = HR_volume_update
            self._HR_volume.itk_mask = sitkh.get_itk_from_sitk_image(
                HR_volume_update)
        """
        Additional info
        """
        if self._verbose:
            nda = sitk.GetArrayFromImage(HR_volume_update)
            print("Minimum of data array = %s" % np.min(nda))