Skip to content

Commit

Permalink
Merge pull request #18 from MGHComputationalPathology/feature/even_mo…
Browse files Browse the repository at this point in the history
…re_seg_tests

Feature/even more seg tests
  • Loading branch information
hackermd committed Feb 26, 2020
2 parents 1345459 + 3cb3d6b commit 6678bde
Show file tree
Hide file tree
Showing 15 changed files with 590 additions and 339 deletions.
2 changes: 2 additions & 0 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Derive a Segmentation image from a series of single-frame Computed Tomography
sop_instance_uid=generate_uid(),
instance_number=1,
manufacturer='Manufacturer',
manufacturer_model_name='Model',
software_versions='v1',
device_serial_number='Device XYZ',
manufacturer_model_name='The best one'
Expand Down Expand Up @@ -147,6 +148,7 @@ Derive a Segmentation image from a multi-frame Slide Microscopy (SM) image:
sop_instance_uid=generate_uid(),
instance_number=1,
manufacturer='Manufacturer',
manufacturer_model_name='Model',
software_versions='v1',
device_serial_number='Device XYZ'
)
Expand Down
6 changes: 4 additions & 2 deletions src/highdicom/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from pydicom.valuerep import DA, DT, TM

from highdicom.sr.coding import CodingSchemeIdentificationItem
from highdicom.enum import ContentQualifications
from highdicom.enum import ContentQualificationValues
from highdicom.version import __version__
from highdicom._iods import IOD_MODULE_MAP
from highdicom._modules import MODULE_ATTRIBUTE_MAP
Expand Down Expand Up @@ -174,7 +174,9 @@ def __init__(
self.ContentDate = DA(datetime.now().date())
self.ContentTime = TM(datetime.now().time())
if content_qualification is not None:
content_qualification = ContentQualifications(content_qualification)
content_qualification = ContentQualificationValues(
content_qualification
)
self.ContentQualification = content_qualification.value
if coding_schemes is not None:
self.CodingSchemeIdentificationSequence = []
Expand Down
9 changes: 4 additions & 5 deletions src/highdicom/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@

from highdicom.enum import (
CoordinateSystemNames,
UniversalEntityIDTypes,
UniversalEntityIDTypeValues,
)
from highdicom.seg.enum import SegmentAlgorithmTypes
from highdicom.sr.coding import CodedConcept
from highdicom.sr.value_types import (
CodeContentItem,
Expand Down Expand Up @@ -277,15 +276,15 @@ def __init__(
self,
issuer_of_identifier: str,
issuer_of_identifier_type: Optional[
Union[str, UniversalEntityIDTypes]
Union[str, UniversalEntityIDTypeValues]
] = None
):
"""
Parameters
----------
issuer_of_identifier: str
Identifier of the entity that created the examined specimen
issuer_of_identifier_type: Union[str, highdicom.enum.UniversalEntityIDTypes], optional
issuer_of_identifier_type: Union[str, highdicom.enum.UniversalEntityIDTypeValues], optional
Type of identifier of the entity that created the examined specimen
(required if `issuer_of_specimen_id` is a Unique Entity ID)
Expand All @@ -295,7 +294,7 @@ def __init__(
self.LocalNamespaceEntityID = issuer_of_identifier
else:
self.UniversalEntityID = issuer_of_identifier
issuer_of_identifier_type = UniversalEntityIDTypes(
issuer_of_identifier_type = UniversalEntityIDTypeValues(
issuer_of_identifier_type
)
self.UniversalEntityIDType = issuer_of_identifier_type.value
Expand Down
16 changes: 8 additions & 8 deletions src/highdicom/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class CoordinateSystemNames(Enum):
SLIDE = 'SLIDE'


class ContentQualifications(Enum):
class ContentQualificationValues(Enum):

"""Enumerated values for Content Qualification attribute."""

Expand All @@ -19,7 +19,7 @@ class ContentQualifications(Enum):
SERVICE = 'SERVICE'


class DimensionOrganizationTypes(Enum):
class DimensionOrganizationTypeValues(Enum):

"""Enumerated values for Dimension Organization Type attribute."""

Expand All @@ -29,7 +29,7 @@ class DimensionOrganizationTypes(Enum):
TILED_SPARSE = 'TILED_SPARSE'


class PhotometricInterpretations(Enum):
class PhotometricInterpretationValues(Enum):

"""Enumerated values for Photometric Interpretation attribute."""

Expand All @@ -44,23 +44,23 @@ class PhotometricInterpretations(Enum):
YBR_RCT = 'YBR_RCT'


class Lateralities(Enum):
class LateralityValues(Enum):

"""Enumerated values for Laterality attribute."""

R = 'R'
L = 'L'


class AnatomicalOrientationTypes(Enum):
class AnatomicalOrientationTypeValues(Enum):

"""Enumerated values for Anatomical Orientation Type attribute."""

BIPED = 'BIPED'
QUADRUPED = 'QUADRUPED'


class PatientOrientationsBiped(Enum):
class PatientOrientationValuesBiped(Enum):

"""Enumerated values for Patient Orientation attribute
if Anatomical Orientation Type attribute has value ``"BIPED"``.
Expand All @@ -74,7 +74,7 @@ class PatientOrientationsBiped(Enum):
F = 'F'


class PatientOrientationsQuadruped(Enum):
class PatientOrientationValuesQuadruped(Enum):

"""Enumerated values for Patient Orientation attribute
if Anatomical Orientation Type attribute has value ``"QUADRUPED"``.
Expand All @@ -95,7 +95,7 @@ class PatientOrientationsQuadruped(Enum):
PL = 'PL'


class UniversalEntityIDTypes(Enum):
class UniversalEntityIDTypeValues(Enum):

"""Enumerated values for Universal Entity ID Type attribute."""

Expand Down
2 changes: 1 addition & 1 deletion src/highdicom/sc/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from enum import Enum


class ConversionTypes(Enum):
class ConversionTypeValues(Enum):

"""Enumerated values for attribute Conversion Type."""

Expand Down
73 changes: 41 additions & 32 deletions src/highdicom/sc/sop.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
SpecimenDescription,
)
from highdicom.enum import (
AnatomicalOrientationTypes,
AnatomicalOrientationTypeValues,
CoordinateSystemNames,
Lateralities,
PhotometricInterpretations,
PatientOrientationsBiped,
PatientOrientationsQuadruped,
LateralityValues,
PhotometricInterpretationValues,
PatientOrientationValuesBiped,
PatientOrientationValuesQuadruped,
)
from highdicom.sc.enum import ConversionTypes
from highdicom.sc.enum import ConversionTypeValues
from highdicom.sr.coding import CodedConcept


Expand All @@ -38,7 +38,10 @@ class SCImage(SOPClass):
def __init__(
self,
pixel_array: np.ndarray,
photometric_interpretation: Union[str, PhotometricInterpretations],
photometric_interpretation: Union[
str,
PhotometricInterpretationValues
],
bits_allocated: int,
coordinate_system: Union[str, CoordinateSystemNames],
study_instance_uid: str,
Expand All @@ -57,19 +60,22 @@ def __init__(
study_time: Optional[Union[str, datetime.time]] = None,
referring_physician_name: Optional[str] = None,
pixel_spacing: Optional[Tuple[int, int]] = None,
laterality: Optional[Union[str, Lateralities]] = None,
laterality: Optional[Union[str, LateralityValues]] = None,
patient_orientation: Optional[
Union[
Tuple[str, str],
Tuple[PatientOrientationsBiped, PatientOrientationsBiped],
Tuple[
PatientOrientationsQuadruped,
PatientOrientationsQuadruped,
PatientOrientationValuesBiped,
PatientOrientationValuesBiped,
],
Tuple[
PatientOrientationValuesQuadruped,
PatientOrientationValuesQuadruped,
]
]
] = None,
anatomical_orientation_type: Optional[
Union[str, AnatomicalOrientationTypes]
Union[str, AnatomicalOrientationTypeValues]
] = None,
container_identifier: Optional[str] = None,
issuer_of_container_identifier: Optional[IssuerOfIdentifier] = None,
Expand All @@ -86,7 +92,7 @@ def __init__(
Array of unsigned integer pixel values representing a single-frame
image; either a 2D grayscale image or a 3D color image
(RGB color space)
photometric_interpretation: Union[str, highdicom.enum.PhotometricInterpretations]
photometric_interpretation: Union[str, highdicom.enum.PhotometricInterpretationValues]
Interpretation of pixel data; either ``"MONOCHROME1"`` or
``"MONOCHROME2"`` for 2D grayscale images or ``"RGB"`` or
``"YBR_FULL"`` for 3D color images
Expand Down Expand Up @@ -130,14 +136,14 @@ def __init__(
pixel_spacing: Tuple[int, int], optional
Physical spacing in millimeter between pixels along the row and
column dimension
laterality: Union[str, highdicom.enum.Lateralities], optional
laterality: Union[str, highdicom.enum.LateralityValues], optional
Laterality of the examined body part (required if
`coordinate_system` is ``"PATIENT"``)
patient_orientation:
Union[Tuple[str, str], Tuple[highdicom.enum.PatientOrientationsBiped, highdicom.enum.PatientOrientationsBiped], Tuple[highdicom.enum.PatientOrientationsQuadruped, highdicom.enum.PatientOrientationsQuadruped]], optional
Union[Tuple[str, str], Tuple[highdicom.enum.PatientOrientationValuesBiped, highdicom.enum.PatientOrientationValuesBiped], Tuple[highdicom.enum.PatientOrientationValuesQuadruped, highdicom.enum.PatientOrientationValuesQuadruped]], optional
Orientation of the patient along the row and column axes of the
image (required if `coordinate_system` is ``"PATIENT"``)
anatomical_orientation_type: Union[str, highdicom.enum.AnatomicalOrientationTypes], optional
anatomical_orientation_type: Union[str, highdicom.enum.AnatomicalOrientationTypeValues], optional
Type of anatomical orientation of patient relative to image (may be
provide if `coordinate_system` is ``"PATIENT"`` and patient is
an animal)
Expand Down Expand Up @@ -190,28 +196,31 @@ def __init__(
)

# General Series
laterality = Lateralities(laterality)
laterality = LateralityValues(laterality)
self.Laterality = laterality.value

# General Image
if anatomical_orientation_type is not None:
anatomical_orientation_type = AnatomicalOrientationTypes(
anatomical_orientation_type = AnatomicalOrientationTypeValues(
anatomical_orientation_type
)
self.AnatomicalOrientationType = \
anatomical_orientation_type.value
else:
anatomical_orientation_type = AnatomicalOrientationTypes.BIPED
anatomical_orientation_type = \
AnatomicalOrientationTypeValues.BIPED

if anatomical_orientation_type == AnatomicalOrientationTypes.BIPED:
row_orientation, col_orientation = patient_orientation
if (anatomical_orientation_type ==
AnatomicalOrientationTypeValues.BIPED):
patient_orientation = [
PatientOrientationsBiped(patient_orientation[0]).value,
PatientOrientationsBiped(patient_orientation[1]).value,
PatientOrientationValuesBiped(row_orientation).value,
PatientOrientationValuesBiped(col_orientation).value,
]
else:
patient_orientation = [
PatientOrientationsQuadruped(patient_orientation[0]).value,
PatientOrientationsQuadruped(patient_orientation[1]).value,
PatientOrientationValuesQuadruped(row_orientation).value,
PatientOrientationValuesQuadruped(col_orientation).value,
]
self.PatientOrientation = patient_orientation

Expand Down Expand Up @@ -239,7 +248,7 @@ def __init__(
self.SpecimenDescriptionSequence = specimen_descriptions

# SC Equipment
self.ConversionType = ConversionTypes.DI.value
self.ConversionType = ConversionTypeValues.DI.value

# SC Image
now = datetime.datetime.now()
Expand All @@ -263,15 +272,15 @@ def __init__(
self.HighBit = self.BitsAllocated - 1
self.BitsStored = self.BitsAllocated
self.PixelRepresentation = 0
photometric_interpretation = PhotometricInterpretations(
photometric_interpretation = PhotometricInterpretationValues(
photometric_interpretation
)
if pixel_array.ndim == 3:
accepted_interpretations = (
PhotometricInterpretations.RGB.value,
PhotometricInterpretations.YBR_FULL.value,
PhotometricInterpretations.YBR_FULL_422.value,
PhotometricInterpretations.YBR_PARTIAL_420.value,
PhotometricInterpretationValues.RGB.value,
PhotometricInterpretationValues.YBR_FULL.value,
PhotometricInterpretationValues.YBR_FULL_422.value,
PhotometricInterpretationValues.YBR_PARTIAL_420.value,
)
if photometric_interpretation.value not in accepted_interpretations:
raise ValueError(
Expand All @@ -293,8 +302,8 @@ def __init__(
self.PlanarConfiguration = 0
elif pixel_array.ndim == 2:
accepted_interpretations = (
PhotometricInterpretations.MONOCHROME1.value,
PhotometricInterpretations.MONOCHROME2.value,
PhotometricInterpretationValues.MONOCHROME1.value,
PhotometricInterpretationValues.MONOCHROME2.value,
)
if photometric_interpretation.value not in accepted_interpretations:
raise ValueError(
Expand Down
9 changes: 5 additions & 4 deletions src/highdicom/seg/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from highdicom.content import AlgorithmIdentificationSequence
from highdicom.enum import CoordinateSystemNames
from highdicom.seg.enum import SegmentAlgorithmTypes
from highdicom.seg.enum import SegmentAlgorithmTypeValues
from highdicom.sr.coding import CodedConcept


Expand All @@ -23,7 +23,7 @@ def __init__(
segment_label: str,
segmented_property_category: Union[Code, CodedConcept],
segmented_property_type: Union[Code, CodedConcept],
algorithm_type: Union[SegmentAlgorithmTypes, str],
algorithm_type: Union[SegmentAlgorithmTypeValues, str],
algorithm_identification: AlgorithmIdentificationSequence,
tracking_uid: Optional[str] = None,
tracking_id: Optional[str] = None,
Expand All @@ -49,7 +49,7 @@ def __init__(
Property the segment represents,
e.g. ``Code("108369006", "SCT", "Neoplasm")``
(see CID 7151 Segmentation Property Types)
algorithm_type: Union[str, highdicom.seg.enum.SegmentAlgorithmTypes]
algorithm_type: Union[str, highdicom.seg.enum.SegmentAlgorithmTypeValues]
Type of algorithm
algorithm_identification: AlgorithmIdentificationSequence, optional
Information useful for identification of the algorithm, such
Expand Down Expand Up @@ -87,7 +87,8 @@ def __init__(
segmented_property_type.scheme_version
),
]
self.SegmentAlgorithmType = SegmentAlgorithmTypes(algorithm_type).value
algorithm_type = SegmentAlgorithmTypeValues(algorithm_type)
self.SegmentAlgorithmType = algorithm_type.value
self.SegmentAlgorithmName = algorithm_identification[0].AlgorithmName
self.SegmentationAlgorithmIdentificationSequence = \
algorithm_identification
Expand Down
Loading

0 comments on commit 6678bde

Please sign in to comment.