Skip to content

Commit 322d187

Browse files
authored
Fix parsing TID1500 when template identifiers are missing (#360)
* Fix and tests for missing template identifier * Add test for missing template behavior * Linter fixes
1 parent 38356c5 commit 322d187

2 files changed

Lines changed: 257 additions & 125 deletions

File tree

src/highdicom/sr/templates.py

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ def _count_roi_items(
8888
-------
8989
int:
9090
Number of 'Image Region' content items
91+
int:
92+
Number of 'Image Region 3D' content items
9193
int:
9294
Number of 'Volume Surface' content items
9395
int:
@@ -103,35 +105,46 @@ def _count_roi_items(
103105
'SR Content Item does not represent a measurement group '
104106
'because it does not have value type CONTAINER.'
105107
)
106-
if group_item.name == codes.DCM.MeasurementGroup:
108+
if group_item.name != codes.DCM.MeasurementGroup:
107109
raise ValueError(
108110
'SR Content Item does not represent a measurement group '
109111
'because it does not have name "Measurement Group".'
110112
)
111113
n_image_region_items = 0
114+
n_image_region_3d_items = 0
112115
n_volume_surface_items = 0
113116
n_referenced_segment_items = 0
114117
n_referenced_segmentation_frame_items = 0
115118
n_region_in_space_items = 0
116119
for item in group_item.ContentSequence:
117-
if (item.name == codes.DCM.ImageRegion and
118-
item.value_type in (ValueTypeValues.SCOORD,
119-
ValueTypeValues.SCOORD3D)):
120-
n_image_region_items += 1
121-
if (item.name == codes.DCM.VolumeSurface and
122-
item.value_type == ValueTypeValues.SCOORD3D):
120+
if item.name == codes.DCM.ImageRegion:
121+
if item.value_type == ValueTypeValues.SCOORD:
122+
n_image_region_items += 1
123+
if item.value_type == ValueTypeValues.SCOORD3D:
124+
n_image_region_3d_items += 1
125+
if (
126+
item.name == codes.DCM.VolumeSurface and
127+
item.value_type == ValueTypeValues.SCOORD3D
128+
):
123129
n_volume_surface_items += 1
124-
if (item.name == codes.DCM.ReferencedSegment and
125-
item.value_type == ValueTypeValues.IMAGE):
130+
if (
131+
item.name == codes.DCM.ReferencedSegment and
132+
item.value_type == ValueTypeValues.IMAGE
133+
):
126134
n_referenced_segment_items += 1
127-
if (item.name == codes.DCM.ReferencedSegmentationFrame and
128-
item.value_type == ValueTypeValues.IMAGE):
135+
if (
136+
item.name == codes.DCM.ReferencedSegmentationFrame and
137+
item.value_type == ValueTypeValues.IMAGE
138+
):
129139
n_referenced_segmentation_frame_items += 1
130-
if (item.name == _REGION_IN_SPACE and
131-
item.value_type == ValueTypeValues.COMPOSITE):
140+
if (
141+
item.name == _REGION_IN_SPACE and
142+
item.value_type == ValueTypeValues.COMPOSITE
143+
):
132144
n_region_in_space_items += 1
133145
return (
134146
n_image_region_items,
147+
n_image_region_3d_items,
135148
n_volume_surface_items,
136149
n_referenced_segment_items,
137150
n_referenced_segmentation_frame_items,
@@ -154,12 +167,17 @@ def _contains_planar_rois(group_item: ContainerContentItem) -> bool:
154167
SCOORD, SCOORD3D, IMAGE, or COMPOSITE representing planar ROIs
155168
156169
"""
157-
n_image_region_items, n_volume_surface_items, n_referenced_segment_items, \
158-
n_referenced_segmentation_frame_items, n_region_in_space_items = \
159-
_count_roi_items(group_item)
170+
(
171+
n_image_region_items,
172+
n_image_region_3d_items,
173+
n_volume_surface_items,
174+
n_referenced_segment_items,
175+
n_referenced_segmentation_frame_items,
176+
n_region_in_space_items
177+
) = _count_roi_items(group_item)
160178

161179
if (
162-
n_image_region_items == 1 or
180+
(n_image_region_items + n_image_region_3d_items) == 1 or
163181
n_referenced_segmentation_frame_items > 0 or
164182
n_region_in_space_items == 1
165183
) and (
@@ -185,17 +203,27 @@ def _contains_volumetric_rois(group_item: ContainerContentItem) -> bool:
185203
SCOORD, SCOORD3D, IMAGE, or COMPOSITE representing volumetric ROIs
186204
187205
"""
188-
n_image_region_items, n_volume_surface_items, n_referenced_segment_items, \
189-
n_referenced_segmentation_frame_items, n_region_in_space_items = \
190-
_count_roi_items(group_item)
206+
(
207+
n_image_region_items,
208+
n_image_region_3d_items,
209+
n_volume_surface_items,
210+
n_referenced_segment_items,
211+
n_referenced_segmentation_frame_items,
212+
n_region_in_space_items
213+
) = _count_roi_items(group_item)
191214

192215
if (
216+
# A single image region (SCOORD) item could be either a planar or
217+
# volumetric ROI, they cannot be distinguished without the template
218+
# identifier. In this situation, we consider a single image region
219+
# item to be a planar ROI
193220
n_image_region_items > 1 or
194221
n_referenced_segment_items > 0 or
195222
n_volume_surface_items > 0 or
196223
n_region_in_space_items > 0
197224
) and (
198-
n_referenced_segmentation_frame_items == 0
225+
n_referenced_segmentation_frame_items == 0 and
226+
n_image_region_3d_items == 0
199227
):
200228
return True
201229
return False

0 commit comments

Comments
 (0)