Skip to content

Commit abaa174

Browse files
authored
Fix bugs in implementation of Advanced Blending Presentation State IOD (#179)
* Allow reference of images from different series * Include palette color lut attributes in sequence * Fix reference of images in presentation state
1 parent 05f4ace commit abaa174

File tree

3 files changed

+62
-46
lines changed

3 files changed

+62
-46
lines changed

src/highdicom/pr/content.py

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -913,27 +913,23 @@ def _add_presentation_state_relationship_attributes(
913913
"""
914914
# Assert referenced images are from the same series and have the same size
915915
ref_im = referenced_images[0]
916-
ref_series_uid = ref_im.SeriesInstanceUID
917-
ref_im_seq = []
916+
ref_im_items_mapping = defaultdict(list)
918917
for im in referenced_images:
919-
series_uid = im.SeriesInstanceUID
920-
if series_uid != ref_series_uid:
921-
raise ValueError(
922-
'All referenced images must belong to the same series.'
923-
)
924918
if im.Rows != ref_im.Rows or im.Columns != ref_im.Columns:
925919
raise ValueError(
926920
'All referenced images must have the same dimensions.'
927921
)
928-
ref_im_item = Dataset()
929-
ref_im_item.ReferencedSOPClassUID = im.SOPClassUID
930-
ref_im_item.ReferencedSOPInstanceUID = im.SOPInstanceUID
931-
ref_im_seq.append(ref_im_item)
922+
item = Dataset()
923+
item.ReferencedSOPClassUID = im.SOPClassUID
924+
item.ReferencedSOPInstanceUID = im.SOPInstanceUID
925+
ref_im_items_mapping[im.SeriesInstanceUID].append(item)
932926

933-
ref_series_item = Dataset()
934-
ref_series_item.SeriesInstanceUID = ref_series_uid
935-
ref_series_item.ReferencedImageSequence = ref_im_seq
936-
dataset.ReferencedSeriesSequence = [ref_series_item]
927+
dataset.ReferencedSeriesSequence = []
928+
for series_instance_uid, ref_images in ref_im_items_mapping.items():
929+
item = Dataset()
930+
item.SeriesInstanceUID = series_instance_uid
931+
item.ReferencedImageSequence = ref_images
932+
dataset.ReferencedSeriesSequence.append(item)
937933

938934

939935
def _add_graphic_group_annotation_layer_attributes(
@@ -1860,24 +1856,22 @@ def __init__(
18601856
referenced_images
18611857
)
18621858
if len(voi_lut_transformations) > 0:
1863-
logger.debug(
1864-
'use VOI LUT attributes from referenced images'
1865-
)
1859+
logger.debug('use VOI LUT attributes from referenced images')
18661860
_add_softcopy_voi_lut_attributes(
18671861
self,
18681862
referenced_images=referenced_images,
18691863
voi_lut_transformations=voi_lut_transformations
18701864
)
18711865
else:
1872-
logger.debug(
1873-
'no VOI LUT attributes found in referenced images'
1874-
)
1866+
logger.debug('no VOI LUT attributes found in referenced images')
18751867

18761868
# Palette Color Lookup Table
1869+
palette_color_lut_item = Dataset()
18771870
_add_palette_color_lookup_table_attributes(
1878-
self,
1871+
palette_color_lut_item,
18791872
palette_color_lut_transformation=palette_color_lut_transformation
18801873
)
1874+
self.PaletteColorLookupTableSequence = [palette_color_lut_item]
18811875

18821876

18831877
class BlendingDisplayInput(Dataset):

src/highdicom/pr/sop.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Module for SOP Classes of Presentation State (PR) IODs."""
22
import logging
33
import pkgutil
4+
from collections import defaultdict
45
from typing import Optional, Sequence, Tuple, Union
56

67
import numpy as np
@@ -1040,13 +1041,21 @@ def __init__(
10401041
)
10411042

10421043
# Confusingly, the Advanced Blending Presentation State IOD does not
1043-
# include the Presentation State Relationship module. However, it
1044-
# includes the Common Instance Reference module, which containes the
1045-
# same attributes.
1046-
_add_presentation_state_relationship_attributes(
1047-
self,
1048-
referenced_images=referenced_images
1049-
)
1044+
# include the Presentation State Relationship module, but instead
1045+
# includes the Common Instance Reference module.
1046+
ref_im_items_mapping = defaultdict(list)
1047+
for im in referenced_images:
1048+
item = Dataset()
1049+
item.ReferencedSOPClassUID = im.SOPClassUID
1050+
item.ReferencedSOPInstanceUID = im.SOPInstanceUID
1051+
ref_im_items_mapping[im.SeriesInstanceUID].append(item)
1052+
1053+
self.ReferencedSeriesSequence = []
1054+
for series_instance_uid, ref_images in ref_im_items_mapping.items():
1055+
item = Dataset()
1056+
item.SeriesInstanceUID = series_instance_uid
1057+
item.ReferencedInstanceSequence = ref_images
1058+
self.ReferencedSeriesSequence.append(item)
10501059

10511060
# Graphic Group, Graphic Annotation, and Graphic Layer
10521061
_add_graphic_group_annotation_layer_attributes(

tests/test_pr.py

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -784,13 +784,16 @@ def setUp(self):
784784

785785
def test_construction(self):
786786
ref_images = [self._sm_image, self._sm_image_reversed]
787+
window_width = 24.
788+
window_center = 12.
789+
787790
ds = AdvancedBlending(
788791
referenced_images=ref_images,
789792
blending_input_number=1,
790793
voi_lut_transformations=[
791794
SoftcopyVOILUTTransformation(
792-
window_center=12.,
793-
window_width=24.
795+
window_center=window_center,
796+
window_width=window_width
794797
)
795798
],
796799
palette_color_lut_transformation=PaletteColorLUTTransformation(
@@ -829,6 +832,7 @@ def test_construction(self):
829832
)
830833
)
831834
)
835+
832836
assert isinstance(ds, Dataset)
833837
assert ds.StudyInstanceUID == ref_images[0].StudyInstanceUID
834838
assert ds.SeriesInstanceUID == ref_images[0].SeriesInstanceUID
@@ -838,22 +842,31 @@ def test_construction(self):
838842
ref_item = ds.ReferencedImageSequence[i]
839843
assert ref_item.ReferencedSOPInstanceUID == ref_im.SOPInstanceUID
840844
assert ds.BlendingInputNumber == 1
845+
841846
assert len(ds.SoftcopyVOILUTSequence) == 1
842-
assert len(ds.RedPaletteColorLookupTableDescriptor) == 3
843-
assert ds.RedPaletteColorLookupTableDescriptor[0] == 256
844-
assert ds.RedPaletteColorLookupTableDescriptor[1] == 0
845-
assert ds.RedPaletteColorLookupTableDescriptor[2] == 16
846-
assert len(ds.GreenPaletteColorLookupTableDescriptor) == 3
847-
assert ds.GreenPaletteColorLookupTableDescriptor[0] == 256
848-
assert ds.GreenPaletteColorLookupTableDescriptor[1] == 0
849-
assert ds.GreenPaletteColorLookupTableDescriptor[2] == 16
850-
assert len(ds.BluePaletteColorLookupTableDescriptor) == 3
851-
assert ds.BluePaletteColorLookupTableDescriptor[0] == 256
852-
assert ds.BluePaletteColorLookupTableDescriptor[1] == 0
853-
assert ds.BluePaletteColorLookupTableDescriptor[2] == 16
854-
assert len(ds.SegmentedRedPaletteColorLookupTableData) == 12
855-
assert len(ds.SegmentedGreenPaletteColorLookupTableData) == 12
856-
assert len(ds.SegmentedBluePaletteColorLookupTableData) == 12
847+
item = ds.SoftcopyVOILUTSequence[0]
848+
assert item.WindowWidth == window_width
849+
assert item.WindowCenter == window_center
850+
assert not hasattr(item, 'VOILUTSequence')
851+
852+
assert len(ds.PaletteColorLookupTableSequence) == 1
853+
item = ds.PaletteColorLookupTableSequence[0]
854+
assert len(item.RedPaletteColorLookupTableDescriptor) == 3
855+
assert item.RedPaletteColorLookupTableDescriptor[0] == 256
856+
assert item.RedPaletteColorLookupTableDescriptor[1] == 0
857+
assert item.RedPaletteColorLookupTableDescriptor[2] == 16
858+
assert len(item.GreenPaletteColorLookupTableDescriptor) == 3
859+
assert item.GreenPaletteColorLookupTableDescriptor[0] == 256
860+
assert item.GreenPaletteColorLookupTableDescriptor[1] == 0
861+
assert item.GreenPaletteColorLookupTableDescriptor[2] == 16
862+
assert len(item.BluePaletteColorLookupTableDescriptor) == 3
863+
assert item.BluePaletteColorLookupTableDescriptor[0] == 256
864+
assert item.BluePaletteColorLookupTableDescriptor[1] == 0
865+
assert item.BluePaletteColorLookupTableDescriptor[2] == 16
866+
assert len(item.SegmentedRedPaletteColorLookupTableData) == 12
867+
assert len(item.SegmentedGreenPaletteColorLookupTableData) == 12
868+
assert len(item.SegmentedBluePaletteColorLookupTableData) == 12
869+
857870
assert not hasattr(ds, 'ContentDescription')
858871
assert not hasattr(ds, 'ConceptNameCodeSequence')
859872
assert not hasattr(ds, 'ThresholdSequence')

0 commit comments

Comments
 (0)