1- # Copyright 2021-2025 MONAI Consortium
1+ # Copyright 2021-2023 MONAI Consortium
22# Licensed under the Apache License, Version 2.0 (the "License");
33# you may not use this file except in compliance with the License.
44# You may obtain a copy of the License at
2727ImplicitVRLittleEndian , _ = optional_import ("pydicom.uid" , name = "ImplicitVRLittleEndian" )
2828Dataset , _ = optional_import ("pydicom.dataset" , name = "Dataset" )
2929FileDataset , _ = optional_import ("pydicom.dataset" , name = "FileDataset" )
30- PyDicomSequence , _ = optional_import ("pydicom.sequence" , name = "Sequence" )
3130sitk , _ = optional_import ("SimpleITK" )
3231codes , _ = optional_import ("pydicom.sr.codedict" , name = "codes" )
3332if TYPE_CHECKING :
4039from monai .deploy .core import ConditionType , Fragment , Image , Operator , OperatorSpec
4140from monai .deploy .core .domain .dicom_series import DICOMSeries
4241from monai .deploy .core .domain .dicom_series_selection import StudySelectedSeries
43- from monai .deploy .operators .dicom_utils import ModelInfo
4442
4543
4644class SegmentDescription :
@@ -185,7 +183,6 @@ def __init__(
185183 * args ,
186184 segment_descriptions : List [SegmentDescription ],
187185 output_folder : Path ,
188- model_info : Optional [ModelInfo ] = None ,
189186 custom_tags : Optional [Dict [str , str ]] = None ,
190187 omit_empty_frames : bool = True ,
191188 ** kwargs ,
@@ -209,8 +206,7 @@ def __init__(
209206 Object encapsulating the description of each segment present in the segmentation.
210207 output_folder: Folder for file output, overridden by named input on compute.
211208 Defaults to current working dir's child folder, output.
212- model_info (ModelInfo, optional): Object encapsulating model creator, name, version and UID.
213- custom_tags: Optional[Dict[str, str]], optional
209+ custom_tags: Optonal[Dict[str, str]], optional
214210 Dictionary for setting custom DICOM tags using Keywords and str values only
215211 omit_empty_frames: bool, optional
216212 Whether to omit frames that contain no segmented pixels from the output segmentation.
@@ -221,7 +217,6 @@ def __init__(
221217 self ._custom_tags = custom_tags
222218 self ._omit_empty_frames = omit_empty_frames
223219 self .output_folder = output_folder if output_folder else DICOMSegmentationWriterOperator .DEFAULT_OUTPUT_FOLDER
224- self .model_info = model_info if model_info else ModelInfo ()
225220
226221 self .input_name_seg = "seg_image"
227222 self .input_name_series = "study_selected_series_list"
@@ -293,10 +288,8 @@ def process_images(
293288 seg_image_numpy = image .asnumpy ()
294289 elif isinstance (image , (Path , str )):
295290 seg_image_numpy = self ._image_file_to_numpy (str (image ))
296- else :
297- if not isinstance (image , np .ndarray ):
298- raise ValueError ("'image' is not a numpy array, Image object, or supported image file." )
299- seg_image_numpy = image
291+ elif not isinstance (image , np .ndarray ):
292+ raise ValueError ("'image' is not a numpy array, Image object, or supported image file." )
300293
301294 # Pick DICOM Series that was used as input for getting the seg image.
302295 # For now, first one in the list.
@@ -361,41 +354,6 @@ def create_dicom_seg(self, image: np.ndarray, dicom_series: DICOMSeries, output_
361354 # Best effort for now.
362355 logging .warning (f"Tag { k } was not written, due to { ex } " )
363356
364- # write model info
365- # code copied from write_common_modules method in monai.deploy.operators.dicom_utils
366-
367- # Contributing Equipment Sequence
368- # The Creator shall describe each algorithm that was used to generate the results in the
369- # Contributing Equipment Sequence (0018,A001). Multiple items may be included. The Creator
370- # shall encode the following details in the Contributing Equipment Sequence:
371- # • Purpose of Reference Code Sequence (0040,A170) shall be (Newcode1, 99IHE, 1630 "Processing Algorithm")
372- # • Manufacturer (0008,0070)
373- # • Manufacturer’s Model Name (0008,1090)
374- # • Software Versions (0018,1020)
375- # • Device UID (0018,1002)
376-
377- if self .model_info :
378- # First create the Purpose of Reference Code Sequence
379- seq_purpose_of_reference_code = PyDicomSequence ()
380- seg_purpose_of_reference_code = Dataset ()
381- seg_purpose_of_reference_code .CodeValue = "Newcode1"
382- seg_purpose_of_reference_code .CodingSchemeDesignator = "99IHE"
383- seg_purpose_of_reference_code .CodeMeaning = '"Processing Algorithm'
384- seq_purpose_of_reference_code .append (seg_purpose_of_reference_code )
385-
386- seq_contributing_equipment = PyDicomSequence ()
387- seg_contributing_equipment = Dataset ()
388- seg_contributing_equipment .PurposeOfReferenceCodeSequence = seq_purpose_of_reference_code
389- # '(121014, DCM, “Device Observer Manufacturer")'
390- seg_contributing_equipment .Manufacturer = self .model_info .creator
391- # u'(121015, DCM, “Device Observer Model Name")'
392- seg_contributing_equipment .ManufacturerModelName = self .model_info .name
393- # u'(111003, DCM, “Algorithm Version")'
394- seg_contributing_equipment .SoftwareVersions = self .model_info .version
395- seg_contributing_equipment .DeviceUID = self .model_info .uid # u'(121012, DCM, “Device Observer UID")'
396- seq_contributing_equipment .append (seg_contributing_equipment )
397- seg .ContributingEquipmentSequence = seq_contributing_equipment
398-
399357 seg .save_as (output_path )
400358
401359 try :
0 commit comments