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

Implementation of Softcopy Presentation States #139

Merged
merged 187 commits into from
May 16, 2022
Merged
Show file tree
Hide file tree
Changes from 164 commits
Commits
Show all changes
187 commits
Select commit Hold shift + click to select a range
da7cedf
Implementation of GraphicObject
Oct 10, 2021
f8e2348
Added tests for GraphicObject
Oct 14, 2021
0a245be
Add tests for filled
Oct 14, 2021
faffc5b
largely complete implementation of TextObject
Oct 14, 2021
b748750
Completed TextObject implementation, add tests
Oct 21, 2021
e541905
WIP on GraphicAnnotation
Oct 21, 2021
b9d2d47
Add GraphicAnnotation and basic tests
CPBridge Nov 5, 2021
da2042a
Further tests
CPBridge Nov 6, 2021
c7909ad
Test for inappropriate use of MATRIX units
CPBridge Nov 6, 2021
55ddf06
Add units check for text objects
CPBridge Nov 6, 2021
02b98d8
Progress on SOP
CPBridge Nov 6, 2021
a5a71c6
Minimal implementation complete
CPBridge Nov 6, 2021
5973d37
Fix errors from validator
Nov 6, 2021
9ff8352
Introduce GraphicLayers
Nov 6, 2021
fb4c920
Typo in exception message
Nov 8, 2021
57f6b5c
Complete docstring
Nov 8, 2021
51984bb
Added graphic group logic
Nov 12, 2021
12c6dd5
Add pr module docs
Nov 12, 2021
697f1bc
Added several tests, fix bugs
Nov 12, 2021
bf3107a
Fix to CIELab values
Nov 16, 2021
c9ca14f
WIP moving to new structure
Nov 18, 2021
a9cac0c
Add missing test TODO
Nov 18, 2021
2c150e0
Finish restructuring
CPBridge Nov 18, 2021
cd60b39
Implement content creator id
Nov 19, 2021
0829e34
Add user guide for GSPS
Nov 19, 2021
b1b0fdb
Fix color issues
Nov 19, 2021
c7dd8db
Fix CIELab.value return type annotations
Nov 19, 2021
e5950cf
Moved Content Creator Identiification to highdicom.content
CPBridge Nov 20, 2021
883fb77
Add _SoftcopyPresentationState base class
CPBridge Dec 11, 2021
9b8da6b
Add Modality LUT
CPBridge Dec 11, 2021
3e11802
Correct SOP Class UIDs
CPBridge Dec 11, 2021
92388e4
Move ModalityLUT, add tests for ModalityLUT
CPBridge Dec 17, 2021
f75cd28
Change endianess
CPBridge Dec 17, 2021
5ef11e6
Tweaks to LUT encoding. Ongoing
Dec 17, 2021
db48cda
Move lut to require np array
CPBridge Dec 18, 2021
15a3b4c
Add ModalityLUT properties
CPBridge Dec 18, 2021
d18161e
Add SoftcopyVOILUT, needs tests and integration
CPBridge Dec 21, 2021
3dc6e93
Fix docstring
CPBridge Dec 21, 2021
f49d6fd
Add SOftcopyVOILUT tests
CPBridge Dec 22, 2021
8a1677b
Implement ReferencedImageSequence on SoftcopyVOILUT
CPBridge Dec 24, 2021
3ac267a
Integration Softcopy VOI LUT and presentation LUT. Needs tests
CPBridge Dec 24, 2021
ea8232b
Update docstrings
CPBridge Dec 24, 2021
ef4fb79
Add ICC profile, various integration tests
CPBridge Dec 30, 2021
7302b72
Fix PR constructor signatures and docstrings
CPBridge Dec 30, 2021
dafdcd6
Implement palette color lut
CPBridge Jan 2, 2022
833da6d
Checks for appropriate samples per pixel and voi referenced images
CPBridge Jan 3, 2022
69186b2
Implement copy_modality_lut option
CPBridge Jan 3, 2022
52c7f5c
Initial implementation of copy_voi_lut
CPBridge Jan 21, 2022
6e3f783
Tests for copying voi LUT
Feb 5, 2022
dd2ec8c
Add test with different window levels
CPBridge Feb 5, 2022
96e69cc
Implement multiframe copy_modality_lut, and test
Feb 11, 2022
6174d5e
Implement multiframe copy_voi_lut with test
Feb 12, 2022
4c92291
Docstring fixes
Feb 12, 2022
83b7acc
More docstring fixes
Feb 12, 2022
430f77a
Apply suggestions from code review
CPBridge Feb 21, 2022
5e4660a
merge branch 'master' into feature/presentation_state
CPBridge Feb 25, 2022
e4c39de
Fix flake8 after review suggestions
CPBridge Feb 25, 2022
68fddea
Updated usage guide to advise against GSPS for annotations.
CPBridge Feb 25, 2022
f869985
Change CIELabColor property from list to tuple
CPBridge Feb 25, 2022
4db9bc4
filled -> is_filled
CPBridge Feb 25, 2022
db1157c
Check negative values in the case of the MATRIX coordinates
CPBridge Feb 25, 2022
747c676
Fix text_value type hint
CPBridge Feb 25, 2022
6b57bd0
Add missing property docstrings
CPBridge Feb 25, 2022
f72d908
Error string correction
CPBridge Feb 25, 2022
880b294
more error message fixes
CPBridge Feb 25, 2022
dfbb4ed
Merge from master and fix conflicts
CPBridge Feb 25, 2022
5b2955b
Docstring fix suggestion
CPBridge Feb 25, 2022
ed2de2b
Allow mixing frame and segment number
Mar 1, 2022
4636435
Flake8 fix
Mar 1, 2022
04089bc
Added has_pixel_data utility
Mar 3, 2022
b8d98cb
Change annotation units docstring
Mar 3, 2022
92fa9fe
Broaden definition of MATRIX to allow all tiled images
Mar 3, 2022
33512f7
Docstring typo
Mar 3, 2022
280eec8
docstring order
Mar 3, 2022
9d03877
Move checks to base class
Mar 3, 2022
d055330
Update src/highdicom/pr/sop.py
CPBridge Mar 3, 2022
11aec6c
Check for tiled images
Mar 3, 2022
3b3b8a1
Update error message
Mar 3, 2022
836e787
Fix tiled check problems
Mar 3, 2022
478e7f7
Merge branch 'master' into feature/presentation_state
CPBridge Mar 26, 2022
5594b44
Change enum docstring
CPBridge Mar 26, 2022
474999f
Copy specimen information
CPBridge Mar 26, 2022
204ec2d
Include content date and time
CPBridge Mar 26, 2022
dae495d
Refactor to separate Palette Color Lookup Table and use for pr module
CPBridge Mar 26, 2022
f89f9be
Add check for type of palette lut
CPBridge Mar 26, 2022
9ff5246
Added Content Creator ID to seg and pm
CPBridge Mar 26, 2022
e2409c2
Added Palette Color LUT to pm
CPBridge Mar 26, 2022
9aa090f
Refactor to include VOILUT class
CPBridge Mar 30, 2022
1d96ad3
Add check for duplicate instances in referenced images
CPBridge Mar 30, 2022
b526512
Refactor Graphic Annotation to use ReferencedImageSequence class
CPBridge Mar 30, 2022
2d81dea
Fix mispelled ContentDate and ContentTime attributes
Mar 30, 2022
2a0585d
Add tracking IDs to usage to encourage their use
Mar 30, 2022
382f411
Merge branch 'master' into feature/presentation_state
Mar 31, 2022
f49ccf4
Fix tests for pydicom 2.3.0
Mar 31, 2022
066afb1
rename fuction
Mar 31, 2022
b050886
Apply suggestions from code review
CPBridge Mar 31, 2022
8756ce1
Rename modality_lut_type -> lut_type
Mar 31, 2022
6b4dbce
Update src/highdicom/content.py
CPBridge Mar 31, 2022
34c7f40
Shorten docstring
CPBridge Apr 1, 2022
bc96bae
Refactor PaletteColorLookupTable to take LUT parameters
CPBridge Apr 1, 2022
3fe5312
Fixes to Palette Color LUT
CPBridge Apr 1, 2022
3adc2f1
Merge branch 'master' into feature/presentation_state
CPBridge Apr 2, 2022
ea3771b
Apply suggestions from code review
CPBridge Apr 3, 2022
eba0dd2
Rename voi_luts -> luts in VOILUT and SoftcopyVOILUT
CPBridge Apr 3, 2022
863fa76
Change docstring of SoftcopyVOILUT
CPBridge Apr 3, 2022
2b40cc1
Remove default value for units in GraphicObject and TextObject
CPBridge Apr 3, 2022
ea08248
Rename concept_name_code -> conceot_name
CPBridge Apr 3, 2022
6387a70
Add example to GraphicLayer/GraphicGroup explanation
CPBridge Apr 3, 2022
e6ba4fa
Move public API to use bytes rather than ImageCmsProfile
CPBridge Apr 3, 2022
874f6b8
Added contraints on the ICC Profile passed.
CPBridge Apr 3, 2022
98bb0e4
Fixed small bug in GraphicAnnotation
CPBridge Apr 3, 2022
a4708cf
Check for first mapped value in Palette Color Lookup Table
CPBridge Apr 3, 2022
708d857
Fixed tests broken by previous commit
CPBridge Apr 3, 2022
81b1b00
Added separate tests for Palette Color Lookup Table
CPBridge Apr 3, 2022
07e554b
Added get_lut method to the palette color lookup table
CPBridge Apr 3, 2022
1cd763c
Add check on the validity of graphic data when constructing GraphicAn…
CPBridge Apr 3, 2022
dcd2a5d
Fix out of bounds check and add further tests
CPBridge Apr 3, 2022
3fb7d0d
Style error
CPBridge Apr 3, 2022
82f5a8e
Update src/highdicom/pr/sop.py
CPBridge Apr 3, 2022
9b7d449
Add check that all images referenced by a Graphic Annotation have the…
CPBridge Apr 3, 2022
b134daa
Merge branch 'feature/presentation_state' of github.com:MGHComputatio…
CPBridge Apr 3, 2022
542dd63
Copy ICC profile if none is provded
CPBridge Apr 4, 2022
8a5ed0d
Apply suggestions from code review
CPBridge Apr 4, 2022
1c49e8d
Update README.md
CPBridge Apr 4, 2022
7ba0b2f
Tidy up in constructor
CPBridge Apr 4, 2022
e4f7192
Merge branch 'feature/presentation_state' of github.com:MGHComputatio…
CPBridge Apr 4, 2022
d1544c6
Add check that images have same total pixel matrix dimensions
CPBridge Apr 4, 2022
6dcc2b1
Add checks for VOI LUT references. Needs tests
Apr 7, 2022
990bf06
Refactor Softcopy Presentation State constructors
hackermd Apr 12, 2022
1df7f01
Include default ICC Profile for sRGB color space
hackermd Apr 12, 2022
bb6129d
Implement Advanced Blending Presentation State
hackermd Apr 14, 2022
eae855b
Add more unit tests for advanced blending
hackermd Apr 14, 2022
784e07d
Fix unit tests
hackermd Apr 14, 2022
89e9422
Roll back change of Modality LUT interface
hackermd Apr 14, 2022
134ae1b
Improve docstring of VOILUT class
hackermd Apr 15, 2022
3718b14
Set content date/time attributes in other function
hackermd Apr 21, 2022
bebf627
Remove obsolete check
hackermd Apr 21, 2022
a004405
Remove additional obsolete check
hackermd Apr 21, 2022
d21a760
Apply suggestions from code review
hackermd Apr 21, 2022
a20fb80
Add tests and fixes for VOI overlap
Apr 22, 2022
4d2c34b
Refactor implementation of LUTs
hackermd Apr 22, 2022
424cad2
Remove obsolete constructor parameters
hackermd Apr 22, 2022
d5675c3
Update src/highdicom/pr/sop.py
hackermd Apr 22, 2022
454d184
Merge changes from feature/presentation_state_suggestions
Apr 22, 2022
82d624b
Add missing test files
hackermd Apr 22, 2022
fa147db
Restrict value multiplicitity of presentation lut
hackermd Apr 22, 2022
f473813
Merge branch 'feature/presentation_state_suggestions' into softcopy_v…
Apr 22, 2022
7662849
Update src/highdicom/pr/sop.py
hackermd Apr 22, 2022
d82ed9e
Update src/highdicom/pr/sop.py
hackermd Apr 22, 2022
b71085d
Derive number of entries from segmented lut data
hackermd Apr 22, 2022
b4409a3
Fix encoding of lut data
hackermd Apr 22, 2022
b2ba7ad
Fix unit tests
hackermd Apr 22, 2022
f752b91
Ensure number of entries is < 2^16
hackermd Apr 22, 2022
0c2ebc1
Merge branch 'feature/presentation_state_suggestions' into softcopy_v…
Apr 22, 2022
006c364
Merge pull request #166 from herrmannlab/feature/presentation_state_s…
CPBridge Apr 22, 2022
eae0c41
Merge branch 'softcopy_voi_tests' into feature/presentation_state
Apr 22, 2022
5c823d3
Merge from branch master, resolve conflicts
Apr 22, 2022
e90b636
Fix style errors
Apr 22, 2022
3c75c32
Fixed modality LUT logic
Apr 22, 2022
5d5f06d
Fix handling of voi_luts
Apr 22, 2022
89bd835
Update src/highdicom/pr/content.py
hackermd Apr 22, 2022
a537b29
Update src/highdicom/pr/content.py
hackermd Apr 22, 2022
7d32e54
Add link to segmented LUT docs
Apr 22, 2022
beccae6
Merge branch 'feature/presentation_state' of github.com:herrmannlab/h…
Apr 22, 2022
253e394
Typo in docstring
Apr 27, 2022
825bfdb
Fix another typo in docstring
Apr 27, 2022
7dc88f7
Fix spelling errors in docstrings
Apr 27, 2022
fe114b8
Add checks for empty list
Apr 27, 2022
9c40d9f
Use IDENTITY as default presentation LUT transform
Apr 27, 2022
44ab4cc
Fix error in docstring
Apr 27, 2022
2a21fc2
Export classes of pr subpackage
hackermd Apr 27, 2022
da8b222
Rename parameter of pr class
hackermd Apr 27, 2022
f491d10
Cast value of window_width and window_center
hackermd Apr 27, 2022
5fa4374
Add uid of advanced blending presentation state
hackermd Apr 27, 2022
34934cd
Fix displayed area extent for tiled images
hackermd Apr 27, 2022
5a738a4
Account for image pyramids for displayed area
hackermd Apr 27, 2022
1964a6a
Add missing attributes to advanced blending pr
hackermd Apr 27, 2022
39e0684
Cast value of window_width and window_center for real
hackermd Apr 28, 2022
c543cf1
Merge pull request #170 from herrmannlab/feature/presentation_state_p…
CPBridge Apr 28, 2022
e99d5f5
Fix referenced series uid for advanced blending
hackermd Apr 28, 2022
a290c80
Fix optional arguments of advanced blending
hackermd Apr 28, 2022
200e993
Merge pull request #172 from herrmannlab/feature/presentation_state_p…
CPBridge Apr 28, 2022
42c48b3
Remove 8 bit LUTS; update tests
CPBridge May 14, 2022
ef856d7
Merge branch 'master' into feature/presentation_state
CPBridge May 14, 2022
855aedd
Merge pull request #177 from herrmannlab/remove_uint8_luts
CPBridge May 15, 2022
136da3e
Fix assumptions about tiled images
hackermd May 16, 2022
fcb0192
Merge pull request #178 from herrmannlab/bugfix/presentation-state-mo…
CPBridge May 16, 2022
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
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ include src/highdicom/legacy/*
include src/highdicom/sc/*
include src/highdicom/seg/*
include src/highdicom/sr/*
include src/highdicom/_icc_profiles/*
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ It currently provides tools for creating and decoding the following DICOM inform
* Secondary Capture images
* Key Object Selection documents
* Legacy Converted Enhanced CT/PET/MR images (e.g., for single frame to multi-frame conversion)
* Softcopy Presentation State instances (including Grayscale, Color, and Pseudo-Color)

## Documentation

Expand Down
Binary file added data/test_files/sm_image_grayscale.dcm
Binary file not shown.
Binary file added data/test_files/sm_image_grayscale_reversed.dcm
Binary file not shown.
11 changes: 11 additions & 0 deletions docs/package.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ highdicom.pm package
:undoc-members:
:show-inheritance:

.. _highdicom-pr-subpackage:

highdicom.pr package
---------------------

.. automodule:: highdicom.pr
:members:
:special-members: __call__
:undoc-members:
:show-inheritance:

.. _highdicom-seg-subpackage:

highdicom.seg package
Expand Down
91 changes: 91 additions & 0 deletions docs/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,97 @@ overlay a segmentation that is stored in a NumPy array called "seg_out".

sc_image.save_as(os.path.join("output", 'sc_output_' + str(iz) + '.dcm'))


Creating Grayscale Softcopy Presentation State (GSPS) Objects
-------------------------------------------------------------

A presentation state contains information about how another image should be
rendered, and may include "annotations" in the form of basic shapes, polylines,
hackermd marked this conversation as resolved.
Show resolved Hide resolved
and text overlays. Note that a GSPS is not recommended for storing annotations
for any purpose except visualization. A structured report would usually be
preferred for storing annotations for clinical or research purposes.

.. code-block:: python

import highdicom as hd

import numpy as np
from pydicom import dcmread
from pydicom.valuerep import PersonName


# Read in an example CT image
image_dataset = dcmread('path/to/image.dcm')

# Create an annotation containing a polyline
polyline = hd.pr.GraphicObject(
graphic_type=hd.pr.GraphicTypeValues.POLYLINE,
graphic_data=np.array([
[10.0, 10.0],
[20.0, 10.0],
[20.0, 20.0],
[10.0, 20.0]]
), # coordinates of polyline vertices
units=hd.pr.AnnotationUnitsValues.PIXEL, # units for graphic data
tracking_id='Finding1', # site-specific ID
tracking_uid=hd.UID() # highdicom will generate a unique ID
)

# Create a text object annotation
text = hd.pr.TextObject(
text_value='Important Finding!',
bounding_box=np.array(
[30.0, 30.0, 40.0, 40.0] # left, top, right, bottom
),
units=hd.pr.AnnotationUnitsValues.PIXEL, # units for bounding box
tracking_id='Finding1Text', # site-specific ID
tracking_uid=hd.UID() # highdicom will generate a unique ID
)

# Create a single layer that will contain both graphics
# There may be multiple layers, and each GraphicAnnotation object
# belongs to a single layer
layer = hd.pr.GraphicLayer(
layer_name='LAYER1',
order=1, # order in which layers are displayed (lower first)
description='Simple Annotation Layer',
)

# A GraphicAnnotation may contain multiple text and/or graphic objects
# and is rendered over all referenced images
annotation = hd.pr.GraphicAnnotation(
referenced_images=[image_dataset],
graphic_layer=layer,
graphic_objects=[polyline],
text_objects=[text]
)

# Assemble the components into a GSPS object
gsps = hd.pr.GrayscaleSoftcopyPresentationState(
referenced_images=[image_dataset],
series_instance_uid=hd.UID(),
series_number=123,
sop_instance_uid=hd.UID(),
instance_number=1,
manufacturer='Manufacturer',
manufacturer_model_name='Model',
software_versions='v1',
device_serial_number='Device XYZ',
content_label='ANNOTATIONS',
graphic_layers=[layer],
graphic_annotations=[annotation],
institution_name='MGH',
institutional_department_name='Radiology',
content_creator_name=PersonName.from_named_components(
family_name='Doe',
given_name='John'
),
)

# Save the GSPS file
gsps.save_as('gsps.dcm')


.. .. _creation-legacy:

.. Creating Legacy Converted Enhanced Images
Expand Down
10 changes: 7 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@
readme_filepath = root_directory.joinpath('README.md')
long_description = readme_filepath.read_text()

with io.open('src/highdicom/version.py', 'rt', encoding='utf8') as f:
version = re.search(r'__version__ = \'(.*?)\'', f.read()).group(1)

def get_version():
version_filepath = Path('src', 'highdicom', 'version.py')
with io.open(version_filepath, 'rt', encoding='utf8') as f:
version = re.search(r'__version__ = \'(.*?)\'', f.read()).group(1)
return version


setuptools.setup(
name='highdicom',
version=version,
version=get_version(),
description='High-level DICOM abstractions.',
long_description=long_description,
long_description_content_type='text/markdown',
Expand Down
44 changes: 39 additions & 5 deletions src/highdicom/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,52 @@
from highdicom import ko
from highdicom import legacy
from highdicom import pm
from highdicom import pr
from highdicom import sc
from highdicom import seg
from highdicom import sr
from highdicom.base import SOPClass
from highdicom.content import (
AlgorithmIdentificationSequence,
ContentCreatorIdentificationCodeSequence,
IssuerOfIdentifier,
LUT,
ModalityLUT,
ModalityLUTTransformation,
PaletteColorLUT,
PaletteColorLUTTransformation,
PixelMeasuresSequence,
PlanePositionSequence,
PlaneOrientationSequence,
PlanePositionSequence,
PresentationLUT,
PresentationLUTTransformation,
ReferencedImageSequence,
SegmentedPaletteColorLUT,
SpecimenCollection,
SpecimenDescription,
SpecimenPreparationStep,
SpecimenProcessing,
SpecimenSampling,
SpecimenStaining,
VOILUT,
VOILUTTransformation,
)
from highdicom.enum import (
AnatomicalOrientationTypeValues,
CoordinateSystemNames,
ContentQualificationValues,
DimensionOrganizationTypeValues,
LateralityValues,
PatientSexValues,
PhotometricInterpretationValues,
PlanarConfigurationValues,
PixelRepresentationValues,
LateralityValues,
AnatomicalOrientationTypeValues,
PlanarConfigurationValues,
PatientOrientationValuesBiped,
PatientOrientationValuesQuadruped,
UniversalEntityIDTypeValues
PresentationLUTShapeValues,
RescaleTypeValues,
UniversalEntityIDTypeValues,
VOILUTFunctionValues,
)
from highdicom import frame
from highdicom import io
Expand All @@ -43,11 +60,17 @@
__all__ = [
'AlgorithmIdentificationSequence',
'AnatomicalOrientationTypeValues',
'ContentCreatorIdentificationCodeSequence',
'ContentQualificationValues',
'CoordinateSystemNames',
'DimensionOrganizationTypeValues',
'IssuerOfIdentifier',
'LateralityValues',
'LUT',
'ModalityLUT',
'ModalityLUTTransformation',
'PaletteColorLUT',
'PaletteColorLUTTransformation',
'PatientOrientationValuesBiped',
'PatientOrientationValuesQuadruped',
'PatientSexValues',
Expand All @@ -57,21 +80,32 @@
'PlanarConfigurationValues',
'PlaneOrientationSequence',
'PlanePositionSequence',
'PresentationLUT',
'PresentationLUTShapeValues',
'PresentationLUTTransformation',
'ReferencedImageSequence',
'RescaleTypeValues',
'SegmentedPaletteColorLUT',
'SpecimenCollection',
'SpecimenDescription',
'SpecimenPreparationStep',
'SpecimenProcessing',
'SpecimenSampling',
'SpecimenStaining',
'SOPClass',
'UID',
'UniversalEntityIDTypeValues',
'VOILUT',
'VOILUTFunctionValues',
'VOILUTTransformation',
'ann',
'color',
'frame',
'io',
'ko',
'legacy',
'pm',
'pr',
'sc',
'seg',
'spatial',
Expand Down
Binary file not shown.
66 changes: 66 additions & 0 deletions src/highdicom/_module_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
from pydicom import Dataset

from highdicom._modules import MODULE_ATTRIBUTE_MAP
from highdicom._iods import (
IOD_MODULE_MAP,
SOP_CLASS_UID_IOD_KEY_MAP
)


# Allowed values for the type of an attribute
Expand Down Expand Up @@ -167,3 +171,65 @@ def construct_module_tree(module: str) -> Dict[str, Any]:
'type': AttributeTypeValues(item['type'])
}
return tree


def is_attribute_in_iod(attribute: str, sop_class_uid: str) -> bool:
"""Check whether an attribute is present within an IOD.

Parameters
----------
attribute: str
Keyword for the attribute
sop_class_uid: str
SOP Class UID identifying the IOD.

Returns
-------
bool:
True if the attribute is present within any module within the IOD
specified by the sop_class_uid. False otherwise.

"""
try:
iod_name = SOP_CLASS_UID_IOD_KEY_MAP[sop_class_uid]
except KeyError as e:
msg = f'No IOD found for SOP Class UID: {sop_class_uid}.'
raise KeyError(msg) from e

for module in IOD_MODULE_MAP[iod_name]:
module_attributes = MODULE_ATTRIBUTE_MAP[module['key']]
for attr in module_attributes:
if attr['keyword'] == attribute:
return True

return False


def does_iod_have_pixel_data(sop_class_uid: str) -> bool:
"""Check whether any pixel data attribute is present within an IOD.

This may be used to determine whether a particular SOP class represents an
image.

Parameters
----------
sop_class_uid: str
SOP Class UID identifying the IOD.

Returns
-------
bool:
True if the any pixel data attribute is present within any module
within the IOD specified by the sop_class_uid. False otherwise. Pixel
data attributes include ``PixelData``, ``FloatPixelData``, and
``DoubleFloatPixelData``.

"""
pixel_attrs = [
'PixelData',
'FloatPixelData',
'DoubleFloatPixelData',
]
return any(
is_attribute_in_iod(attr, sop_class_uid) for attr in pixel_attrs
)
Loading