Skip to content

Commit 292c70c

Browse files
Refactor nnUNet bundle inference operator to MONetBundleInferenceOperator and add implementation
Signed-off-by: Simone Bendazzoli <simben@kth.se>
1 parent 9036d24 commit 292c70c

File tree

4 files changed

+35
-137
lines changed

4 files changed

+35
-137
lines changed

examples/apps/ai_spleen_nnunet_seg_app/app.py

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,49 +22,32 @@
2222
from monai.deploy.operators.dicom_seg_writer_operator import DICOMSegmentationWriterOperator, SegmentDescription
2323
from monai.deploy.operators.dicom_series_selector_operator import DICOMSeriesSelectorOperator
2424
from monai.deploy.operators.dicom_series_to_volume_operator import DICOMSeriesToVolumeOperator
25-
<<<<<<< HEAD
26-
from monai.deploy.operators.monai_bundle_inference_operator import BundleConfigNames, IOMapping
27-
from monai.deploy.operators.monet_bundle_inference_operator import MONetBundleInferenceOperator
28-
=======
2925
from monai.deploy.operators.monai_bundle_inference_operator import (
3026
BundleConfigNames,
3127
IOMapping,
3228

3329
)
34-
from monai.deploy.operators.monai_nnunet_bundle_inference_operator import MonainnUNetBundleInferenceOperator
35-
>>>>>>> dacfaa9 (Add nnUNet segmentation application and dependencies)
30+
from monai.deploy.operators.monai_nnunet_bundle_inference_operator import MONetBundleInferenceOperator
3631
from monai.deploy.operators.stl_conversion_operator import STLConversionOperator
3732

3833

3934
# @resource(cpu=1, gpu=1, memory="7Gi")
4035
# pip_packages can be a string that is a path(str) to requirements.txt file or a list of packages.
4136
# The monai pkg is not required by this class, instead by the included operators.
4237
class AISpleennnUNetSegApp(Application):
43-
<<<<<<< HEAD
44-
"""Demonstrates inference with built-in MONet Bundle inference operator with DICOM files as input/output
45-
46-
This application loads a set of DICOM instances, select the appropriate series, converts the series to
47-
3D volume image, performs inference with the built-in MONet Bundle inference operator, including nnUNet resampling, pre-processing
48-
=======
4938
"""Demonstrates inference with built-in MONAI nnUNet Bundle inference operator with DICOM files as input/output
5039
5140
This application loads a set of DICOM instances, select the appropriate series, converts the series to
5241
3D volume image, performs inference with the built-in MONAI nnUNet Bundle inference operator, including pre-processing
53-
>>>>>>> dacfaa9 (Add nnUNet segmentation application and dependencies)
5442
and post-processing, save the segmentation image in a DICOM Seg OID in an instance file, and optionally the
5543
surface mesh in STL format.
5644
5745
Pertinent nnUNet MONAI Bundle:
5846
<Upload to the MONAI Model Zoo>
5947
6048
Execution Time Estimate:
61-
<<<<<<< HEAD
62-
With a Nvidia RTXA600 48GB GPU, for an input DICOM Series of size 106x415x415 and patches of size 64x192x160, the execution time is around
63-
50 seconds with saving both DICOM Seg and surface mesh STL file.
64-
=======
6549
With a Nvidia RTXA600 48GB GPU, for an input DICOM Series of 139 instances, the execution time is around
6650
75 seconds with saving both DICOM Seg and surface mesh STL file.
67-
>>>>>>> dacfaa9 (Add nnUNet segmentation application and dependencies)
6851
"""
6952

7053
def __init__(self, *args, **kwargs):
@@ -104,11 +87,7 @@ def compose(self):
10487

10588
config_names = BundleConfigNames(config_names=["inference"]) # Same as the default
10689

107-
<<<<<<< HEAD
10890
bundle_spleen_seg_op = MONetBundleInferenceOperator(
109-
=======
110-
bundle_spleen_seg_op = MonainnUNetBundleInferenceOperator(
111-
>>>>>>> dacfaa9 (Add nnUNet segmentation application and dependencies)
11291
self,
11392
input_mapping=[IOMapping("image", Image, IOType.IN_MEMORY)],
11493
output_mapping=[IOMapping("pred", Image, IOType.IN_MEMORY)],
@@ -183,8 +162,6 @@ def compose(self):
183162
"""
184163

185164
if __name__ == "__main__":
186-
<<<<<<< HEAD
187-
=======
188165
# Creates the app and test it standalone. When running is this mode, please note the following:
189166
# -m <model file>, for model file path
190167
# -i <DICOM folder>, for input DICOM CT series folder
@@ -195,7 +172,6 @@ def compose(self):
195172
# export HOLOSCAN_INPUT_PATH=dcm
196173
# export HOLOSCAN_MODEL_PATH=spleen_model/model.ts
197174
# export HOLOSCAN_OUTPUT_PATH="output"
198-
>>>>>>> dacfaa9 (Add nnUNet segmentation application and dependencies)
199175
logging.info(f"Begin {__name__}")
200176
AISpleennnUNetSegApp().run()
201177
logging.info(f"End {__name__}")

