Skip to content

Commit 1384e61

Browse files
committed
ModelInfo arg added to DICOMSegWriterOp
Signed-off-by: bluna301 <[email protected]>
1 parent 114950d commit 1384e61

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

monai/deploy/operators/dicom_seg_writer_operator.py

+41-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2021-2023 MONAI Consortium
1+
# Copyright 2021-2025 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
@@ -27,6 +27,7 @@
2727
ImplicitVRLittleEndian, _ = optional_import("pydicom.uid", name="ImplicitVRLittleEndian")
2828
Dataset, _ = optional_import("pydicom.dataset", name="Dataset")
2929
FileDataset, _ = optional_import("pydicom.dataset", name="FileDataset")
30+
PyDicomSequence, _ = optional_import("pydicom.sequence", name="Sequence")
3031
sitk, _ = optional_import("SimpleITK")
3132
codes, _ = optional_import("pydicom.sr.codedict", name="codes")
3233
if TYPE_CHECKING:
@@ -39,6 +40,7 @@
3940
from monai.deploy.core import ConditionType, Fragment, Image, Operator, OperatorSpec
4041
from monai.deploy.core.domain.dicom_series import DICOMSeries
4142
from monai.deploy.core.domain.dicom_series_selection import StudySelectedSeries
43+
from monai.deploy.operators.dicom_utils import ModelInfo
4244

4345

4446
class SegmentDescription:
@@ -183,6 +185,7 @@ def __init__(
183185
*args,
184186
segment_descriptions: List[SegmentDescription],
185187
output_folder: Path,
188+
model_info: Optional[ModelInfo] = None,
186189
custom_tags: Optional[Dict[str, str]] = None,
187190
omit_empty_frames: bool = True,
188191
**kwargs,
@@ -206,6 +209,7 @@ def __init__(
206209
Object encapsulating the description of each segment present in the segmentation.
207210
output_folder: Folder for file output, overridden by named input on compute.
208211
Defaults to current working dir's child folder, output.
212+
model_info (ModelInfo, optional): Object encapsulating model creator, name, version and UID.
209213
custom_tags: Optional[Dict[str, str]], optional
210214
Dictionary for setting custom DICOM tags using Keywords and str values only
211215
omit_empty_frames: bool, optional
@@ -217,6 +221,7 @@ def __init__(
217221
self._custom_tags = custom_tags
218222
self._omit_empty_frames = omit_empty_frames
219223
self.output_folder = output_folder if output_folder else DICOMSegmentationWriterOperator.DEFAULT_OUTPUT_FOLDER
224+
self.model_info = model_info if model_info else ModelInfo()
220225

221226
self.input_name_seg = "seg_image"
222227
self.input_name_series = "study_selected_series_list"
@@ -356,6 +361,41 @@ def create_dicom_seg(self, image: np.ndarray, dicom_series: DICOMSeries, output_
356361
# Best effort for now.
357362
logging.warning(f"Tag {k} was not written, due to {ex}")
358363

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+
359399
seg.save_as(output_path)
360400

361401
try:

0 commit comments

Comments
 (0)