Source code for pyradise.process.orientation
from enum import Enum
from typing import Optional, Union
import SimpleITK as sitk
from pyradise.data import (IntensityImage, SegmentationImage, Subject,
TransformInfo)
from .base import Filter, FilterParams
__all_ = ["OrientationFilterParameters", "OrientationFilter", "SpatialOrientation"]
class _Coord(Enum):
"""An enum class containing all available medical directions to build the :class:`SpatialOrientation` entries."""
ITK_COORDINATE_UNKNOWN = 0
"""Default value for a unidentifiable coordinate direction."""
RIGHT = 2
"""Coordinate direction right."""
LEFT = 3
"""Coordinate direction left."""
POSTERIOR = 4 # back
"""Coordinate direction posterior."""
ANTERIOR = 5 # front
"""Coordinate direction anterior."""
INFERIOR = 8 # below
"""Coordinate direction inferior."""
SUPERIOR = 9 # above
"""Coordinate direction superior."""
class _MajorTerms(Enum):
"""An enum class for the possible axes within an image to describe the orientation. This enum is used to build
the :class:`SpatialOrientation`"""
PRIMARY_MINOR = 0
"""The primary minor axis."""
SECONDARY_MINOR = 8
"""The secondary minor axis."""
TERTIARY_MINOR = 16
"""The tertiary minor axis."""
[docs]class SpatialOrientation(Enum):
"""An enum class for all possible medical image orientations an image can possess."""
INVALID = _Coord.ITK_COORDINATE_UNKNOWN
"""The default value for an unidentifiable image orientation."""
RIP = (
(_Coord.RIGHT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The right inferior posterior (RIP) orientation."""
LIP = (
(_Coord.LEFT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The left inferior posterior (LIP) orientation."""
RSP = (
(_Coord.RIGHT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The right superior posterior (RSP) orientation."""
LSP = (
(_Coord.LEFT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The left superior posterior (LSP) orientation."""
RIA = (
(_Coord.RIGHT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The right inferior anterior (RIA) orientation."""
LIA = (
(_Coord.LEFT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The left inferior anterior (LIA) orientation."""
RSA = (
(_Coord.RIGHT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The right superior anterior (RSA) orientation."""
LSA = (
(_Coord.LEFT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The left superior anterior (LSA) orientation."""
IRP = (
(_Coord.INFERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The inferior right posterior (IRP) orientation."""
ILP = (
(_Coord.INFERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The inferior left posterior (ILP) orientation."""
SRP = (
(_Coord.SUPERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The superior right posterior (SRP) orientation."""
SLP = (
(_Coord.SUPERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The superior left posterior (SLP) orientation."""
IRA = (
(_Coord.INFERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The inferior right anterior (IRA) orientation."""
ILA = (
(_Coord.INFERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The inferior left anterior (ILA) orientation."""
SRA = (
(_Coord.SUPERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The superior right anterior (SRA) orientation."""
SLA = (
(_Coord.SUPERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The superior left anterior (SLA) orientation."""
RPI = (
(_Coord.RIGHT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The right posterior inferior (RPI) orientation."""
LPI = (
(_Coord.LEFT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The left posterior inferior (LPI) orientation."""
RAI = (
(_Coord.RIGHT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The right anterior inferior (RAI) orientation."""
LAI = (
(_Coord.LEFT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The left anterior inferior (LAI) orientation."""
RPS = (
(_Coord.RIGHT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The right posterior superior (RPS) orientation."""
LPS = (
(_Coord.LEFT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The left posterior superior (LPS) orientation."""
RAS = (
(_Coord.RIGHT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The right anterior superior (RAS) orientation."""
LAS = (
(_Coord.LEFT.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The left anterior superior (LAS) orientation."""
PRI = (
(_Coord.POSTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The posterior right inferior (PRI) orientation."""
PLI = (
(_Coord.POSTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The posterior left inferior (PLI) orientation."""
ARI = (
(_Coord.ANTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The anterior right inferior (ARI) orientation."""
ALI = (
(_Coord.ANTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The anterior left inferior (ALI) orientation."""
PRS = (
(_Coord.POSTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The posterior right superior (PRS) orientation."""
PLS = (
(_Coord.POSTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The posterior left superior (PLS) orientation."""
ARS = (
(_Coord.ANTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The anterior right superior (ARS) orientation."""
ALS = (
(_Coord.ANTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The anterior left superior (ALS) orientation."""
IPR = (
(_Coord.INFERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The inferior posterior right (IPR) orientation."""
SPR = (
(_Coord.SUPERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The superior posterior right (SPR) orientation."""
IAR = (
(_Coord.INFERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The inferior anterior right (IAR) orientation."""
SAR = (
(_Coord.SUPERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The superior anterior right (SAR) orientation."""
IPL = (
(_Coord.INFERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The inferior posterior left (IPL) orientation."""
SPL = (
(_Coord.SUPERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.POSTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The superior posterior left (SPL) orientation."""
IAL = (
(_Coord.INFERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The inferior anterior left (IAL) orientation."""
SAL = (
(_Coord.SUPERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.ANTERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The superior anterior left (SAL) orientation."""
PIR = (
(_Coord.POSTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The posterior inferior right (PIR) orientation."""
PSR = (
(_Coord.POSTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The posterior superior right (PSR) orientation."""
AIR = (
(_Coord.ANTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The anterior inferior right (AIR) orientation."""
ASR = (
(_Coord.ANTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.RIGHT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The anterior superior right (ASR) orientation."""
PIL = (
(_Coord.POSTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The posterior inferior left (PIL) orientation."""
PSL = (
(_Coord.POSTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The posterior superior left (PSL) orientation."""
AIL = (
(_Coord.ANTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.INFERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The anterior inferior left (AIL) orientation."""
ASL = (
(_Coord.ANTERIOR.value << _MajorTerms.PRIMARY_MINOR.value)
+ (_Coord.SUPERIOR.value << _MajorTerms.SECONDARY_MINOR.value)
+ (_Coord.LEFT.value << _MajorTerms.TERTIARY_MINOR.value)
)
"""The anterior superior left (ASL) orientation."""
# pylint: disable = too-few-public-methods
[docs]class OrientationFilterParams(FilterParams):
"""A filter parameter class for the :class:`~pyradise.process.orientation.OrientationFilter`.
The orientation is a string or :class:`~pyradise.process.orientation.SpatialOrientation` value consisting of three
characters. These three characters describe the orientation of the image with the following values:
* ``I``: Inferior
* ``S``: Superior
* ``A``: Anterior
* ``P``: Posterior
* ``R``: Right
* ``L``: Left
The orientation of the image is described by the order of the characters. The first character describes the primary
orientation of patient in the positive x-axis direction. The second character describes the secondary orientation of
patient in the positive y-axis direction. The third character describes the tertiary orientation of patient in the
positive z-axis direction. For example, the orientation ``RAS`` means that the patient is facing right in the
positive x-axis direction, facing anterior in the positive y-axis direction, and facing superior in the positive
z-axis direction. For more details we refer to appropriate literature (e.g.
`website <http://www.grahamwideman.com/gw/brain/orientation/orientterms.htm>`_).
Args:
output_orientation (Union[SpatialOrientation, str]): The desired output orientation of all provided images.
"""
def __init__(self, output_orientation: Union[SpatialOrientation, str]) -> None:
super().__init__()
if isinstance(output_orientation, str):
try:
self.output_orientation: SpatialOrientation = SpatialOrientation[output_orientation]
except KeyError:
raise ValueError(f"Invalid output orientation: {output_orientation}")
else:
self.output_orientation: SpatialOrientation = output_orientation
[docs]class OrientationFilter(Filter):
"""A filter class for reorienting all :class:`~pyradise.data.image.Image` instances of a
:class:`~pyradise.data.subject.Subject` instance to a specified
:class:`~pyradise.process.orientation.SpatialOrientation`.
"""
[docs] @staticmethod
def is_invertible() -> bool:
"""Returns whether the filter is invertible or not.
Returns:
bool: True because the reorientation of images is invertible.
"""
return True
[docs] def execute(self, subject: Subject, params: OrientationFilterParams) -> Subject:
"""Execute the image reorientation procedure.
Args:
subject (Subject): The :class:`~pyradise.data.subject.Subject` instance to be processed.
params (OrientationFilterParams): The filters parameters.
Returns:
Subject: The :class:`~pyradise.data.subject.Subject` instance with oriented
:class:`~pyradise.data.image.IntensityImage` and :class:`~pyradise.data.image.SegmentationImage` instances.
"""
for image in subject.get_images():
# get the image data as SimpleITK image
sitk_image = image.get_image_data()
# reorient the image
orient_filter = sitk.DICOMOrientImageFilter()
orient_filter.SetDesiredCoordinateOrientation(params.output_orientation.name)
oriented_sitk_image = orient_filter.Execute(sitk_image)
# set the oriented image data to the image
image.set_image_data(oriented_sitk_image)
# track the necessary information
pre_orientation = orient_filter.GetOrientationFromDirectionCosines(sitk_image.GetDirection())
self.tracking_data["original_orientation"] = pre_orientation
self._register_tracked_data(image, sitk_image, oriented_sitk_image, params)
return subject
[docs] def execute_inverse(
self,
subject: Subject,
transform_info: TransformInfo,
target_image: Optional[Union[SegmentationImage, IntensityImage]] = None,
) -> Subject:
"""Execute the inverse image reorientation procedure.
Args:
subject (Subject): The :class:`~pyradise.data.subject.Subject` instance to be processed.
transform_info (TransformInfo): The :class:`~pyradise.data.taping.TransformInfo` instance.
target_image (Optional[Union[SegmentationImage, IntensityImage]]): The target image to which the inverse
transformation should be applied. If None, the inverse transformation is applied to all images (default:
None).
Returns:
Subject: The :class:`~pyradise.data.subject.Subject` instance with reoriented
:class:`~pyradise.data.image.IntensityImage` and :class:`~pyradise.data.image.SegmentationImage` instances.
"""
for image in subject.get_images():
if target_image is not None and image != target_image:
continue
# get the original orientation
original_orient = transform_info.get_data("original_orientation")
# reorient the image
orient_filter = sitk.DICOMOrientImageFilter()
orient_filter.SetDesiredCoordinateOrientation(original_orient)
oriented_sitk_image = orient_filter.Execute(image.get_image_data())
# set the oriented image data to the image
image.set_image_data(oriented_sitk_image)
return subject