diff --git a/src/highdicom/seg/content.py b/src/highdicom/seg/content.py index 29dca91a..2cf6a845 100644 --- a/src/highdicom/seg/content.py +++ b/src/highdicom/seg/content.py @@ -340,11 +340,7 @@ def __init__( segment_number_index.DimensionDescriptionLabel = 'Segment Number' self.append(segment_number_index) - if self._coordinate_system is None: - # TODO what on earth to do here? - pass - - elif self._coordinate_system == CoordinateSystemNames.SLIDE: + if self._coordinate_system == CoordinateSystemNames.SLIDE: x_axis_index = Dataset() x_axis_index.DimensionIndexPointer = tag_for_keyword( @@ -428,6 +424,19 @@ def __init__( self.append(image_position_index) + elif self._coordinate_system is None: + if not include_segment_number: + # Use frame label here just for the sake of using something + frame_label_index = Dataset() + frame_label_index.DimensionIndexPointer = tag_for_keyword( + 'FrameLabel' + ) + frame_label_index.FunctionalGroupPointer = tag_for_keyword( + 'FrameContentSequence' + ) + frame_label_index.DimensionOrganizationUID = dim_uid + frame_label_index.DimensionDescriptionLabel = 'Frame Label' + self.append(frame_label_index) else: raise ValueError( f'Unknown coordinate system "{self._coordinate_system}"' diff --git a/src/highdicom/seg/sop.py b/src/highdicom/seg/sop.py index c4154331..787505ca 100644 --- a/src/highdicom/seg/sop.py +++ b/src/highdicom/seg/sop.py @@ -1546,6 +1546,7 @@ def __init__( plane_position_values=plane_position_values, has_ref_frame_uid=has_ref_frame_uid, coordinate_system=self._coordinate_system, + segmentation_type=segmentation_type, ) pffg_item = self._get_pffg_item( segment_number=segment_number, @@ -2123,6 +2124,7 @@ def _get_dimension_index_values( plane_position_values: np.ndarray, has_ref_frame_uid: bool, coordinate_system: Optional[CoordinateSystemNames], + segmentation_type: SegmentationTypeValues, ) -> List[int]: """Get dimension index values for a frame. @@ -2147,7 +2149,13 @@ def _get_dimension_index_values( """ if not has_ref_frame_uid: - index_values = [] + if segmentation_type == SegmentationTypeValues.LABELMAP: + # Here we have to return the "Frame Label" dimension value + # (which is used just to have one index since Referenced + # Segment cannot be used) + index_values = [1] + else: + index_values = [] else: # Look up the position of the plane relative to the indexed # dimension. @@ -2243,6 +2251,13 @@ def _get_pffg_item( else: all_index_values = [int(segment_number)] + index_values frame_content_item.DimensionIndexValues = all_index_values + + # If this is an labelmap segmentation of an image that has no frame + # of reference, we need to create a dummy frame label to be pointed to + # as a dimension index because there is nothing else appropriate to + # use + if segment_number is None and coordinate_system is None: + frame_content_item.FrameLabel = "Segmentation Frame" pffg_item.FrameContentSequence = [frame_content_item] if has_ref_frame_uid: if coordinate_system == CoordinateSystemNames.SLIDE: diff --git a/tests/test_seg.py b/tests/test_seg.py index 32c47cde..51d3d2b6 100644 --- a/tests/test_seg.py +++ b/tests/test_seg.py @@ -1413,6 +1413,35 @@ def test_construction_7(self): assert SegmentsOverlapValues[instance.SegmentsOverlap] == \ SegmentsOverlapValues.NO + def test_construction_8(self): + # A chest X-ray with no frame of reference, LABELMAP + instance = Segmentation( + [self._cr_image], + self._cr_pixel_array, + SegmentationTypeValues.LABELMAP, + self._segment_descriptions, + self._series_instance_uid, + self._series_number, + self._sop_instance_uid, + self._instance_number, + self._manufacturer, + self._manufacturer_model_name, + self._software_versions, + self._device_serial_number, + content_label=self._content_label + ) + assert ( + instance.DimensionIndexSequence[0].DimensionIndexPointer == + tag_for_keyword('FrameLabel') + ) + dim_ind_vals = ( + instance + .PerFrameFunctionalGroupsSequence[0] + .FrameContentSequence[0] + .DimensionIndexValues + ) + assert dim_ind_vals == 1 + def test_pixel_types_fractional( self, fractional_transfer_syntax_uid,