monai/deploy/operators/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
from .dicom_utils import EquipmentInfo, ModelInfo, random_with_n_digits, save_dcm_file, write_common_modules
5353
from .inference_operator import InferenceOperator
5454
from .monai_bundle_inference_operator import BundleConfigNames, IOMapping, MonaiBundleInferenceOperator
55-
from .monai_nnunet_bundle_inference_operator import MonainnUNetBundleInferenceOperator
55+
from .monet_bundle_inference_operator import MONetBundleInferenceOperator
5656
from .monai_seg_inference_operator import MonaiSegInferenceOperator
5757
from .monet_bundle_inference_operator import MONetBundleInferenceOperator
5858
from .nii_data_loader_operator import NiftiDataLoader

monai/deploy/operators/monai_nnunet_bundle_inference_operator.py

Lines changed: 0 additions & 89 deletions
This file was deleted.

monai/deploy/operators/monet_bundle_inference_operator.py

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,47 @@
99
# See the License for the specific language governing permissions and
1010
# limitations under the License.
1111

12-
from typing import Any, Dict, Tuple, Union
13-
14-
from monai.deploy.core import Image
1512
from monai.deploy.operators.monai_bundle_inference_operator import MonaiBundleInferenceOperator, get_bundle_config
1613
from monai.deploy.utils.importutil import optional_import
17-
from monai.transforms import ConcatItemsd, ResampleToMatch
14+
from typing import Any, Dict, Tuple, Union
15+
from monai.deploy.core import Image
1816

17+
MONAI_UTILS = "monai.utils"
18+
nibabel, _ = optional_import("nibabel", "3.2.1")
1919
torch, _ = optional_import("torch", "1.10.2")
20+
21+
NdarrayOrTensor, _ = optional_import("monai.config", name="NdarrayOrTensor")
2022
MetaTensor, _ = optional_import("monai.data.meta_tensor", name="MetaTensor")
23+
PostFix, _ = optional_import("monai.utils.enums", name="PostFix") # For the default meta_key_postfix
24+
first, _ = optional_import("monai.utils.misc", name="first")
25+
ensure_tuple, _ = optional_import(MONAI_UTILS, name="ensure_tuple")
26+
convert_to_dst_type, _ = optional_import(MONAI_UTILS, name="convert_to_dst_type")
27+
Key, _ = optional_import(MONAI_UTILS, name="ImageMetaKey")
28+
MetaKeys, _ = optional_import(MONAI_UTILS, name="MetaKeys")
29+
SpaceKeys, _ = optional_import(MONAI_UTILS, name="SpaceKeys")
30+
Compose_, _ = optional_import("monai.transforms", name="Compose")
31+
ConfigParser_, _ = optional_import("monai.bundle", name="ConfigParser")
32+
MapTransform_, _ = optional_import("monai.transforms", name="MapTransform")
33+
SimpleInferer, _ = optional_import("monai.inferers", name="SimpleInferer")
34+
35+
Compose: Any = Compose_
36+
MapTransform: Any = MapTransform_
37+
ConfigParser: Any = ConfigParser_
2138
__all__ = ["MONetBundleInferenceOperator"]
2239

2340

2441
class MONetBundleInferenceOperator(MonaiBundleInferenceOperator):
2542
"""
26-
A specialized operator for performing inference using the MONet bundle.
43+
A specialized operator for performing inference using the MONAI nnUNet bundle.
2744
This operator extends the `MonaiBundleInferenceOperator` to support nnUNet-specific
2845
configurations and prediction logic. It initializes the nnUNet predictor and provides
2946
a method for performing inference on input data.
30-
47+
3148
Attributes
3249
----------
3350
_nnunet_predictor : torch.nn.Module
3451
The nnUNet predictor module used for inference.
35-
52+
3653
Methods
3754
-------
3855
_init_config(config_names)
@@ -48,31 +65,25 @@ def __init__(
4865
**kwargs,
4966
):
5067

51-
super().__init__(*args, **kwargs)
52-
53-
self._nnunet_predictor: torch.nn.Module = None
5468

55-
def _init_config(self, config_names):
69+
super().__init__(*args, **kwargs)
70+
71+
self._nnunet_predictor : torch.nn.Module = None
72+
73+
74+
def _init_config(self, config_names):
5675

5776
super()._init_config(config_names)
58-
parser = get_bundle_config(str(self._bundle_path), config_names)
77+
parser = get_bundle_config(str(self._bundle_path), config_names)
5978
self._parser = parser
6079

6180
self._nnunet_predictor = parser.get_parsed_content("network_def")
6281

6382
def predict(self, data: Any, *args, **kwargs) -> Union[Image, Any, Tuple[Any, ...], Dict[Any, Any]]:
64-
"""Predicts output using the inferer. If multimodal data is provided as keyword arguments,
65-
it concatenates the data with the main input data."""
83+
"""Predicts output using the inferer."""
6684

6785
self._nnunet_predictor.predictor.network = self._model_network
68-
69-
if len(kwargs) > 0:
70-
multimodal_data = {"image": data}
71-
for key in kwargs.keys():
72-
if isinstance(kwargs[key], MetaTensor):
73-
multimodal_data[key] = ResampleToMatch(mode="bilinear")(kwargs[key], img_dst=data
74-
)
75-
data = ConcatItemsd(keys=list(multimodal_data.keys()),name="image")(multimodal_data)["image"]
86+
#os.environ['nnUNet_def_n_proc'] = "1"
7687
if len(data.shape) == 4:
7788
data = data[None]
7889
return self._nnunet_predictor(data)

0 commit comments

Comments
 (0)