Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/image library entries #77

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/highdicom/sr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
AlgorithmIdentification,
DeviceObserverIdentifyingAttributes,
ImageLibrary,
ImageLibraryEntry,
LanguageOfContentItemAndDescendants,
Measurement,
MeasurementProperties,
Expand Down Expand Up @@ -107,6 +108,7 @@
'GraphicTypeValues3D',
'ImageContentItem',
'ImageLibrary',
'ImageLibraryEntry',
'ImageRegion',
'ImageRegion3D',
'LanguageOfContentItemAndDescendants',
Expand Down
2 changes: 1 addition & 1 deletion src/highdicom/sr/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class RelationshipTypeValues(Enum):
"""Enumerated values for attribute Relationship Type."""

CONTAINS = 'CONTAINS'
HAS_ACQ_CONTENT = 'HAS ACQ CONTENT'
HAS_ACQ_CONTEXT = 'HAS ACQ CONTEXT'
HAS_CONCEPT_MOD = 'HAS CONCEPT MOD'
HAS_OBS_CONTEXT = 'HAS OBS CONTEXT'
HAS_PROPERTIES = 'HAS PROPERTIES'
Expand Down
186 changes: 94 additions & 92 deletions src/highdicom/sr/templates.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""DICOM structured reporting templates."""
from typing import Any, Dict, List, Optional, Sequence, Union
from typing import List, Optional, Sequence, Union

import numpy as np
from pydicom.dataset import Dataset
from pydicom.sr.coding import Code
from pydicom.sr.codedict import codes
Expand Down Expand Up @@ -2722,6 +2721,94 @@ def __init__(
self.append(value_item)


class ImageLibraryEntry(Template):

"""`TID 1601 <http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1601>`_
Image Library Entry""" # noqa: E501

def __init__(
self,
modality: Union[Code, CodedConcept],
frame_of_reference_uid: str,
pixel_data_rows: int,
pixel_data_columns: int,
descriptors: Sequence[ContentItem]
) -> None:
"""
Parameters
----------
modality: Union[highdicom.sr.coding.CodedConcept, pydicom.sr.coding.Code]
Modality
frame_of_reference_uid: str
Frame of Reference UID
pixel_data_rows: int
Number of rows in pixel data frames
pixel_data_columns: int
Number of rows in pixel data frames
descriptors: Sequence[highdicom.sr.value_types.ContentItem], optional
Additional SR Content Items that should be included

""" # noqa
super().__init__()
modality_item = CodeContentItem(
name=CodedConcept(
value='121139',
meaning='Modality',
scheme_designator='DCM'
),
value=modality,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTEXT
)
self.append(modality_item)
frame_of_reference_uid_item = UIDRefContentItem(
name=CodedConcept(
value='112227',
meaning='Frame of Reference UID',
scheme_designator='DCM'
),
value=frame_of_reference_uid,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTEXT
)
self.append(frame_of_reference_uid_item)
pixel_data_rows_item = NumContentItem(
name=CodedConcept(
value='110910',
meaning='Pixel Data Rows',
scheme_designator='DCM'
),
value=pixel_data_rows,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTEXT,
unit=CodedConcept(
value='{pixels}',
meaning='Pixels',
scheme_designator='UCUM'
)
)
self.append(pixel_data_rows_item)
pixel_data_cols_item = NumContentItem(
name=CodedConcept(
value='110911',
meaning='Pixel Data Columns',
scheme_designator='DCM'
),
value=pixel_data_columns,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTEXT,
unit=CodedConcept(
value='{pixels}',
meaning='Pixels',
scheme_designator='UCUM'
)
)
self.append(pixel_data_cols_item)
for item in descriptors:
if not isinstance(item, ContentItem):
raise TypeError(
'Image Library Entry Descriptor must have type ContentItem.'
)
item.RelationshipType = RelationshipTypeValues.HAS_ACQ_CONTEXT.value
self.append(item)


class MeasurementReport(Template):

"""`TID 1500 <http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1500>`_
Expand All @@ -2746,6 +2833,9 @@ def __init__(
title: Optional[Union[CodedConcept, Code]] = None,
language_of_content_item_and_descendants: Optional[
LanguageOfContentItemAndDescendants
] = None,
image_library_entries: Optional[
Sequence[Sequence[ImageLibraryEntry]]
] = None
):
"""
Expand Down Expand Up @@ -2812,7 +2902,7 @@ def __init__(
relationship_type=RelationshipTypeValues.HAS_CONCEPT_MOD
)
item.ContentSequence.append(procedure_item)
image_library_item = ImageLibrary()
image_library_item = ImageLibrary(image_library_entries)
item.ContentSequence.extend(image_library_item)

num_arguments_provided = sum([
Expand Down Expand Up @@ -3293,94 +3383,6 @@ def get_image_measurments(
return sequences


class ImageLibraryEntry(Template):

"""`TID 1601 <http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1601>`_
Image Library Entry""" # noqa: E501

def __init__(
self,
modality: Union[Code, CodedConcept],
frame_of_reference_uid: str,
pixel_data_rows: int,
pixel_data_columns: int,
descriptors: Sequence[ContentItem]
) -> None:
"""
Parameters
----------
modality: Union[highdicom.sr.coding.CodedConcept, pydicom.sr.coding.Code]
Modality
frame_of_reference_uid: str
Frame of Reference UID
pixel_data_rows: int
Number of rows in pixel data frames
pixel_data_columns: int
Number of rows in pixel data frames
descriptors: Sequence[highdicom.sr.value_types.ContentItem], optional
Additional SR Content Items that should be included

