Skip to content

Commit d017501

Browse files
MMelQinSimoneBendazzoli93
authored andcommitted
Address a removed monai function, fix CUDA 11 runtime lib, and resurrect option to omit or not DICOM SEG empty frame (Project-MONAI#471)
* Updated the code where a deprecated monai core function is used. Signed-off-by: M Q <[email protected]> * Add back the option for if omitting DICOM SEG empty frames, defaults to true. Signed-off-by: M Q <[email protected]> * Pin torch to ~=2.0.1 for libcudart.11.0 Signed-off-by: M Q <[email protected]> * Test packages Signed-off-by: M Q <[email protected]> --------- Signed-off-by: M Q <[email protected]> Signed-off-by: Simone Bendazzoli <[email protected]>
1 parent 6c0f134 commit d017501

File tree

6 files changed

+1281
-1037
lines changed

6 files changed

+1281
-1037
lines changed

.github/workflows/pr.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ jobs:
3030
python3 -c 'import sys; print(sys.executable)'
3131
python3 -c 'import site; print(site.getsitepackages())'
3232
python3 -m pip freeze
33+
export LD_LIBRARY_PATH=`pwd`/.venv/lib/python3.8/site-packages/nvidia/cuda_runtime/lib:$LD_LIBRARY_PATH
3334
python3 -c 'from holoscan.core import *'
34-
./run check -f
35+
./run check -f
3536
- name: Run Unit tests
3637
run: |
3738
source .venv/bin/activate

monai/deploy/operators/dicom_seg_writer_operator.py

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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
@@ -27,7 +27,6 @@
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")
3130
sitk, _ = optional_import("SimpleITK")
3231
codes, _ = optional_import("pydicom.sr.codedict", name="codes")
3332
if TYPE_CHECKING:
@@ -40,7 +39,6 @@
4039
from monai.deploy.core import ConditionType, Fragment, Image, Operator, OperatorSpec
4140
from monai.deploy.core.domain.dicom_series import DICOMSeries
4241
from monai.deploy.core.domain.dicom_series_selection import StudySelectedSeries
43-
from monai.deploy.operators.dicom_utils import ModelInfo
4442

4543

4644
class 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

Comments
 (0)