""" # noqa
super().__init__()
modality_item = CodeContentItem(
name=CodedConcept(
value='121139',
meaning='Modality',
scheme_designator='DCM'
),
value=modality,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTENT
)
self.append(modality_item)
frame_of_reference_uid_item = UIDRefContentItem(
name=CodedConcept(
value='112227',
meaning='Frame of Reference UID',
scheme_designator='DCM'
),
value=frame_of_reference_uid,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTENT
)
self.append(frame_of_reference_uid_item)
pixel_data_rows_item = NumContentItem(
name=CodedConcept(
value='110910',
meaning='Pixel Data Rows',
scheme_designator='DCM'
),
value=pixel_data_rows,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTENT,
unit=CodedConcept(
value='{pixels}',
meaning='Pixels',
scheme_designator='UCUM'
)
)
self.append(pixel_data_rows_item)
pixel_data_cols_item = NumContentItem(
name=CodedConcept(
value='110911',
meaning='Pixel Data Columns',
scheme_designator='DCM'
),
value=pixel_data_columns,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTENT,
unit=CodedConcept(
value='{pixels}',
meaning='Pixels',
scheme_designator='UCUM'
)
)
self.append(pixel_data_cols_item)
for item in descriptors:
if not isinstance(item, ContentItem):
raise TypeError(
'Image Library Entry Descriptor must have type ContentItem.'
)
item.RelationshipType = RelationshipTypeValues.HAS_ACQ_CONTENT.value
self.append(item)


class ImageLibrary(Template):

"""`TID 1600 <http://dicom.nema.org/medical/dicom/current/output/chtml/part16/chapter_A.html#sect_TID_1600>`_
Expand Down Expand Up @@ -3411,7 +3413,7 @@ def __init__(
for group in entries:
group_item = ContainerContentItem(
name=CodedConcept(
value='26200',
value='126200',
meaning='Image Library Group',
scheme_designator='DCM'
),
Expand Down
4 changes: 2 additions & 2 deletions tests/test_sr.py
Original file line number Diff line number Diff line change
Expand Up @@ -2972,12 +2972,12 @@ def test_construction(self):
content_date_item = DateContentItem(
name=codes.DCM.ContentDate,
value=content_date,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTENT
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTEXT
)
content_time_item = TimeContentItem(
name=codes.DCM.ContentTime,
value=content_time,
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTENT
relationship_type=RelationshipTypeValues.HAS_ACQ_CONTEXT
)
entry = ImageLibraryEntry(
modality=modality,
Expand Down