Creating a Deploy App for Multi-Ai with Multiple Models

This tutorial shows how to create an inference application with multiple models, focusing on model files organization, inferring with named model in the application, and packaging.

Typically multiple models will work in tandem, e.g. a lung segmentation model’s output, along with the original image, are be used by a lung nodule detection and classification model. However, there are currently no such models in the MONAI Model Zoo, so two independent models will be used in this example, Spleen Segmentation and Pancreas Segmentation, both are trained with DICOM images of CT modality, and both are packaged in the MONAI Bundle format. A single input of a CT Abdomen DICOM Series can be used for both models within the application.

Important Steps

  • Place the model TorchScripts in a defined folder structure, see below for details

  • Pass the model name to the inference operator instance in the app

  • Connect the input to and output from the inference operators, as required by the app

Required Model File Organization

  • The model files in TorchScript, be it MONAI Bundle compliant or not, must each be placed in an uniquely named folder. The name of this folder is used within the application to retrieve the loaded model network from the execution context.

  • The folders containing the individual model file must then be place under a parent folder. The name of this folder can be any valid folder name chosen by the application developer.

Example Model File Organization

In this example, the models are organized as shown below.

multi_models
├── pancreas_ct_dints
│   └── model.ts
└── spleen_ct
    └── model.ts

Please note,

  • The multi_models is parent folder, and its path will be used as the model path when using App SDK CLI exec and package commands.

  • The sub-folder names become model names, pancreas_ct_dints and spleen_model, respectively.

In the following sections, we will demonstrate how to create and package the application using these two models.

Note

The two models are both MONAI bundles, published in MONAI Model Zoo

The DICOM CT series used as test input is downloaded from TCIA, CT Abdomen Collection ID CPTAC-PDA Subject ID C3N-00198.

Both the DICOM files and the models have been packaged and shared on Google Drive.

Creating Operators and connecting them in Application class

We will implement an application that consists of seven Operators:

  • DICOMDataLoaderOperator:

    • Input(dicom_files): a folder path (DataPath)

    • Output(dicom_study_list): a list of DICOM studies in memory (List[DICOMStudy])

  • DICOMSeriesSelectorOperator:

    • Input(dicom_study_list): a list of DICOM studies in memory (List[DICOMStudy])

    • Input(selection_rules): a selection rule (Dict)

    • Output(study_selected_series_list): a DICOM series object in memory (StudySelectedSeries)

  • DICOMSeriesToVolumeOperator:

    • Input(study_selected_series_list): a DICOM series object in memory (StudySelectedSeries)

    • Output(image): an image object in memory (Image)

  • MonaiBundleInferenceOperator x 2:

    • Input(image): an image object in memory (Image)

    • Output(pred): an image object in memory (Image)

  • DICOMSegmentationWriterOperator x2:

    • Input(seg_image): a segmentation image object in memory (Image)

    • Input(study_selected_series_list): a DICOM series object in memory (StudySelectedSeries)

    • Output(dicom_seg_instance): a file path (DataPath)

Note

The DICOMSegmentationWriterOperator needs both the segmentation image as well as the original DICOM series meta-data in order to use the patient demographics and the DICOM Study level attributes.

The workflow of the application is illustrated below.

%%{init: {"theme": "base", "themeVariables": { "fontSize": "16px"}} }%% classDiagram direction TB DICOMDataLoaderOperator --|> DICOMSeriesSelectorOperator : dicom_study_list...dicom_study_list DICOMSeriesSelectorOperator --|> DICOMSeriesToVolumeOperator : study_selected_series_list...study_selected_series_list DICOMSeriesToVolumeOperator --|> Spleen_BundleInferenceOperator : image...image DICOMSeriesSelectorOperator --|> Spleen_DICOMSegmentationWriterOperator : study_selected_series_list...study_selected_series_list Spleen_BundleInferenceOperator --|> Spleen_DICOMSegmentationWriterOperator : pred...seg_image DICOMSeriesToVolumeOperator --|> Pancreas_BundleInferenceOperator : image...image DICOMSeriesSelectorOperator --|> Pancreas_DICOMSegmentationWriterOperator : study_selected_series_list...study_selected_series_list Pancreas_BundleInferenceOperator --|> Pancreas_DICOMSegmentationWriterOperator : pred...seg_image class DICOMDataLoaderOperator { <in>dicom_files : DISK dicom_study_list(out) IN_MEMORY } class DICOMSeriesSelectorOperator { <in>dicom_study_list : IN_MEMORY <in>selection_rules : IN_MEMORY study_selected_series_list(out) IN_MEMORY } class DICOMSeriesToVolumeOperator { <in>study_selected_series_list : IN_MEMORY image(out) IN_MEMORY } class Spleen_BundleInferenceOperator { <in>image : IN_MEMORY pred(out) IN_MEMORY } class Pancreas_BundleInferenceOperator { <in>image : IN_MEMORY pred(out) IN_MEMORY } class Spleen_DICOMSegmentationWriterOperator { <in>seg_image : IN_MEMORY <in>study_selected_series_list : IN_MEMORY dicom_seg_instance(out) DISK } class Pancreas_DICOMSegmentationWriterOperator { <in>seg_image : IN_MEMORY <in>study_selected_series_list : IN_MEMORY dicom_seg_instance(out) DISK }

Setup environment

# Install MONAI and other necessary image processing packages for the application
!python -c "import monai" || pip install --upgrade -q "monai"
!python -c "import torch" || pip install -q "torch>=1.12.0"
!python -c "import numpy" || pip install -q "numpy>=1.21"
!python -c "import nibabel" || pip install -q "nibabel>=3.2.1"
!python -c "import pydicom" || pip install -q "pydicom>=1.4.2"
!python -c "import highdicom" || pip install -q "highdicom>=0.18.2"
!python -c "import SimpleITK" || pip install -q "SimpleITK>=2.0.0"
!python -c "import typeguard" || pip install -q "typeguard~=2.12.1"

# Install MONAI Deploy App SDK package
!python -c "import monai.deploy" || pip install --upgrade -q "monai-deploy-app-sdk"

Note: you may need to restart the Jupyter kernel to use the updated packages.

Download/Extract input and model/bundle files from Google Drive

# Download the test data and MONAI bundle zip file
!pip install gdown 
!gdown "https://drive.google.com/uc?id=1llJ4NGNTjY187RLX4MtlmHYhfGxBNWmd"

# After downloading ai_spleen_bundle_data zip file from the web browser or using gdown,
!unzip -o "ai_multi_model_bundle_data.zip"
Requirement already satisfied: gdown in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (4.5.1)
Requirement already satisfied: beautifulsoup4 in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from gdown) (4.11.1)
Requirement already satisfied: six in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from gdown) (1.16.0)
Requirement already satisfied: filelock in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from gdown) (3.8.0)
Requirement already satisfied: requests[socks] in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from gdown) (2.28.1)
Requirement already satisfied: tqdm in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from gdown) (4.64.0)
Requirement already satisfied: soupsieve>1.2 in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from beautifulsoup4->gdown) (2.3.2.post1)
Requirement already satisfied: certifi>=2017.4.17 in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from requests[socks]->gdown) (2022.6.15)
Requirement already satisfied: idna<4,>=2.5 in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from requests[socks]->gdown) (3.3)
Requirement already satisfied: charset-normalizer<3,>=2 in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from requests[socks]->gdown) (2.1.1)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from requests[socks]->gdown) (1.26.12)
Requirement already satisfied: PySocks!=1.5.7,>=1.5.6 in /home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages (from requests[socks]->gdown) (1.7.1)
Downloading...
From: https://drive.google.com/uc?id=1llJ4NGNTjY187RLX4MtlmHYhfGxBNWmd
To: /home/mqin/src/monai-deploy-app-sdk/notebooks/tutorials/ai_multi_model_bundle_data.zip
100%|█████████████████████████████████████████| 647M/647M [00:05<00:00, 114MB/s]
Archive:  ai_multi_model_bundle_data.zip
  inflating: dcm/1-001.dcm           
  inflating: dcm/1-002.dcm           
  inflating: dcm/1-003.dcm           
  inflating: dcm/1-004.dcm           
  inflating: dcm/1-005.dcm           
  inflating: dcm/1-006.dcm           
  inflating: dcm/1-007.dcm           
  inflating: dcm/1-008.dcm           
  inflating: dcm/1-009.dcm           
  inflating: dcm/1-010.dcm           
  inflating: dcm/1-011.dcm           
  inflating: dcm/1-012.dcm           
  inflating: dcm/1-013.dcm           
  inflating: dcm/1-014.dcm           
  inflating: dcm/1-015.dcm           
  inflating: dcm/1-016.dcm           
  inflating: dcm/1-017.dcm           
  inflating: dcm/1-018.dcm           
  inflating: dcm/1-019.dcm           
  inflating: dcm/1-020.dcm           
  inflating: dcm/1-021.dcm           
  inflating: dcm/1-022.dcm           
  inflating: dcm/1-023.dcm           
  inflating: dcm/1-024.dcm           
  inflating: dcm/1-025.dcm           
  inflating: dcm/1-026.dcm           
  inflating: dcm/1-027.dcm           
  inflating: dcm/1-028.dcm           
  inflating: dcm/1-029.dcm           
  inflating: dcm/1-030.dcm           
  inflating: dcm/1-031.dcm           
  inflating: dcm/1-032.dcm           
  inflating: dcm/1-033.dcm           
  inflating: dcm/1-034.dcm           
  inflating: dcm/1-035.dcm           
  inflating: dcm/1-036.dcm           
  inflating: dcm/1-037.dcm           
  inflating: dcm/1-038.dcm           
  inflating: dcm/1-039.dcm           
  inflating: dcm/1-040.dcm           
  inflating: dcm/1-041.dcm           
  inflating: dcm/1-042.dcm           
  inflating: dcm/1-043.dcm           
  inflating: dcm/1-044.dcm           
  inflating: dcm/1-045.dcm           
  inflating: dcm/1-046.dcm           
  inflating: dcm/1-047.dcm           
  inflating: dcm/1-048.dcm           
  inflating: dcm/1-049.dcm           
  inflating: dcm/1-050.dcm           
  inflating: dcm/1-051.dcm           
  inflating: dcm/1-052.dcm           
  inflating: dcm/1-053.dcm           
  inflating: dcm/1-054.dcm           
  inflating: dcm/1-055.dcm           
  inflating: dcm/1-056.dcm           
  inflating: dcm/1-057.dcm           
  inflating: dcm/1-058.dcm           
  inflating: dcm/1-059.dcm           
  inflating: dcm/1-060.dcm           
  inflating: dcm/1-061.dcm           
  inflating: dcm/1-062.dcm           
  inflating: dcm/1-063.dcm           
  inflating: dcm/1-064.dcm           
  inflating: dcm/1-065.dcm           
  inflating: dcm/1-066.dcm           
  inflating: dcm/1-067.dcm           
  inflating: dcm/1-068.dcm           
  inflating: dcm/1-069.dcm           
  inflating: dcm/1-070.dcm           
  inflating: dcm/1-071.dcm           
  inflating: dcm/1-072.dcm           
  inflating: dcm/1-073.dcm           
  inflating: dcm/1-074.dcm           
  inflating: dcm/1-075.dcm           
  inflating: dcm/1-076.dcm           
  inflating: dcm/1-077.dcm           
  inflating: dcm/1-078.dcm           
  inflating: dcm/1-079.dcm           
  inflating: dcm/1-080.dcm           
  inflating: dcm/1-081.dcm           
  inflating: dcm/1-082.dcm           
  inflating: dcm/1-083.dcm           
  inflating: dcm/1-084.dcm           
  inflating: dcm/1-085.dcm           
  inflating: dcm/1-086.dcm           
  inflating: dcm/1-087.dcm           
  inflating: dcm/1-088.dcm           
  inflating: dcm/1-089.dcm           
  inflating: dcm/1-090.dcm           
  inflating: dcm/1-091.dcm           
  inflating: dcm/1-092.dcm           
  inflating: dcm/1-093.dcm           
  inflating: dcm/1-094.dcm           
  inflating: dcm/1-095.dcm           
  inflating: dcm/1-096.dcm           
  inflating: dcm/1-097.dcm           
  inflating: dcm/1-098.dcm           
  inflating: dcm/1-099.dcm           
  inflating: dcm/1-100.dcm           
  inflating: dcm/1-101.dcm           
  inflating: dcm/1-102.dcm           
  inflating: dcm/1-103.dcm           
  inflating: dcm/1-104.dcm           
  inflating: dcm/1-105.dcm           
  inflating: dcm/1-106.dcm           
  inflating: dcm/1-107.dcm           
  inflating: dcm/1-108.dcm           
  inflating: dcm/1-109.dcm           
  inflating: dcm/1-110.dcm           
  inflating: dcm/1-111.dcm           
  inflating: dcm/1-112.dcm           
  inflating: dcm/1-113.dcm           
  inflating: dcm/1-114.dcm           
  inflating: dcm/1-115.dcm           
  inflating: dcm/1-116.dcm           
  inflating: dcm/1-117.dcm           
  inflating: dcm/1-118.dcm           
  inflating: dcm/1-119.dcm           
  inflating: dcm/1-120.dcm           
  inflating: dcm/1-121.dcm           
  inflating: dcm/1-122.dcm           
  inflating: dcm/1-123.dcm           
  inflating: dcm/1-124.dcm           
  inflating: dcm/1-125.dcm           
  inflating: dcm/1-126.dcm           
  inflating: dcm/1-127.dcm           
  inflating: dcm/1-128.dcm           
  inflating: dcm/1-129.dcm           
  inflating: dcm/1-130.dcm           
  inflating: dcm/1-131.dcm           
  inflating: dcm/1-132.dcm           
  inflating: dcm/1-133.dcm           
  inflating: dcm/1-134.dcm           
  inflating: dcm/1-135.dcm           
  inflating: dcm/1-136.dcm           
  inflating: dcm/1-137.dcm           
  inflating: dcm/1-138.dcm           
  inflating: dcm/1-139.dcm           
  inflating: dcm/1-140.dcm           
  inflating: dcm/1-141.dcm           
  inflating: dcm/1-142.dcm           
  inflating: dcm/1-143.dcm           
  inflating: dcm/1-144.dcm           
  inflating: dcm/1-145.dcm           
  inflating: dcm/1-146.dcm           
  inflating: dcm/1-147.dcm           
  inflating: dcm/1-148.dcm           
  inflating: dcm/1-149.dcm           
  inflating: dcm/1-150.dcm           
  inflating: dcm/1-151.dcm           
  inflating: dcm/1-152.dcm           
  inflating: dcm/1-153.dcm           
  inflating: dcm/1-154.dcm           
  inflating: dcm/1-155.dcm           
  inflating: dcm/1-156.dcm           
  inflating: dcm/1-157.dcm           
  inflating: dcm/1-158.dcm           
  inflating: dcm/1-159.dcm           
  inflating: dcm/1-160.dcm           
  inflating: dcm/1-161.dcm           
  inflating: dcm/1-162.dcm           
  inflating: dcm/1-163.dcm           
  inflating: dcm/1-164.dcm           
  inflating: dcm/1-165.dcm           
  inflating: dcm/1-166.dcm           
  inflating: dcm/1-167.dcm           
  inflating: dcm/1-168.dcm           
  inflating: dcm/1-169.dcm           
  inflating: dcm/1-170.dcm           
  inflating: dcm/1-171.dcm           
  inflating: dcm/1-172.dcm           
  inflating: dcm/1-173.dcm           
  inflating: dcm/1-174.dcm           
  inflating: dcm/1-175.dcm           
  inflating: dcm/1-176.dcm           
  inflating: dcm/1-177.dcm           
  inflating: dcm/1-178.dcm           
  inflating: dcm/1-179.dcm           
  inflating: dcm/1-180.dcm           
  inflating: dcm/1-181.dcm           
  inflating: dcm/1-182.dcm           
  inflating: dcm/1-183.dcm           
  inflating: dcm/1-184.dcm           
  inflating: dcm/1-185.dcm           
  inflating: dcm/1-186.dcm           
  inflating: dcm/1-187.dcm           
  inflating: dcm/1-188.dcm           
  inflating: dcm/1-189.dcm           
  inflating: dcm/1-190.dcm           
  inflating: dcm/1-191.dcm           
  inflating: dcm/1-192.dcm           
  inflating: dcm/1-193.dcm           
  inflating: dcm/1-194.dcm           
  inflating: dcm/1-195.dcm           
  inflating: dcm/1-196.dcm           
  inflating: dcm/1-197.dcm           
  inflating: dcm/1-198.dcm           
  inflating: dcm/1-199.dcm           
  inflating: dcm/1-200.dcm           
  inflating: dcm/1-201.dcm           
  inflating: dcm/1-202.dcm           
  inflating: dcm/1-203.dcm           
  inflating: dcm/1-204.dcm           
  inflating: multi_models/pancreas_ct_dints/model.ts  
  inflating: multi_models/spleen_ct/model.ts  

Setup imports

Let’s import necessary classes/decorators to define Application and Operator.

import logging

# Required for setting SegmentDescription attributes. Direct import as this is not part of App SDK package.
from pydicom.sr.codedict import codes

import monai.deploy.core as md
from monai.deploy.core import Application, resource
from monai.deploy.core.domain import Image
from monai.deploy.core.io_type import IOType
from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator
from monai.deploy.operators.dicom_seg_writer_operator import DICOMSegmentationWriterOperator, SegmentDescription
from monai.deploy.operators.dicom_series_selector_operator import DICOMSeriesSelectorOperator
from monai.deploy.operators.dicom_series_to_volume_operator import DICOMSeriesToVolumeOperator
from monai.deploy.operators.monai_bundle_inference_operator import (
    BundleConfigNames,
    IOMapping,
    MonaiBundleInferenceOperator,
)

Determining the Model Name and IOfor the Model Bundle Inference Operator

The App SDK provides a MonaiBundleInferenceOperator class to perform inference with a MONAI Bundle, which is essentially a PyTorch model in TorchScript with additional metadata describing the model network and processing specification. This operator uses the MONAI utilities to parse a MONAI Bundle to automatically instantiate the objects required for input and output processing as well as inference, as such it depends on MONAI transforms, inferers, and in turn their dependencies.

Each Operator class inherits from the base Operator class, and its input/output properties are specified by using @input/@output decorators. For the MonaiBundleInferenceOperator class, the input/output need to be defined to match those of the model network, both in name and data type. For the current release, an IOMapping object is used to connect the operator input/output to those of the model network by using the same names. This is likely to change, to be automated, in the future releases once certain limitation in the App SDK is removed.

When multiple models are used in an application, it is important that each model network name is passed in when creating the inference operator, via the model_name argument.

The Spleen CT Segmentation and Pancreas model networks have a named input, called “image”, and the named output called “pred”, and both are of image type. These can all be mapped to the App SDK Image. This piece of information is typically acquired by examining the model metadata network_data_format attribute in the bundle, as seen in this [example] (https://github.com/Project-MONAI/model-zoo/blob/dev/models/spleen_ct_segmentation/configs/metadata.json).

Creating Application class

Our application class would look like below.

It defines App class, inheriting Application class.

The requirements (resource and package dependency) for the App can be specified by using @resource and @env decorators.

Objects required for DICOM parsing, series selection, pixel data conversion to volume image, model specific inference, and the AI result specific DICOM Segmentation object writers are created. The execution pipeline, as a Directed Acyclic Graph, is then constructed by connecting these objects through self.add_flow().

@resource(cpu=1, gpu=1, memory="7Gi")
# Enforcing torch>=1.12.0 because one of the Bundles/TorchScripts, Pancreas CT Seg, was created
# with this version, and would fail to jit.load with lower version of torch.
# The Bundle Inference Operator as of now only requires torch>=1.10.2, and does not yet dynamically
# parse the MONAI bundle to get the required pip package or ver on initialization, hence it does not set
# its own @env decorator accordingly when the app is being packaged into a MONAI Package.
@md.env(pip_packages=["torch>=1.12.0"])
# pip_packages can be a string that is a path(str) to requirements.txt file or a list of packages.
# The monai pkg is not required by this class, instead by the included operators.
class App(Application):
    """This example demonstrates how to create a multi-model/multi-AI application.

    The important steps are:
        1. Place the model TorchScripts in a defined folder structure, see below for details
        2. Pass the model name to the inference operator instance in the app
        3. Connect the input to and output from the inference operators, as required by the app

    Model organization for this example:

        multi_models
        ├── pancreas_ct_dints
        │   └── model.ts
        └── spleen_ct
            └── model.ts
    """

    def __init__(self, *args, **kwargs):
        """Creates an application instance."""
        self._logger = logging.getLogger("{}.{}".format(__name__, type(self).__name__))
        super().__init__(*args, **kwargs)

    def run(self, *args, **kwargs):
        # This method calls the base class to run. Can be omitted if simply calling through.
        self._logger.info(f"Begin {self.run.__name__}")
        super().run(*args, **kwargs)
        self._logger.info(f"End {self.run.__name__}")

    def compose(self):
        """Creates the app specific operators and chain them up in the processing DAG."""

        logging.info(f"Begin {self.compose.__name__}")

        # Create the custom operator(s) as well as SDK built-in operator(s).
        study_loader_op = DICOMDataLoaderOperator()
        series_selector_op = DICOMSeriesSelectorOperator(Sample_Rules_Text)
        series_to_vol_op = DICOMSeriesToVolumeOperator()

        # Create the inference operator that supports MONAI Bundle and automates the inference.
        # The IOMapping labels match the input and prediction keys in the pre and post processing.
        # The model_name is optional when the app has only one model.
        # The bundle_path argument optionally can be set to an accessible bundle file path in the dev
        # environment, so when the app is packaged into a MAP, the operator can complete the bundle parsing
        # during init to provide the optional packages info, parsed from the bundle, to the packager
        # for it to install the packages in the MAP docker image.
        # Setting output IOType to DISK only works only for leaf operators, not the case in this example.
        # When multiple models/bundles are supported, create an inference operator for each.
        #
        # Pertinent MONAI Bundle:
        #   https://github.com/Project-MONAI/model-zoo/tree/dev/models/spleen_ct_segmentation, v0.3.2
        #   https://github.com/Project-MONAI/model-zoo/tree/dev/models/pancreas_ct_dints_segmentation, v0.3

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

        # This is the inference operator for the spleen_model bundle. Note the model name.
        bundle_spleen_seg_op = MonaiBundleInferenceOperator(
            input_mapping=[IOMapping("image", Image, IOType.IN_MEMORY)],
            output_mapping=[IOMapping("pred", Image, IOType.IN_MEMORY)],
            bundle_config_names=config_names,
            model_name="spleen_ct",
        )

        # This is the inference operator for the pancreas_ct_dints bundle. Note the model name.
        bundle_pancreas_seg_op = MonaiBundleInferenceOperator(
            input_mapping=[IOMapping("image", Image, IOType.IN_MEMORY)],
            output_mapping=[IOMapping("pred", Image, IOType.IN_MEMORY)],
            model_name="pancreas_ct_dints",
        )

        # Create DICOM Seg writer providing the required segment description for each segment with
        # the actual algorithm and the pertinent organ/tissue. The segment_label, algorithm_name,
        # and algorithm_version are of DICOM VR LO type, limited to 64 chars.
        # https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html
        #
        # NOTE: Each generated DICOM Seg will be a dcm file with the name based on the SOP instance UID.

        # Description for the Spleen seg, and the seg writer obj
        seg_descriptions_spleen = [
            SegmentDescription(
                segment_label="Spleen",
                segmented_property_category=codes.SCT.Organ,
                segmented_property_type=codes.SCT.Spleen,
                algorithm_name="volumetric (3D) segmentation of the spleen from CT image",
                algorithm_family=codes.DCM.ArtificialIntelligence,
                algorithm_version="0.3.2",
            )
        ]

        custom_tags_spleen = {"SeriesDescription": "AI Spleen Seg for research use only. Not for clinical use."}
        dicom_seg_writer_spleen = DICOMSegmentationWriterOperator(
            segment_descriptions=seg_descriptions_spleen, custom_tags=custom_tags_spleen
        )

        # Description for the Pancreas seg, and the seg writer obj
        seg_descriptions_pancreas = [
            SegmentDescription(
                segment_label="Pancreas",
                segmented_property_category=codes.SCT.Organ,
                segmented_property_type=codes.SCT.Pancreas,
                algorithm_name="volumetric (3D) segmentation of the pancreas from CT image",
                algorithm_family=codes.DCM.ArtificialIntelligence,
                algorithm_version="0.3.0",
            )
        ]
        custom_tags_pancreas = {"SeriesDescription": "AI Pancreas Seg for research use only. Not for clinical use."}

        dicom_seg_writer_pancreas = DICOMSegmentationWriterOperator(
            segment_descriptions=seg_descriptions_pancreas, custom_tags=custom_tags_pancreas
        )

        # NOTE: Sharp eyed readers can already see that the above instantiation of object can be simply parameterized.
        #       Very true, but leaving them as if for easy reading. In fact the whole app can be parameterized for general use.

        # Create the processing pipeline, by specifying the upstream and downstream operators, and
        # ensuring the output from the former matches the input of the latter, in both name and type.
        self.add_flow(study_loader_op, series_selector_op, {"dicom_study_list": "dicom_study_list"})
        self.add_flow(
            series_selector_op, series_to_vol_op, {"study_selected_series_list": "study_selected_series_list"}
        )

        # Feed the input image to all inference operators
        self.add_flow(series_to_vol_op, bundle_spleen_seg_op, {"image": "image"})
        # The Pancreas CT Seg bundle requires PyTorch 1.12.0 to avoid failure to load.
        self.add_flow(series_to_vol_op, bundle_pancreas_seg_op, {"image": "image"})

        # Create DICOM Seg for one of the inference output
        # Note below the dicom_seg_writer requires two inputs, each coming from a upstream operator.
        self.add_flow(
            series_selector_op, dicom_seg_writer_spleen, {"study_selected_series_list": "study_selected_series_list"}
        )
        self.add_flow(bundle_spleen_seg_op, dicom_seg_writer_spleen, {"pred": "seg_image"})

        # Create DICOM Seg for one of the inference output
        # Note below the dicom_seg_writer requires two inputs, each coming from a upstream operator.
        self.add_flow(
            series_selector_op, dicom_seg_writer_pancreas, {"study_selected_series_list": "study_selected_series_list"}
        )
        self.add_flow(bundle_pancreas_seg_op, dicom_seg_writer_pancreas, {"pred": "seg_image"})

        logging.info(f"End {self.compose.__name__}")


# This is a sample series selection rule in JSON, simply selecting CT series.
# If the study has more than 1 CT series, then all of them will be selected.
# Please see more detail in DICOMSeriesSelectorOperator.
Sample_Rules_Text = """
{
    "selections": [
        {
            "name": "CT Series",
            "conditions": {
                "StudyDescription": "(.*?)",
                "Modality": "(?i)CT",
                "SeriesDescription": "(.*?)"
            }
        }
    ]
}
"""

if __name__ == "__main__":
    # Creates the app and test it standalone. When running is this mode, please note the following:
    #     -m <model file>, for model file path
    #     -i <DICOM folder>, for input DICOM CT series folder
    #     -o <output folder>, for the output folder, default $PWD/output
    # e.g.
    #     monai-deploy exec app.py -i input -m model/model.ts
    #
    logging.basicConfig(level=logging.DEBUG)
    app_instance = App(do_run=True)
2022-10-23 16:14:37,601 - Begin compose
2022-10-23 16:14:37,604 - End compose
2022-10-23 16:14:37,605 - Begin run
2022-10-23 16:14:37,605 - End run

Executing app locally

We can execute the app in the Jupyter notebook. Note that the DICOM files of the CT Abdomen series must be present in the dcm and the Torch Script model at model.ts. Please use the actual path in your environment.

app = App()

app.run(input="dcm", output="output", model="multi_models")
2022-10-23 16:14:37,742 - Begin compose
2022-10-23 16:14:37,745 - End compose
2022-10-23 16:14:37,746 - Begin run
Going to initiate execution of operator DICOMDataLoaderOperator
Executing operator DICOMDataLoaderOperator (Process ID: 1303858, Operator ID: d12df864-d3eb-4c7f-88b8-3fbbec159fbc)
[2022-10-23 16:14:38,314] [INFO] (root) - Finding series for Selection named: CT Series
[2022-10-23 16:14:38,315] [INFO] (root) - Searching study, : 1.3.6.1.4.1.14519.5.2.1.7085.2626.822645453932810382886582736291
  # of series: 1
[2022-10-23 16:14:38,316] [INFO] (root) - Working on series, instance UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239
[2022-10-23 16:14:38,317] [INFO] (root) - On attribute: 'StudyDescription' to match value: '(.*?)'
[2022-10-23 16:14:38,318] [INFO] (root) -     Series attribute StudyDescription value: CT ABDOMEN W IV CONTRAST
[2022-10-23 16:14:38,319] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 16:14:38,320] [INFO] (root) - On attribute: 'Modality' to match value: '(?i)CT'
[2022-10-23 16:14:38,321] [INFO] (root) -     Series attribute Modality value: CT
[2022-10-23 16:14:38,322] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 16:14:38,323] [INFO] (root) - On attribute: 'SeriesDescription' to match value: '(.*?)'
[2022-10-23 16:14:38,323] [INFO] (root) -     Series attribute SeriesDescription value: ABD/PANC 3.0 B31f
[2022-10-23 16:14:38,324] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 16:14:38,325] [INFO] (root) - Selected Series, UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239
Done performing execution of operator DICOMDataLoaderOperator

Going to initiate execution of operator DICOMSeriesSelectorOperator
Executing operator DICOMSeriesSelectorOperator (Process ID: 1303858, Operator ID: 6f40f1f0-27f8-4f71-b9bd-4fa8eeece94d)
Done performing execution of operator DICOMSeriesSelectorOperator

Going to initiate execution of operator DICOMSeriesToVolumeOperator
Executing operator DICOMSeriesToVolumeOperator (Process ID: 1303858, Operator ID: 09eefdde-25cb-4762-90b5-8b75fe237a62)
Done performing execution of operator DICOMSeriesToVolumeOperator

Going to initiate execution of operator MonaiBundleInferenceOperator
Executing operator MonaiBundleInferenceOperator (Process ID: 1303858, Operator ID: a5fcb2c0-5b57-42ba-8669-58ea87828a88)
Done performing execution of operator MonaiBundleInferenceOperator

Going to initiate execution of operator MonaiBundleInferenceOperator
Executing operator MonaiBundleInferenceOperator (Process ID: 1303858, Operator ID: d2117e67-7a3e-4e91-8ba9-ce26f1f8f079)
Done performing execution of operator MonaiBundleInferenceOperator

Going to initiate execution of operator DICOMSegmentationWriterOperator
Executing operator DICOMSegmentationWriterOperator (Process ID: 1303858, Operator ID: 3cd0e57b-0b5c-49c5-8e90-4a588c246e74)
/home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages/highdicom/valuerep.py:54: UserWarning: The string "C3N-00198" is unlikely to represent the intended person name since it contains only a single component. Construct a person name according to the format in described in http://dicom.nema.org/dicom/2013/output/chtml/part05/sect_6.2.html#sect_6.2.1.2, or, in pydicom 2.2.0 or later, use the pydicom.valuerep.PersonName.from_named_components() method to construct the person name correctly. If a single-component name is really intended, add a trailing caret character to disambiguate the name.
  warnings.warn(
[2022-10-23 16:17:02,106] [INFO] (highdicom.seg.sop) - add plane #0 for segment #1
[2022-10-23 16:17:02,108] [INFO] (highdicom.seg.sop) - add plane #1 for segment #1
[2022-10-23 16:17:02,110] [INFO] (highdicom.seg.sop) - add plane #2 for segment #1
[2022-10-23 16:17:02,112] [INFO] (highdicom.seg.sop) - add plane #3 for segment #1
[2022-10-23 16:17:02,114] [INFO] (highdicom.seg.sop) - add plane #4 for segment #1
[2022-10-23 16:17:02,116] [INFO] (highdicom.seg.sop) - add plane #5 for segment #1
[2022-10-23 16:17:02,117] [INFO] (highdicom.seg.sop) - add plane #6 for segment #1
[2022-10-23 16:17:02,120] [INFO] (highdicom.seg.sop) - add plane #7 for segment #1
[2022-10-23 16:17:02,126] [INFO] (highdicom.seg.sop) - add plane #8 for segment #1
[2022-10-23 16:17:02,130] [INFO] (highdicom.seg.sop) - add plane #9 for segment #1
[2022-10-23 16:17:02,134] [INFO] (highdicom.seg.sop) - add plane #10 for segment #1
[2022-10-23 16:17:02,139] [INFO] (highdicom.seg.sop) - add plane #11 for segment #1
[2022-10-23 16:17:02,143] [INFO] (highdicom.seg.sop) - add plane #12 for segment #1
[2022-10-23 16:17:02,145] [INFO] (highdicom.seg.sop) - add plane #13 for segment #1
[2022-10-23 16:17:02,147] [INFO] (highdicom.seg.sop) - add plane #14 for segment #1
[2022-10-23 16:17:02,151] [INFO] (highdicom.seg.sop) - add plane #15 for segment #1
[2022-10-23 16:17:02,153] [INFO] (highdicom.seg.sop) - add plane #16 for segment #1
[2022-10-23 16:17:02,155] [INFO] (highdicom.seg.sop) - add plane #17 for segment #1
[2022-10-23 16:17:02,157] [INFO] (highdicom.seg.sop) - add plane #18 for segment #1
[2022-10-23 16:17:02,159] [INFO] (highdicom.seg.sop) - add plane #19 for segment #1
[2022-10-23 16:17:02,164] [INFO] (highdicom.seg.sop) - add plane #20 for segment #1
[2022-10-23 16:17:02,168] [INFO] (highdicom.seg.sop) - add plane #21 for segment #1
[2022-10-23 16:17:02,172] [INFO] (highdicom.seg.sop) - add plane #22 for segment #1
[2022-10-23 16:17:02,175] [INFO] (highdicom.seg.sop) - add plane #23 for segment #1
[2022-10-23 16:17:02,178] [INFO] (highdicom.seg.sop) - add plane #24 for segment #1
[2022-10-23 16:17:02,181] [INFO] (highdicom.seg.sop) - add plane #25 for segment #1
[2022-10-23 16:17:02,183] [INFO] (highdicom.seg.sop) - add plane #26 for segment #1
[2022-10-23 16:17:02,186] [INFO] (highdicom.seg.sop) - add plane #27 for segment #1
[2022-10-23 16:17:02,188] [INFO] (highdicom.seg.sop) - add plane #28 for segment #1
[2022-10-23 16:17:02,190] [INFO] (highdicom.seg.sop) - add plane #29 for segment #1
[2022-10-23 16:17:02,192] [INFO] (highdicom.seg.sop) - add plane #30 for segment #1
[2022-10-23 16:17:02,194] [INFO] (highdicom.seg.sop) - add plane #31 for segment #1
[2022-10-23 16:17:02,196] [INFO] (highdicom.seg.sop) - add plane #32 for segment #1
[2022-10-23 16:17:02,198] [INFO] (highdicom.seg.sop) - add plane #33 for segment #1
[2022-10-23 16:17:02,200] [INFO] (highdicom.seg.sop) - add plane #34 for segment #1
[2022-10-23 16:17:02,201] [INFO] (highdicom.seg.sop) - add plane #35 for segment #1
[2022-10-23 16:17:02,203] [INFO] (highdicom.seg.sop) - add plane #36 for segment #1
[2022-10-23 16:17:02,205] [INFO] (highdicom.seg.sop) - add plane #37 for segment #1
[2022-10-23 16:17:02,206] [INFO] (highdicom.seg.sop) - add plane #38 for segment #1
[2022-10-23 16:17:02,208] [INFO] (highdicom.seg.sop) - add plane #39 for segment #1
[2022-10-23 16:17:02,209] [INFO] (highdicom.seg.sop) - add plane #40 for segment #1
[2022-10-23 16:17:02,211] [INFO] (highdicom.seg.sop) - add plane #41 for segment #1
[2022-10-23 16:17:02,213] [INFO] (highdicom.seg.sop) - add plane #42 for segment #1
[2022-10-23 16:17:02,216] [INFO] (highdicom.seg.sop) - add plane #43 for segment #1
[2022-10-23 16:17:02,218] [INFO] (highdicom.seg.sop) - add plane #44 for segment #1
[2022-10-23 16:17:02,220] [INFO] (highdicom.seg.sop) - add plane #45 for segment #1
[2022-10-23 16:17:02,222] [INFO] (highdicom.seg.sop) - add plane #46 for segment #1
[2022-10-23 16:17:02,224] [INFO] (highdicom.seg.sop) - add plane #47 for segment #1
[2022-10-23 16:17:02,226] [INFO] (highdicom.seg.sop) - add plane #48 for segment #1
[2022-10-23 16:17:02,228] [INFO] (highdicom.seg.sop) - add plane #49 for segment #1
[2022-10-23 16:17:02,230] [INFO] (highdicom.seg.sop) - add plane #50 for segment #1
[2022-10-23 16:17:02,231] [INFO] (highdicom.seg.sop) - add plane #51 for segment #1
[2022-10-23 16:17:02,233] [INFO] (highdicom.seg.sop) - add plane #52 for segment #1
[2022-10-23 16:17:02,236] [INFO] (highdicom.seg.sop) - add plane #53 for segment #1
[2022-10-23 16:17:02,238] [INFO] (highdicom.seg.sop) - add plane #54 for segment #1
[2022-10-23 16:17:02,240] [INFO] (highdicom.seg.sop) - add plane #55 for segment #1
[2022-10-23 16:17:02,243] [INFO] (highdicom.seg.sop) - add plane #56 for segment #1
[2022-10-23 16:17:02,245] [INFO] (highdicom.seg.sop) - add plane #57 for segment #1
[2022-10-23 16:17:02,247] [INFO] (highdicom.seg.sop) - add plane #58 for segment #1
[2022-10-23 16:17:02,249] [INFO] (highdicom.seg.sop) - add plane #59 for segment #1
[2022-10-23 16:17:02,251] [INFO] (highdicom.seg.sop) - add plane #60 for segment #1
[2022-10-23 16:17:02,254] [INFO] (highdicom.seg.sop) - add plane #61 for segment #1
[2022-10-23 16:17:02,257] [INFO] (highdicom.seg.sop) - add plane #62 for segment #1
[2022-10-23 16:17:02,260] [INFO] (highdicom.seg.sop) - add plane #63 for segment #1
[2022-10-23 16:17:02,264] [INFO] (highdicom.seg.sop) - add plane #64 for segment #1
[2022-10-23 16:17:02,267] [INFO] (highdicom.seg.sop) - add plane #65 for segment #1
[2022-10-23 16:17:02,270] [INFO] (highdicom.seg.sop) - add plane #66 for segment #1
[2022-10-23 16:17:02,272] [INFO] (highdicom.seg.sop) - add plane #67 for segment #1
[2022-10-23 16:17:02,274] [INFO] (highdicom.seg.sop) - add plane #68 for segment #1
[2022-10-23 16:17:02,276] [INFO] (highdicom.seg.sop) - add plane #69 for segment #1
[2022-10-23 16:17:02,278] [INFO] (highdicom.seg.sop) - add plane #70 for segment #1
[2022-10-23 16:17:02,280] [INFO] (highdicom.seg.sop) - add plane #71 for segment #1
[2022-10-23 16:17:02,282] [INFO] (highdicom.seg.sop) - add plane #72 for segment #1
[2022-10-23 16:17:02,285] [INFO] (highdicom.seg.sop) - add plane #73 for segment #1
[2022-10-23 16:17:02,287] [INFO] (highdicom.seg.sop) - add plane #74 for segment #1
[2022-10-23 16:17:02,289] [INFO] (highdicom.seg.sop) - add plane #75 for segment #1
[2022-10-23 16:17:02,291] [INFO] (highdicom.seg.sop) - add plane #76 for segment #1
[2022-10-23 16:17:02,293] [INFO] (highdicom.seg.sop) - add plane #77 for segment #1
[2022-10-23 16:17:02,295] [INFO] (highdicom.seg.sop) - add plane #78 for segment #1
[2022-10-23 16:17:02,297] [INFO] (highdicom.seg.sop) - add plane #79 for segment #1
[2022-10-23 16:17:02,299] [INFO] (highdicom.seg.sop) - add plane #80 for segment #1
[2022-10-23 16:17:02,301] [INFO] (highdicom.seg.sop) - add plane #81 for segment #1
[2022-10-23 16:17:02,303] [INFO] (highdicom.seg.sop) - add plane #82 for segment #1
[2022-10-23 16:17:02,305] [INFO] (highdicom.seg.sop) - add plane #83 for segment #1
[2022-10-23 16:17:02,307] [INFO] (highdicom.seg.sop) - add plane #84 for segment #1
[2022-10-23 16:17:02,309] [INFO] (highdicom.seg.sop) - add plane #85 for segment #1
[2022-10-23 16:17:02,311] [INFO] (highdicom.seg.sop) - add plane #86 for segment #1
[2022-10-23 16:17:02,353] [INFO] (highdicom.base) - copy Image-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:17:02,353] [INFO] (highdicom.base) - copy attributes of module "Specimen"
[2022-10-23 16:17:02,354] [INFO] (highdicom.base) - copy Patient-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:17:02,354] [INFO] (highdicom.base) - copy attributes of module "Patient"
[2022-10-23 16:17:02,355] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Subject"
[2022-10-23 16:17:02,356] [INFO] (highdicom.base) - copy Study-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:17:02,356] [INFO] (highdicom.base) - copy attributes of module "General Study"
[2022-10-23 16:17:02,357] [INFO] (highdicom.base) - copy attributes of module "Patient Study"
[2022-10-23 16:17:02,357] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Study"
Done performing execution of operator DICOMSegmentationWriterOperator

Going to initiate execution of operator DICOMSegmentationWriterOperator
Executing operator DICOMSegmentationWriterOperator (Process ID: 1303858, Operator ID: 70acb0d2-9ab6-4724-ada6-f9e793f3f9c9)
[2022-10-23 16:17:03,808] [INFO] (highdicom.seg.sop) - add plane #0 for segment #1
[2022-10-23 16:17:03,810] [INFO] (highdicom.seg.sop) - add plane #1 for segment #1
[2022-10-23 16:17:03,811] [INFO] (highdicom.seg.sop) - add plane #2 for segment #1
[2022-10-23 16:17:03,813] [INFO] (highdicom.seg.sop) - add plane #3 for segment #1
[2022-10-23 16:17:03,816] [INFO] (highdicom.seg.sop) - add plane #4 for segment #1
[2022-10-23 16:17:03,818] [INFO] (highdicom.seg.sop) - add plane #5 for segment #1
[2022-10-23 16:17:03,820] [INFO] (highdicom.seg.sop) - add plane #6 for segment #1
[2022-10-23 16:17:03,822] [INFO] (highdicom.seg.sop) - add plane #7 for segment #1
[2022-10-23 16:17:03,825] [INFO] (highdicom.seg.sop) - add plane #8 for segment #1
[2022-10-23 16:17:03,827] [INFO] (highdicom.seg.sop) - add plane #9 for segment #1
[2022-10-23 16:17:03,829] [INFO] (highdicom.seg.sop) - add plane #10 for segment #1
[2022-10-23 16:17:03,831] [INFO] (highdicom.seg.sop) - add plane #11 for segment #1
[2022-10-23 16:17:03,833] [INFO] (highdicom.seg.sop) - add plane #12 for segment #1
[2022-10-23 16:17:03,836] [INFO] (highdicom.seg.sop) - add plane #13 for segment #1
[2022-10-23 16:17:03,838] [INFO] (highdicom.seg.sop) - add plane #14 for segment #1
[2022-10-23 16:17:03,840] [INFO] (highdicom.seg.sop) - add plane #15 for segment #1
[2022-10-23 16:17:03,843] [INFO] (highdicom.seg.sop) - add plane #16 for segment #1
[2022-10-23 16:17:03,845] [INFO] (highdicom.seg.sop) - add plane #17 for segment #1
[2022-10-23 16:17:03,848] [INFO] (highdicom.seg.sop) - add plane #18 for segment #1
[2022-10-23 16:17:03,850] [INFO] (highdicom.seg.sop) - add plane #19 for segment #1
[2022-10-23 16:17:03,852] [INFO] (highdicom.seg.sop) - add plane #20 for segment #1
[2022-10-23 16:17:03,855] [INFO] (highdicom.seg.sop) - add plane #21 for segment #1
[2022-10-23 16:17:03,857] [INFO] (highdicom.seg.sop) - add plane #22 for segment #1
[2022-10-23 16:17:03,859] [INFO] (highdicom.seg.sop) - add plane #23 for segment #1
[2022-10-23 16:17:03,862] [INFO] (highdicom.seg.sop) - add plane #24 for segment #1
[2022-10-23 16:17:03,865] [INFO] (highdicom.seg.sop) - add plane #25 for segment #1
[2022-10-23 16:17:03,868] [INFO] (highdicom.seg.sop) - add plane #26 for segment #1
[2022-10-23 16:17:03,870] [INFO] (highdicom.seg.sop) - add plane #27 for segment #1
[2022-10-23 16:17:03,872] [INFO] (highdicom.seg.sop) - add plane #28 for segment #1
[2022-10-23 16:17:03,874] [INFO] (highdicom.seg.sop) - add plane #29 for segment #1
[2022-10-23 16:17:03,876] [INFO] (highdicom.seg.sop) - add plane #30 for segment #1
[2022-10-23 16:17:03,878] [INFO] (highdicom.seg.sop) - add plane #31 for segment #1
[2022-10-23 16:17:03,880] [INFO] (highdicom.seg.sop) - add plane #32 for segment #1
[2022-10-23 16:17:03,882] [INFO] (highdicom.seg.sop) - add plane #33 for segment #1
[2022-10-23 16:17:03,884] [INFO] (highdicom.seg.sop) - add plane #34 for segment #1
[2022-10-23 16:17:03,888] [INFO] (highdicom.seg.sop) - add plane #35 for segment #1
[2022-10-23 16:17:03,892] [INFO] (highdicom.seg.sop) - add plane #36 for segment #1
[2022-10-23 16:17:03,896] [INFO] (highdicom.seg.sop) - add plane #37 for segment #1
[2022-10-23 16:17:03,900] [INFO] (highdicom.seg.sop) - add plane #38 for segment #1
[2022-10-23 16:17:03,903] [INFO] (highdicom.seg.sop) - add plane #39 for segment #1
[2022-10-23 16:17:03,906] [INFO] (highdicom.seg.sop) - add plane #40 for segment #1
[2022-10-23 16:17:03,909] [INFO] (highdicom.seg.sop) - add plane #41 for segment #1
[2022-10-23 16:17:03,912] [INFO] (highdicom.seg.sop) - add plane #42 for segment #1
[2022-10-23 16:17:03,914] [INFO] (highdicom.seg.sop) - add plane #43 for segment #1
[2022-10-23 16:17:03,917] [INFO] (highdicom.seg.sop) - add plane #44 for segment #1
[2022-10-23 16:17:03,919] [INFO] (highdicom.seg.sop) - add plane #45 for segment #1
[2022-10-23 16:17:03,921] [INFO] (highdicom.seg.sop) - add plane #46 for segment #1
[2022-10-23 16:17:03,924] [INFO] (highdicom.seg.sop) - add plane #47 for segment #1
[2022-10-23 16:17:03,925] [INFO] (highdicom.seg.sop) - add plane #48 for segment #1
[2022-10-23 16:17:03,927] [INFO] (highdicom.seg.sop) - add plane #49 for segment #1
[2022-10-23 16:17:03,929] [INFO] (highdicom.seg.sop) - add plane #50 for segment #1
[2022-10-23 16:17:03,930] [INFO] (highdicom.seg.sop) - add plane #51 for segment #1
[2022-10-23 16:17:03,932] [INFO] (highdicom.seg.sop) - add plane #52 for segment #1
[2022-10-23 16:17:03,934] [INFO] (highdicom.seg.sop) - add plane #53 for segment #1
[2022-10-23 16:17:03,935] [INFO] (highdicom.seg.sop) - add plane #54 for segment #1
[2022-10-23 16:17:03,937] [INFO] (highdicom.seg.sop) - add plane #55 for segment #1
[2022-10-23 16:17:03,938] [INFO] (highdicom.seg.sop) - add plane #56 for segment #1
[2022-10-23 16:17:03,940] [INFO] (highdicom.seg.sop) - add plane #57 for segment #1
[2022-10-23 16:17:03,941] [INFO] (highdicom.seg.sop) - add plane #58 for segment #1
[2022-10-23 16:17:03,943] [INFO] (highdicom.seg.sop) - add plane #59 for segment #1
[2022-10-23 16:17:03,945] [INFO] (highdicom.seg.sop) - add plane #60 for segment #1
[2022-10-23 16:17:03,947] [INFO] (highdicom.seg.sop) - add plane #61 for segment #1
[2022-10-23 16:17:03,948] [INFO] (highdicom.seg.sop) - add plane #62 for segment #1
[2022-10-23 16:17:03,950] [INFO] (highdicom.seg.sop) - add plane #63 for segment #1
[2022-10-23 16:17:03,951] [INFO] (highdicom.seg.sop) - add plane #64 for segment #1
[2022-10-23 16:17:03,953] [INFO] (highdicom.seg.sop) - add plane #65 for segment #1
[2022-10-23 16:17:03,954] [INFO] (highdicom.seg.sop) - add plane #66 for segment #1
[2022-10-23 16:17:03,956] [INFO] (highdicom.seg.sop) - add plane #67 for segment #1
[2022-10-23 16:17:03,995] [INFO] (highdicom.base) - copy Image-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:17:03,995] [INFO] (highdicom.base) - copy attributes of module "Specimen"
[2022-10-23 16:17:03,996] [INFO] (highdicom.base) - copy Patient-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:17:03,996] [INFO] (highdicom.base) - copy attributes of module "Patient"
[2022-10-23 16:17:03,997] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Subject"
[2022-10-23 16:17:03,998] [INFO] (highdicom.base) - copy Study-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:17:03,998] [INFO] (highdicom.base) - copy attributes of module "General Study"
[2022-10-23 16:17:03,999] [INFO] (highdicom.base) - copy attributes of module "Patient Study"
[2022-10-23 16:17:04,000] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Study"
[2022-10-23 16:17:04,106] [INFO] (__main__.App) - End run
Done performing execution of operator DICOMSegmentationWriterOperator

Once the application is verified inside Jupyter notebook, we can write the above Python code into Python files in an application folder.

The application folder structure would look like below:

my_app
├── __main__.py
└── app.py
# Create an application folder
!mkdir -p my_app

app.py

%%writefile my_app/app.py

# Copyright 2021-2022 MONAI Consortium
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import logging

# Required for setting SegmentDescription attributes. Direct import as this is not part of App SDK package.
from pydicom.sr.codedict import codes

import monai.deploy.core as md
from monai.deploy.core import Application, resource
from monai.deploy.core.domain import Image
from monai.deploy.core.io_type import IOType
from monai.deploy.operators.dicom_data_loader_operator import DICOMDataLoaderOperator
from monai.deploy.operators.dicom_seg_writer_operator import DICOMSegmentationWriterOperator, SegmentDescription
from monai.deploy.operators.dicom_series_selector_operator import DICOMSeriesSelectorOperator
from monai.deploy.operators.dicom_series_to_volume_operator import DICOMSeriesToVolumeOperator
from monai.deploy.operators.monai_bundle_inference_operator import (
    BundleConfigNames,
    IOMapping,
    MonaiBundleInferenceOperator,
)


@resource(cpu=1, gpu=1, memory="7Gi")
# Enforcing torch>=1.12.0 because one of the Bundles/TorchScripts, Pancreas CT Seg, was created
# with this version, and would fail to jit.load with lower version of torch.
# The Bundle Inference Operator as of now only requires torch>=1.10.2, and does not yet dynamically
# parse the MONAI bundle to get the required pip package or ver on initialization, hence it does not set
# its own @env decorator accordingly when the app is being packaged into a MONAI Package.
@md.env(pip_packages=["torch>=1.12.0"])
# pip_packages can be a string that is a path(str) to requirements.txt file or a list of packages.
# The monai pkg is not required by this class, instead by the included operators.
class App(Application):
    """This example demonstrates how to create a multi-model/multi-AI application.

    The important steps are:
        1. Place the model TorchScripts in a defined folder structure, see below for details
        2. Pass the model name to the inference operator instance in the app
        3. Connect the input to and output from the inference operators, as required by the app

    Model organization for this example:

        multi_models
        ├── pancreas_ct_dints
        │   └── model.ts
        └── spleen_ct
            └── model.ts

    Note:
    1. The TorchScript files of MONAI Bundles can be downloaded from MONAI Model Zoo, at
       https://github.com/Project-MONAI/model-zoo/tree/dev/models
    2. The input DICOM instances are from a DICOM Series of CT Abdomen, similar to the ones
       used in the Spleen Segmentation example
    3. This example is purely for technical demonstration, not for clinical use
    """

    def __init__(self, *args, **kwargs):
        """Creates an application instance."""
        self._logger = logging.getLogger("{}.{}".format(__name__, type(self).__name__))
        super().__init__(*args, **kwargs)

    def run(self, *args, **kwargs):
        # This method calls the base class to run. Can be omitted if simply calling through.
        self._logger.info(f"Begin {self.run.__name__}")
        super().run(*args, **kwargs)
        self._logger.info(f"End {self.run.__name__}")

    def compose(self):
        """Creates the app specific operators and chain them up in the processing DAG."""

        logging.info(f"Begin {self.compose.__name__}")

        # Create the custom operator(s) as well as SDK built-in operator(s).
        study_loader_op = DICOMDataLoaderOperator()
        series_selector_op = DICOMSeriesSelectorOperator(Sample_Rules_Text)
        series_to_vol_op = DICOMSeriesToVolumeOperator()

        # Create the inference operator that supports MONAI Bundle and automates the inference.
        # The IOMapping labels match the input and prediction keys in the pre and post processing.
        # The model_name is optional when the app has only one model.
        # The bundle_path argument optionally can be set to an accessible bundle file path in the dev
        # environment, so when the app is packaged into a MAP, the operator can complete the bundle parsing
        # during init to provide the optional packages info, parsed from the bundle, to the packager
        # for it to install the packages in the MAP docker image.
        # Setting output IOType to DISK only works only for leaf operators, not the case in this example.
        # When multiple models/bundles are supported, create an inference operator for each.
        #
        # Pertinent MONAI Bundle:
        #   https://github.com/Project-MONAI/model-zoo/tree/dev/models/spleen_ct_segmentation, v0.3.2
        #   https://github.com/Project-MONAI/model-zoo/tree/dev/models/pancreas_ct_dints_segmentation, v0.3

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

        # This is the inference operator for the spleen_model bundle. Note the model name.
        bundle_spleen_seg_op = MonaiBundleInferenceOperator(
            input_mapping=[IOMapping("image", Image, IOType.IN_MEMORY)],
            output_mapping=[IOMapping("pred", Image, IOType.IN_MEMORY)],
            bundle_config_names=config_names,
            model_name="spleen_ct",
        )

        # This is the inference operator for the pancreas_ct_dints bundle. Note the model name.
        bundle_pancreas_seg_op = MonaiBundleInferenceOperator(
            input_mapping=[IOMapping("image", Image, IOType.IN_MEMORY)],
            output_mapping=[IOMapping("pred", Image, IOType.IN_MEMORY)],
            model_name="pancreas_ct_dints",
        )

        # Create DICOM Seg writer providing the required segment description for each segment with
        # the actual algorithm and the pertinent organ/tissue. The segment_label, algorithm_name,
        # and algorithm_version are of DICOM VR LO type, limited to 64 chars.
        # https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_6.2.html
        #
        # NOTE: Each generated DICOM Seg will be a dcm file with the name based on the SOP instance UID.

        # Description for the Spleen seg, and the seg writer obj
        seg_descriptions_spleen = [
            SegmentDescription(
                segment_label="Spleen",
                segmented_property_category=codes.SCT.Organ,
                segmented_property_type=codes.SCT.Spleen,
                algorithm_name="volumetric (3D) segmentation of the spleen from CT image",
                algorithm_family=codes.DCM.ArtificialIntelligence,
                algorithm_version="0.3.2",
            )
        ]

        custom_tags_spleen = {"SeriesDescription": "AI Spleen Seg for research use only. Not for clinical use."}
        dicom_seg_writer_spleen = DICOMSegmentationWriterOperator(
            segment_descriptions=seg_descriptions_spleen, custom_tags=custom_tags_spleen
        )

        # Description for the Pancreas seg, and the seg writer obj
        seg_descriptions_pancreas = [
            SegmentDescription(
                segment_label="Pancreas",
                segmented_property_category=codes.SCT.Organ,
                segmented_property_type=codes.SCT.Pancreas,
                algorithm_name="volumetric (3D) segmentation of the pancreas from CT image",
                algorithm_family=codes.DCM.ArtificialIntelligence,
                algorithm_version="0.3.0",
            )
        ]
        custom_tags_pancreas = {"SeriesDescription": "AI Pancreas Seg for research use only. Not for clinical use."}

        dicom_seg_writer_pancreas = DICOMSegmentationWriterOperator(
            segment_descriptions=seg_descriptions_pancreas, custom_tags=custom_tags_pancreas
        )

        # NOTE: Sharp eyed readers can already see that the above instantiation of object can be simply parameterized.
        #       Very true, but leaving them as if for easy reading. In fact the whole app can be parameterized for general use.

        # Create the processing pipeline, by specifying the upstream and downstream operators, and
        # ensuring the output from the former matches the input of the latter, in both name and type.
        self.add_flow(study_loader_op, series_selector_op, {"dicom_study_list": "dicom_study_list"})
        self.add_flow(
            series_selector_op, series_to_vol_op, {"study_selected_series_list": "study_selected_series_list"}
        )

        # Feed the input image to all inference operators
        self.add_flow(series_to_vol_op, bundle_spleen_seg_op, {"image": "image"})
        # The Pancreas CT Seg bundle requires PyTorch 1.12.0 to avoid failure to load.
        self.add_flow(series_to_vol_op, bundle_pancreas_seg_op, {"image": "image"})

        # Create DICOM Seg for one of the inference output
        # Note below the dicom_seg_writer requires two inputs, each coming from a upstream operator.
        self.add_flow(
            series_selector_op, dicom_seg_writer_spleen, {"study_selected_series_list": "study_selected_series_list"}
        )
        self.add_flow(bundle_spleen_seg_op, dicom_seg_writer_spleen, {"pred": "seg_image"})

        # Create DICOM Seg for one of the inference output
        # Note below the dicom_seg_writer requires two inputs, each coming from a upstream operator.
        self.add_flow(
            series_selector_op, dicom_seg_writer_pancreas, {"study_selected_series_list": "study_selected_series_list"}
        )
        self.add_flow(bundle_pancreas_seg_op, dicom_seg_writer_pancreas, {"pred": "seg_image"})

        logging.info(f"End {self.compose.__name__}")


# This is a sample series selection rule in JSON, simply selecting CT series.
# If the study has more than 1 CT series, then all of them will be selected.
# Please see more detail in DICOMSeriesSelectorOperator.
Sample_Rules_Text = """
{
    "selections": [
        {
            "name": "CT Series",
            "conditions": {
                "StudyDescription": "(.*?)",
                "Modality": "(?i)CT",
                "SeriesDescription": "(.*?)"
            }
        }
    ]
}
"""

if __name__ == "__main__":
    # Creates the app and test it standalone. When running is this mode, please note the following:
    #     -m <model file>, for model file path
    #     -i <DICOM folder>, for input DICOM CT series folder
    #     -o <output folder>, for the output folder, default $PWD/output
    # e.g.
    #     monai-deploy exec app.py -i input -m model/model.ts
    #
    logging.basicConfig(level=logging.DEBUG)
    app_instance = App(do_run=True)
Writing my_app/app.py
if __name__ == "__main__":
    App(do_run=True)

The above lines are needed to execute the application code by using python interpreter.

__main__.py

__main__.py is needed for MONAI Application Packager to detect the main application code (app.py) when the application is executed with the application folder path (e.g., python simple_imaging_app).

%%writefile my_app/__main__.py
import logging
from app import App

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    App(do_run=True)
Writing my_app/__main__.py
!ls my_app
app.py	__main__.py

In this time, let’s execute the app in the command line.

!python my_app -i dcm -o output -m multi_models
2022-10-23 16:17:09,434 - Begin compose
2022-10-23 16:17:09,436 - End compose
2022-10-23 16:17:09,436 - Begin run
Going to initiate execution of operator DICOMDataLoaderOperator
Executing operator DICOMDataLoaderOperator (Process ID: 1304139, Operator ID: b4a3028c-409b-40b4-ac87-84063c8492ff)
Done performing execution of operator DICOMDataLoaderOperator

Going to initiate execution of operator DICOMSeriesSelectorOperator
Executing operator DICOMSeriesSelectorOperator (Process ID: 1304139, Operator ID: dae12c6a-e046-499e-adab-3ee14e65d99d)
[2022-10-23 16:17:09,959] [INFO] (root) - Finding series for Selection named: CT Series
[2022-10-23 16:17:09,959] [INFO] (root) - Searching study, : 1.3.6.1.4.1.14519.5.2.1.7085.2626.822645453932810382886582736291
  # of series: 1
[2022-10-23 16:17:09,959] [INFO] (root) - Working on series, instance UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239
[2022-10-23 16:17:09,959] [INFO] (root) - On attribute: 'StudyDescription' to match value: '(.*?)'
[2022-10-23 16:17:09,959] [INFO] (root) -     Series attribute StudyDescription value: CT ABDOMEN W IV CONTRAST
[2022-10-23 16:17:09,959] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 16:17:09,959] [INFO] (root) - On attribute: 'Modality' to match value: '(?i)CT'
[2022-10-23 16:17:09,959] [INFO] (root) -     Series attribute Modality value: CT
[2022-10-23 16:17:09,959] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 16:17:09,960] [INFO] (root) - On attribute: 'SeriesDescription' to match value: '(.*?)'
[2022-10-23 16:17:09,960] [INFO] (root) -     Series attribute SeriesDescription value: ABD/PANC 3.0 B31f
[2022-10-23 16:17:09,960] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 16:17:09,960] [INFO] (root) - Selected Series, UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239
Done performing execution of operator DICOMSeriesSelectorOperator

Going to initiate execution of operator DICOMSeriesToVolumeOperator
Executing operator DICOMSeriesToVolumeOperator (Process ID: 1304139, Operator ID: ca8c4e90-0e6d-4a3a-b3fe-7bac291ae196)
Done performing execution of operator DICOMSeriesToVolumeOperator

Going to initiate execution of operator MonaiBundleInferenceOperator
Executing operator MonaiBundleInferenceOperator (Process ID: 1304139, Operator ID: cf1e02c7-2435-44e2-8851-1d563187f704)
Done performing execution of operator MonaiBundleInferenceOperator

Going to initiate execution of operator MonaiBundleInferenceOperator
Executing operator MonaiBundleInferenceOperator (Process ID: 1304139, Operator ID: 2edbc688-1c59-47ae-8197-c38dc346a278)
Done performing execution of operator MonaiBundleInferenceOperator

Going to initiate execution of operator DICOMSegmentationWriterOperator
Executing operator DICOMSegmentationWriterOperator (Process ID: 1304139, Operator ID: 043a224c-fe51-4557-ba1b-09f2eef565f2)
/home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages/highdicom/valuerep.py:54: UserWarning: The string "C3N-00198" is unlikely to represent the intended person name since it contains only a single component. Construct a person name according to the format in described in http://dicom.nema.org/dicom/2013/output/chtml/part05/sect_6.2.html#sect_6.2.1.2, or, in pydicom 2.2.0 or later, use the pydicom.valuerep.PersonName.from_named_components() method to construct the person name correctly. If a single-component name is really intended, add a trailing caret character to disambiguate the name.
  warnings.warn(
[2022-10-23 16:19:34,601] [INFO] (highdicom.seg.sop) - add plane #0 for segment #1
[2022-10-23 16:19:34,603] [INFO] (highdicom.seg.sop) - add plane #1 for segment #1
[2022-10-23 16:19:34,604] [INFO] (highdicom.seg.sop) - add plane #2 for segment #1
[2022-10-23 16:19:34,605] [INFO] (highdicom.seg.sop) - add plane #3 for segment #1
[2022-10-23 16:19:34,606] [INFO] (highdicom.seg.sop) - add plane #4 for segment #1
[2022-10-23 16:19:34,607] [INFO] (highdicom.seg.sop) - add plane #5 for segment #1
[2022-10-23 16:19:34,608] [INFO] (highdicom.seg.sop) - add plane #6 for segment #1
[2022-10-23 16:19:34,608] [INFO] (highdicom.seg.sop) - add plane #7 for segment #1
[2022-10-23 16:19:34,609] [INFO] (highdicom.seg.sop) - add plane #8 for segment #1
[2022-10-23 16:19:34,610] [INFO] (highdicom.seg.sop) - add plane #9 for segment #1
[2022-10-23 16:19:34,611] [INFO] (highdicom.seg.sop) - add plane #10 for segment #1
[2022-10-23 16:19:34,612] [INFO] (highdicom.seg.sop) - add plane #11 for segment #1
[2022-10-23 16:19:34,613] [INFO] (highdicom.seg.sop) - add plane #12 for segment #1
[2022-10-23 16:19:34,614] [INFO] (highdicom.seg.sop) - add plane #13 for segment #1
[2022-10-23 16:19:34,615] [INFO] (highdicom.seg.sop) - add plane #14 for segment #1
[2022-10-23 16:19:34,616] [INFO] (highdicom.seg.sop) - add plane #15 for segment #1
[2022-10-23 16:19:34,617] [INFO] (highdicom.seg.sop) - add plane #16 for segment #1
[2022-10-23 16:19:34,618] [INFO] (highdicom.seg.sop) - add plane #17 for segment #1
[2022-10-23 16:19:34,619] [INFO] (highdicom.seg.sop) - add plane #18 for segment #1
[2022-10-23 16:19:34,619] [INFO] (highdicom.seg.sop) - add plane #19 for segment #1
[2022-10-23 16:19:34,620] [INFO] (highdicom.seg.sop) - add plane #20 for segment #1
[2022-10-23 16:19:34,621] [INFO] (highdicom.seg.sop) - add plane #21 for segment #1
[2022-10-23 16:19:34,622] [INFO] (highdicom.seg.sop) - add plane #22 for segment #1
[2022-10-23 16:19:34,623] [INFO] (highdicom.seg.sop) - add plane #23 for segment #1
[2022-10-23 16:19:34,624] [INFO] (highdicom.seg.sop) - add plane #24 for segment #1
[2022-10-23 16:19:34,625] [INFO] (highdicom.seg.sop) - add plane #25 for segment #1
[2022-10-23 16:19:34,626] [INFO] (highdicom.seg.sop) - add plane #26 for segment #1
[2022-10-23 16:19:34,627] [INFO] (highdicom.seg.sop) - add plane #27 for segment #1
[2022-10-23 16:19:34,628] [INFO] (highdicom.seg.sop) - add plane #28 for segment #1
[2022-10-23 16:19:34,629] [INFO] (highdicom.seg.sop) - add plane #29 for segment #1
[2022-10-23 16:19:34,630] [INFO] (highdicom.seg.sop) - add plane #30 for segment #1
[2022-10-23 16:19:34,631] [INFO] (highdicom.seg.sop) - add plane #31 for segment #1
[2022-10-23 16:19:34,632] [INFO] (highdicom.seg.sop) - add plane #32 for segment #1
[2022-10-23 16:19:34,633] [INFO] (highdicom.seg.sop) - add plane #33 for segment #1
[2022-10-23 16:19:34,634] [INFO] (highdicom.seg.sop) - add plane #34 for segment #1
[2022-10-23 16:19:34,635] [INFO] (highdicom.seg.sop) - add plane #35 for segment #1
[2022-10-23 16:19:34,636] [INFO] (highdicom.seg.sop) - add plane #36 for segment #1
[2022-10-23 16:19:34,636] [INFO] (highdicom.seg.sop) - add plane #37 for segment #1
[2022-10-23 16:19:34,637] [INFO] (highdicom.seg.sop) - add plane #38 for segment #1
[2022-10-23 16:19:34,639] [INFO] (highdicom.seg.sop) - add plane #39 for segment #1
[2022-10-23 16:19:34,640] [INFO] (highdicom.seg.sop) - add plane #40 for segment #1
[2022-10-23 16:19:34,641] [INFO] (highdicom.seg.sop) - add plane #41 for segment #1
[2022-10-23 16:19:34,642] [INFO] (highdicom.seg.sop) - add plane #42 for segment #1
[2022-10-23 16:19:34,643] [INFO] (highdicom.seg.sop) - add plane #43 for segment #1
[2022-10-23 16:19:34,644] [INFO] (highdicom.seg.sop) - add plane #44 for segment #1
[2022-10-23 16:19:34,851] [INFO] (highdicom.seg.sop) - add plane #45 for segment #1
[2022-10-23 16:19:34,852] [INFO] (highdicom.seg.sop) - add plane #46 for segment #1
[2022-10-23 16:19:34,853] [INFO] (highdicom.seg.sop) - add plane #47 for segment #1
[2022-10-23 16:19:34,854] [INFO] (highdicom.seg.sop) - add plane #48 for segment #1
[2022-10-23 16:19:34,855] [INFO] (highdicom.seg.sop) - add plane #49 for segment #1
[2022-10-23 16:19:34,856] [INFO] (highdicom.seg.sop) - add plane #50 for segment #1
[2022-10-23 16:19:34,857] [INFO] (highdicom.seg.sop) - add plane #51 for segment #1
[2022-10-23 16:19:34,858] [INFO] (highdicom.seg.sop) - add plane #52 for segment #1
[2022-10-23 16:19:34,859] [INFO] (highdicom.seg.sop) - add plane #53 for segment #1
[2022-10-23 16:19:34,860] [INFO] (highdicom.seg.sop) - add plane #54 for segment #1
[2022-10-23 16:19:34,861] [INFO] (highdicom.seg.sop) - add plane #55 for segment #1
[2022-10-23 16:19:34,862] [INFO] (highdicom.seg.sop) - add plane #56 for segment #1
[2022-10-23 16:19:34,863] [INFO] (highdicom.seg.sop) - add plane #57 for segment #1
[2022-10-23 16:19:34,864] [INFO] (highdicom.seg.sop) - add plane #58 for segment #1
[2022-10-23 16:19:34,865] [INFO] (highdicom.seg.sop) - add plane #59 for segment #1
[2022-10-23 16:19:34,866] [INFO] (highdicom.seg.sop) - add plane #60 for segment #1
[2022-10-23 16:19:34,867] [INFO] (highdicom.seg.sop) - add plane #61 for segment #1
[2022-10-23 16:19:34,868] [INFO] (highdicom.seg.sop) - add plane #62 for segment #1
[2022-10-23 16:19:34,869] [INFO] (highdicom.seg.sop) - add plane #63 for segment #1
[2022-10-23 16:19:34,870] [INFO] (highdicom.seg.sop) - add plane #64 for segment #1
[2022-10-23 16:19:34,871] [INFO] (highdicom.seg.sop) - add plane #65 for segment #1
[2022-10-23 16:19:34,872] [INFO] (highdicom.seg.sop) - add plane #66 for segment #1
[2022-10-23 16:19:34,873] [INFO] (highdicom.seg.sop) - add plane #67 for segment #1
[2022-10-23 16:19:34,874] [INFO] (highdicom.seg.sop) - add plane #68 for segment #1
[2022-10-23 16:19:34,875] [INFO] (highdicom.seg.sop) - add plane #69 for segment #1
[2022-10-23 16:19:34,876] [INFO] (highdicom.seg.sop) - add plane #70 for segment #1
[2022-10-23 16:19:34,877] [INFO] (highdicom.seg.sop) - add plane #71 for segment #1
[2022-10-23 16:19:34,878] [INFO] (highdicom.seg.sop) - add plane #72 for segment #1
[2022-10-23 16:19:34,878] [INFO] (highdicom.seg.sop) - add plane #73 for segment #1
[2022-10-23 16:19:34,879] [INFO] (highdicom.seg.sop) - add plane #74 for segment #1
[2022-10-23 16:19:34,880] [INFO] (highdicom.seg.sop) - add plane #75 for segment #1
[2022-10-23 16:19:34,882] [INFO] (highdicom.seg.sop) - add plane #76 for segment #1
[2022-10-23 16:19:34,883] [INFO] (highdicom.seg.sop) - add plane #77 for segment #1
[2022-10-23 16:19:34,884] [INFO] (highdicom.seg.sop) - add plane #78 for segment #1
[2022-10-23 16:19:34,885] [INFO] (highdicom.seg.sop) - add plane #79 for segment #1
[2022-10-23 16:19:34,886] [INFO] (highdicom.seg.sop) - add plane #80 for segment #1
[2022-10-23 16:19:34,887] [INFO] (highdicom.seg.sop) - add plane #81 for segment #1
[2022-10-23 16:19:34,888] [INFO] (highdicom.seg.sop) - add plane #82 for segment #1
[2022-10-23 16:19:34,889] [INFO] (highdicom.seg.sop) - add plane #83 for segment #1
[2022-10-23 16:19:34,890] [INFO] (highdicom.seg.sop) - add plane #84 for segment #1
[2022-10-23 16:19:34,891] [INFO] (highdicom.seg.sop) - add plane #85 for segment #1
[2022-10-23 16:19:34,892] [INFO] (highdicom.seg.sop) - add plane #86 for segment #1
[2022-10-23 16:19:34,926] [INFO] (highdicom.base) - copy Image-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:19:34,926] [INFO] (highdicom.base) - copy attributes of module "Specimen"
[2022-10-23 16:19:34,926] [INFO] (highdicom.base) - copy Patient-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:19:34,926] [INFO] (highdicom.base) - copy attributes of module "Patient"
[2022-10-23 16:19:34,926] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Subject"
[2022-10-23 16:19:34,926] [INFO] (highdicom.base) - copy Study-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:19:34,927] [INFO] (highdicom.base) - copy attributes of module "General Study"
[2022-10-23 16:19:34,927] [INFO] (highdicom.base) - copy attributes of module "Patient Study"
[2022-10-23 16:19:34,927] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Study"
Done performing execution of operator DICOMSegmentationWriterOperator

Going to initiate execution of operator DICOMSegmentationWriterOperator
Executing operator DICOMSegmentationWriterOperator (Process ID: 1304139, Operator ID: 2bfeb96e-a8a9-43c6-bbb8-bd76590be9e0)
[2022-10-23 16:19:36,319] [INFO] (highdicom.seg.sop) - add plane #0 for segment #1
[2022-10-23 16:19:36,320] [INFO] (highdicom.seg.sop) - add plane #1 for segment #1
[2022-10-23 16:19:36,321] [INFO] (highdicom.seg.sop) - add plane #2 for segment #1
[2022-10-23 16:19:36,322] [INFO] (highdicom.seg.sop) - add plane #3 for segment #1
[2022-10-23 16:19:36,323] [INFO] (highdicom.seg.sop) - add plane #4 for segment #1
[2022-10-23 16:19:36,324] [INFO] (highdicom.seg.sop) - add plane #5 for segment #1
[2022-10-23 16:19:36,325] [INFO] (highdicom.seg.sop) - add plane #6 for segment #1
[2022-10-23 16:19:36,326] [INFO] (highdicom.seg.sop) - add plane #7 for segment #1
[2022-10-23 16:19:36,327] [INFO] (highdicom.seg.sop) - add plane #8 for segment #1
[2022-10-23 16:19:36,328] [INFO] (highdicom.seg.sop) - add plane #9 for segment #1
[2022-10-23 16:19:36,329] [INFO] (highdicom.seg.sop) - add plane #10 for segment #1
[2022-10-23 16:19:36,330] [INFO] (highdicom.seg.sop) - add plane #11 for segment #1
[2022-10-23 16:19:36,331] [INFO] (highdicom.seg.sop) - add plane #12 for segment #1
[2022-10-23 16:19:36,332] [INFO] (highdicom.seg.sop) - add plane #13 for segment #1
[2022-10-23 16:19:36,333] [INFO] (highdicom.seg.sop) - add plane #14 for segment #1
[2022-10-23 16:19:36,334] [INFO] (highdicom.seg.sop) - add plane #15 for segment #1
[2022-10-23 16:19:36,335] [INFO] (highdicom.seg.sop) - add plane #16 for segment #1
[2022-10-23 16:19:36,336] [INFO] (highdicom.seg.sop) - add plane #17 for segment #1
[2022-10-23 16:19:36,337] [INFO] (highdicom.seg.sop) - add plane #18 for segment #1
[2022-10-23 16:19:36,338] [INFO] (highdicom.seg.sop) - add plane #19 for segment #1
[2022-10-23 16:19:36,339] [INFO] (highdicom.seg.sop) - add plane #20 for segment #1
[2022-10-23 16:19:36,340] [INFO] (highdicom.seg.sop) - add plane #21 for segment #1
[2022-10-23 16:19:36,341] [INFO] (highdicom.seg.sop) - add plane #22 for segment #1
[2022-10-23 16:19:36,342] [INFO] (highdicom.seg.sop) - add plane #23 for segment #1
[2022-10-23 16:19:36,343] [INFO] (highdicom.seg.sop) - add plane #24 for segment #1
[2022-10-23 16:19:36,344] [INFO] (highdicom.seg.sop) - add plane #25 for segment #1
[2022-10-23 16:19:36,345] [INFO] (highdicom.seg.sop) - add plane #26 for segment #1
[2022-10-23 16:19:36,346] [INFO] (highdicom.seg.sop) - add plane #27 for segment #1
[2022-10-23 16:19:36,347] [INFO] (highdicom.seg.sop) - add plane #28 for segment #1
[2022-10-23 16:19:36,348] [INFO] (highdicom.seg.sop) - add plane #29 for segment #1
[2022-10-23 16:19:36,349] [INFO] (highdicom.seg.sop) - add plane #30 for segment #1
[2022-10-23 16:19:36,350] [INFO] (highdicom.seg.sop) - add plane #31 for segment #1
[2022-10-23 16:19:36,351] [INFO] (highdicom.seg.sop) - add plane #32 for segment #1
[2022-10-23 16:19:36,352] [INFO] (highdicom.seg.sop) - add plane #33 for segment #1
[2022-10-23 16:19:36,352] [INFO] (highdicom.seg.sop) - add plane #34 for segment #1
[2022-10-23 16:19:36,353] [INFO] (highdicom.seg.sop) - add plane #35 for segment #1
[2022-10-23 16:19:36,354] [INFO] (highdicom.seg.sop) - add plane #36 for segment #1
[2022-10-23 16:19:36,355] [INFO] (highdicom.seg.sop) - add plane #37 for segment #1
[2022-10-23 16:19:36,356] [INFO] (highdicom.seg.sop) - add plane #38 for segment #1
[2022-10-23 16:19:36,357] [INFO] (highdicom.seg.sop) - add plane #39 for segment #1
[2022-10-23 16:19:36,358] [INFO] (highdicom.seg.sop) - add plane #40 for segment #1
[2022-10-23 16:19:36,359] [INFO] (highdicom.seg.sop) - add plane #41 for segment #1
[2022-10-23 16:19:36,360] [INFO] (highdicom.seg.sop) - add plane #42 for segment #1
[2022-10-23 16:19:36,361] [INFO] (highdicom.seg.sop) - add plane #43 for segment #1
[2022-10-23 16:19:36,363] [INFO] (highdicom.seg.sop) - add plane #44 for segment #1
[2022-10-23 16:19:36,364] [INFO] (highdicom.seg.sop) - add plane #45 for segment #1
[2022-10-23 16:19:36,365] [INFO] (highdicom.seg.sop) - add plane #46 for segment #1
[2022-10-23 16:19:36,366] [INFO] (highdicom.seg.sop) - add plane #47 for segment #1
[2022-10-23 16:19:36,367] [INFO] (highdicom.seg.sop) - add plane #48 for segment #1
[2022-10-23 16:19:36,368] [INFO] (highdicom.seg.sop) - add plane #49 for segment #1
[2022-10-23 16:19:36,369] [INFO] (highdicom.seg.sop) - add plane #50 for segment #1
[2022-10-23 16:19:36,370] [INFO] (highdicom.seg.sop) - add plane #51 for segment #1
[2022-10-23 16:19:36,371] [INFO] (highdicom.seg.sop) - add plane #52 for segment #1
[2022-10-23 16:19:36,372] [INFO] (highdicom.seg.sop) - add plane #53 for segment #1
[2022-10-23 16:19:36,373] [INFO] (highdicom.seg.sop) - add plane #54 for segment #1
[2022-10-23 16:19:36,374] [INFO] (highdicom.seg.sop) - add plane #55 for segment #1
[2022-10-23 16:19:36,376] [INFO] (highdicom.seg.sop) - add plane #56 for segment #1
[2022-10-23 16:19:36,377] [INFO] (highdicom.seg.sop) - add plane #57 for segment #1
[2022-10-23 16:19:36,378] [INFO] (highdicom.seg.sop) - add plane #58 for segment #1
[2022-10-23 16:19:36,379] [INFO] (highdicom.seg.sop) - add plane #59 for segment #1
[2022-10-23 16:19:36,380] [INFO] (highdicom.seg.sop) - add plane #60 for segment #1
[2022-10-23 16:19:36,381] [INFO] (highdicom.seg.sop) - add plane #61 for segment #1
[2022-10-23 16:19:36,382] [INFO] (highdicom.seg.sop) - add plane #62 for segment #1
[2022-10-23 16:19:36,383] [INFO] (highdicom.seg.sop) - add plane #63 for segment #1
[2022-10-23 16:19:36,384] [INFO] (highdicom.seg.sop) - add plane #64 for segment #1
[2022-10-23 16:19:36,385] [INFO] (highdicom.seg.sop) - add plane #65 for segment #1
[2022-10-23 16:19:36,386] [INFO] (highdicom.seg.sop) - add plane #66 for segment #1
[2022-10-23 16:19:36,387] [INFO] (highdicom.seg.sop) - add plane #67 for segment #1
[2022-10-23 16:19:36,412] [INFO] (highdicom.base) - copy Image-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:19:36,412] [INFO] (highdicom.base) - copy attributes of module "Specimen"
[2022-10-23 16:19:36,413] [INFO] (highdicom.base) - copy Patient-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:19:36,413] [INFO] (highdicom.base) - copy attributes of module "Patient"
[2022-10-23 16:19:36,413] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Subject"
[2022-10-23 16:19:36,413] [INFO] (highdicom.base) - copy Study-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:19:36,413] [INFO] (highdicom.base) - copy attributes of module "General Study"
[2022-10-23 16:19:36,413] [INFO] (highdicom.base) - copy attributes of module "Patient Study"
[2022-10-23 16:19:36,413] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Study"
Done performing execution of operator DICOMSegmentationWriterOperator

[2022-10-23 16:19:36,493] [INFO] (app.App) - End run

Above command is same with the following command line:

import os
os.environ['MKL_THREADING_LAYER'] = 'GNU'
!monai-deploy exec my_app -i dcm -o output -m multi_models
2022-10-23 16:19:41,503 - Begin compose
2022-10-23 16:19:41,505 - End compose
2022-10-23 16:19:41,505 - Begin run
Going to initiate execution of operator DICOMDataLoaderOperator
Executing operator DICOMDataLoaderOperator (Process ID: 1304251, Operator ID: 334fd88f-0c7a-4004-bf95-dcf21dc3fe7b)
Done performing execution of operator DICOMDataLoaderOperator

Going to initiate execution of operator DICOMSeriesSelectorOperator
Executing operator DICOMSeriesSelectorOperator (Process ID: 1304251, Operator ID: 060f7ba3-b44b-4950-b732-014887fc8a41)
[2022-10-23 16:19:42,025] [INFO] (root) - Finding series for Selection named: CT Series
[2022-10-23 16:19:42,025] [INFO] (root) - Searching study, : 1.3.6.1.4.1.14519.5.2.1.7085.2626.822645453932810382886582736291
  # of series: 1
[2022-10-23 16:19:42,026] [INFO] (root) - Working on series, instance UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239
[2022-10-23 16:19:42,026] [INFO] (root) - On attribute: 'StudyDescription' to match value: '(.*?)'
[2022-10-23 16:19:42,026] [INFO] (root) -     Series attribute StudyDescription value: CT ABDOMEN W IV CONTRAST
[2022-10-23 16:19:42,026] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 16:19:42,026] [INFO] (root) - On attribute: 'Modality' to match value: '(?i)CT'
[2022-10-23 16:19:42,026] [INFO] (root) -     Series attribute Modality value: CT
[2022-10-23 16:19:42,026] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 16:19:42,026] [INFO] (root) - On attribute: 'SeriesDescription' to match value: '(.*?)'
[2022-10-23 16:19:42,026] [INFO] (root) -     Series attribute SeriesDescription value: ABD/PANC 3.0 B31f
[2022-10-23 16:19:42,026] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 16:19:42,026] [INFO] (root) - Selected Series, UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239
Done performing execution of operator DICOMSeriesSelectorOperator

Going to initiate execution of operator DICOMSeriesToVolumeOperator
Executing operator DICOMSeriesToVolumeOperator (Process ID: 1304251, Operator ID: 0b23b294-4e3a-47f6-9a54-62e0cda43135)
Done performing execution of operator DICOMSeriesToVolumeOperator

Going to initiate execution of operator MonaiBundleInferenceOperator
Executing operator MonaiBundleInferenceOperator (Process ID: 1304251, Operator ID: 0d9916f3-9d87-4577-965a-89b7270e6509)
Done performing execution of operator MonaiBundleInferenceOperator

Going to initiate execution of operator MonaiBundleInferenceOperator
Executing operator MonaiBundleInferenceOperator (Process ID: 1304251, Operator ID: d6a9ceb4-9091-4cbd-ae01-a3ccda29ed26)
Done performing execution of operator MonaiBundleInferenceOperator

Going to initiate execution of operator DICOMSegmentationWriterOperator
Executing operator DICOMSegmentationWriterOperator (Process ID: 1304251, Operator ID: 9a75b60a-8e56-48b7-a1ed-b48fe4040bc1)
/home/mqin/src/monai-deploy-app-sdk/.venv/lib/python3.8/site-packages/highdicom/valuerep.py:54: UserWarning: The string "C3N-00198" is unlikely to represent the intended person name since it contains only a single component. Construct a person name according to the format in described in http://dicom.nema.org/dicom/2013/output/chtml/part05/sect_6.2.html#sect_6.2.1.2, or, in pydicom 2.2.0 or later, use the pydicom.valuerep.PersonName.from_named_components() method to construct the person name correctly. If a single-component name is really intended, add a trailing caret character to disambiguate the name.
  warnings.warn(
[2022-10-23 16:22:06,783] [INFO] (highdicom.seg.sop) - add plane #0 for segment #1
[2022-10-23 16:22:06,785] [INFO] (highdicom.seg.sop) - add plane #1 for segment #1
[2022-10-23 16:22:06,786] [INFO] (highdicom.seg.sop) - add plane #2 for segment #1
[2022-10-23 16:22:06,787] [INFO] (highdicom.seg.sop) - add plane #3 for segment #1
[2022-10-23 16:22:06,788] [INFO] (highdicom.seg.sop) - add plane #4 for segment #1
[2022-10-23 16:22:06,789] [INFO] (highdicom.seg.sop) - add plane #5 for segment #1
[2022-10-23 16:22:06,790] [INFO] (highdicom.seg.sop) - add plane #6 for segment #1
[2022-10-23 16:22:06,791] [INFO] (highdicom.seg.sop) - add plane #7 for segment #1
[2022-10-23 16:22:06,791] [INFO] (highdicom.seg.sop) - add plane #8 for segment #1
[2022-10-23 16:22:06,792] [INFO] (highdicom.seg.sop) - add plane #9 for segment #1
[2022-10-23 16:22:06,793] [INFO] (highdicom.seg.sop) - add plane #10 for segment #1
[2022-10-23 16:22:06,794] [INFO] (highdicom.seg.sop) - add plane #11 for segment #1
[2022-10-23 16:22:06,796] [INFO] (highdicom.seg.sop) - add plane #12 for segment #1
[2022-10-23 16:22:06,797] [INFO] (highdicom.seg.sop) - add plane #13 for segment #1
[2022-10-23 16:22:06,798] [INFO] (highdicom.seg.sop) - add plane #14 for segment #1
[2022-10-23 16:22:06,799] [INFO] (highdicom.seg.sop) - add plane #15 for segment #1
[2022-10-23 16:22:06,800] [INFO] (highdicom.seg.sop) - add plane #16 for segment #1
[2022-10-23 16:22:06,801] [INFO] (highdicom.seg.sop) - add plane #17 for segment #1
[2022-10-23 16:22:06,802] [INFO] (highdicom.seg.sop) - add plane #18 for segment #1
[2022-10-23 16:22:06,803] [INFO] (highdicom.seg.sop) - add plane #19 for segment #1
[2022-10-23 16:22:06,804] [INFO] (highdicom.seg.sop) - add plane #20 for segment #1
[2022-10-23 16:22:06,805] [INFO] (highdicom.seg.sop) - add plane #21 for segment #1
[2022-10-23 16:22:06,805] [INFO] (highdicom.seg.sop) - add plane #22 for segment #1
[2022-10-23 16:22:06,806] [INFO] (highdicom.seg.sop) - add plane #23 for segment #1
[2022-10-23 16:22:06,807] [INFO] (highdicom.seg.sop) - add plane #24 for segment #1
[2022-10-23 16:22:06,808] [INFO] (highdicom.seg.sop) - add plane #25 for segment #1
[2022-10-23 16:22:06,809] [INFO] (highdicom.seg.sop) - add plane #26 for segment #1
[2022-10-23 16:22:06,810] [INFO] (highdicom.seg.sop) - add plane #27 for segment #1
[2022-10-23 16:22:06,811] [INFO] (highdicom.seg.sop) - add plane #28 for segment #1
[2022-10-23 16:22:06,812] [INFO] (highdicom.seg.sop) - add plane #29 for segment #1
[2022-10-23 16:22:06,813] [INFO] (highdicom.seg.sop) - add plane #30 for segment #1
[2022-10-23 16:22:06,814] [INFO] (highdicom.seg.sop) - add plane #31 for segment #1
[2022-10-23 16:22:06,815] [INFO] (highdicom.seg.sop) - add plane #32 for segment #1
[2022-10-23 16:22:06,816] [INFO] (highdicom.seg.sop) - add plane #33 for segment #1
[2022-10-23 16:22:06,817] [INFO] (highdicom.seg.sop) - add plane #34 for segment #1
[2022-10-23 16:22:06,818] [INFO] (highdicom.seg.sop) - add plane #35 for segment #1
[2022-10-23 16:22:06,819] [INFO] (highdicom.seg.sop) - add plane #36 for segment #1
[2022-10-23 16:22:06,820] [INFO] (highdicom.seg.sop) - add plane #37 for segment #1
[2022-10-23 16:22:06,821] [INFO] (highdicom.seg.sop) - add plane #38 for segment #1
[2022-10-23 16:22:06,822] [INFO] (highdicom.seg.sop) - add plane #39 for segment #1
[2022-10-23 16:22:06,823] [INFO] (highdicom.seg.sop) - add plane #40 for segment #1
[2022-10-23 16:22:06,824] [INFO] (highdicom.seg.sop) - add plane #41 for segment #1
[2022-10-23 16:22:06,825] [INFO] (highdicom.seg.sop) - add plane #42 for segment #1
[2022-10-23 16:22:06,826] [INFO] (highdicom.seg.sop) - add plane #43 for segment #1
[2022-10-23 16:22:06,827] [INFO] (highdicom.seg.sop) - add plane #44 for segment #1
[2022-10-23 16:22:06,828] [INFO] (highdicom.seg.sop) - add plane #45 for segment #1
[2022-10-23 16:22:06,829] [INFO] (highdicom.seg.sop) - add plane #46 for segment #1
[2022-10-23 16:22:06,830] [INFO] (highdicom.seg.sop) - add plane #47 for segment #1
[2022-10-23 16:22:06,831] [INFO] (highdicom.seg.sop) - add plane #48 for segment #1
[2022-10-23 16:22:06,832] [INFO] (highdicom.seg.sop) - add plane #49 for segment #1
[2022-10-23 16:22:06,833] [INFO] (highdicom.seg.sop) - add plane #50 for segment #1
[2022-10-23 16:22:06,834] [INFO] (highdicom.seg.sop) - add plane #51 for segment #1
[2022-10-23 16:22:06,835] [INFO] (highdicom.seg.sop) - add plane #52 for segment #1
[2022-10-23 16:22:06,836] [INFO] (highdicom.seg.sop) - add plane #53 for segment #1
[2022-10-23 16:22:06,837] [INFO] (highdicom.seg.sop) - add plane #54 for segment #1
[2022-10-23 16:22:06,838] [INFO] (highdicom.seg.sop) - add plane #55 for segment #1
[2022-10-23 16:22:06,839] [INFO] (highdicom.seg.sop) - add plane #56 for segment #1
[2022-10-23 16:22:06,840] [INFO] (highdicom.seg.sop) - add plane #57 for segment #1
[2022-10-23 16:22:06,841] [INFO] (highdicom.seg.sop) - add plane #58 for segment #1
[2022-10-23 16:22:06,842] [INFO] (highdicom.seg.sop) - add plane #59 for segment #1
[2022-10-23 16:22:06,843] [INFO] (highdicom.seg.sop) - add plane #60 for segment #1
[2022-10-23 16:22:06,844] [INFO] (highdicom.seg.sop) - add plane #61 for segment #1
[2022-10-23 16:22:06,845] [INFO] (highdicom.seg.sop) - add plane #62 for segment #1
[2022-10-23 16:22:06,846] [INFO] (highdicom.seg.sop) - add plane #63 for segment #1
[2022-10-23 16:22:06,847] [INFO] (highdicom.seg.sop) - add plane #64 for segment #1
[2022-10-23 16:22:06,848] [INFO] (highdicom.seg.sop) - add plane #65 for segment #1
[2022-10-23 16:22:06,849] [INFO] (highdicom.seg.sop) - add plane #66 for segment #1
[2022-10-23 16:22:06,850] [INFO] (highdicom.seg.sop) - add plane #67 for segment #1
[2022-10-23 16:22:06,851] [INFO] (highdicom.seg.sop) - add plane #68 for segment #1
[2022-10-23 16:22:06,852] [INFO] (highdicom.seg.sop) - add plane #69 for segment #1
[2022-10-23 16:22:06,854] [INFO] (highdicom.seg.sop) - add plane #70 for segment #1
[2022-10-23 16:22:06,855] [INFO] (highdicom.seg.sop) - add plane #71 for segment #1
[2022-10-23 16:22:06,856] [INFO] (highdicom.seg.sop) - add plane #72 for segment #1
[2022-10-23 16:22:06,857] [INFO] (highdicom.seg.sop) - add plane #73 for segment #1
[2022-10-23 16:22:06,858] [INFO] (highdicom.seg.sop) - add plane #74 for segment #1
[2022-10-23 16:22:06,859] [INFO] (highdicom.seg.sop) - add plane #75 for segment #1
[2022-10-23 16:22:06,860] [INFO] (highdicom.seg.sop) - add plane #76 for segment #1
[2022-10-23 16:22:06,861] [INFO] (highdicom.seg.sop) - add plane #77 for segment #1
[2022-10-23 16:22:06,862] [INFO] (highdicom.seg.sop) - add plane #78 for segment #1
[2022-10-23 16:22:06,863] [INFO] (highdicom.seg.sop) - add plane #79 for segment #1
[2022-10-23 16:22:06,864] [INFO] (highdicom.seg.sop) - add plane #80 for segment #1
[2022-10-23 16:22:06,865] [INFO] (highdicom.seg.sop) - add plane #81 for segment #1
[2022-10-23 16:22:06,866] [INFO] (highdicom.seg.sop) - add plane #82 for segment #1
[2022-10-23 16:22:06,867] [INFO] (highdicom.seg.sop) - add plane #83 for segment #1
[2022-10-23 16:22:06,868] [INFO] (highdicom.seg.sop) - add plane #84 for segment #1
[2022-10-23 16:22:06,870] [INFO] (highdicom.seg.sop) - add plane #85 for segment #1
[2022-10-23 16:22:06,872] [INFO] (highdicom.seg.sop) - add plane #86 for segment #1
[2022-10-23 16:22:06,908] [INFO] (highdicom.base) - copy Image-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:22:06,908] [INFO] (highdicom.base) - copy attributes of module "Specimen"
[2022-10-23 16:22:06,908] [INFO] (highdicom.base) - copy Patient-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:22:06,908] [INFO] (highdicom.base) - copy attributes of module "Patient"
[2022-10-23 16:22:06,908] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Subject"
[2022-10-23 16:22:06,909] [INFO] (highdicom.base) - copy Study-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:22:06,909] [INFO] (highdicom.base) - copy attributes of module "General Study"
[2022-10-23 16:22:06,909] [INFO] (highdicom.base) - copy attributes of module "Patient Study"
[2022-10-23 16:22:06,909] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Study"
Done performing execution of operator DICOMSegmentationWriterOperator

Going to initiate execution of operator DICOMSegmentationWriterOperator
Executing operator DICOMSegmentationWriterOperator (Process ID: 1304251, Operator ID: 0e637a28-dd05-412f-83a4-0b24d88b2666)
[2022-10-23 16:22:08,310] [INFO] (highdicom.seg.sop) - add plane #0 for segment #1
[2022-10-23 16:22:08,312] [INFO] (highdicom.seg.sop) - add plane #1 for segment #1
[2022-10-23 16:22:08,313] [INFO] (highdicom.seg.sop) - add plane #2 for segment #1
[2022-10-23 16:22:08,315] [INFO] (highdicom.seg.sop) - add plane #3 for segment #1
[2022-10-23 16:22:08,316] [INFO] (highdicom.seg.sop) - add plane #4 for segment #1
[2022-10-23 16:22:08,317] [INFO] (highdicom.seg.sop) - add plane #5 for segment #1
[2022-10-23 16:22:08,319] [INFO] (highdicom.seg.sop) - add plane #6 for segment #1
[2022-10-23 16:22:08,320] [INFO] (highdicom.seg.sop) - add plane #7 for segment #1
[2022-10-23 16:22:08,322] [INFO] (highdicom.seg.sop) - add plane #8 for segment #1
[2022-10-23 16:22:08,323] [INFO] (highdicom.seg.sop) - add plane #9 for segment #1
[2022-10-23 16:22:08,324] [INFO] (highdicom.seg.sop) - add plane #10 for segment #1
[2022-10-23 16:22:08,326] [INFO] (highdicom.seg.sop) - add plane #11 for segment #1
[2022-10-23 16:22:08,327] [INFO] (highdicom.seg.sop) - add plane #12 for segment #1
[2022-10-23 16:22:08,329] [INFO] (highdicom.seg.sop) - add plane #13 for segment #1
[2022-10-23 16:22:08,330] [INFO] (highdicom.seg.sop) - add plane #14 for segment #1
[2022-10-23 16:22:08,331] [INFO] (highdicom.seg.sop) - add plane #15 for segment #1
[2022-10-23 16:22:08,333] [INFO] (highdicom.seg.sop) - add plane #16 for segment #1
[2022-10-23 16:22:08,334] [INFO] (highdicom.seg.sop) - add plane #17 for segment #1
[2022-10-23 16:22:08,336] [INFO] (highdicom.seg.sop) - add plane #18 for segment #1
[2022-10-23 16:22:08,337] [INFO] (highdicom.seg.sop) - add plane #19 for segment #1
[2022-10-23 16:22:08,338] [INFO] (highdicom.seg.sop) - add plane #20 for segment #1
[2022-10-23 16:22:08,340] [INFO] (highdicom.seg.sop) - add plane #21 for segment #1
[2022-10-23 16:22:08,341] [INFO] (highdicom.seg.sop) - add plane #22 for segment #1
[2022-10-23 16:22:08,342] [INFO] (highdicom.seg.sop) - add plane #23 for segment #1
[2022-10-23 16:22:08,344] [INFO] (highdicom.seg.sop) - add plane #24 for segment #1
[2022-10-23 16:22:08,345] [INFO] (highdicom.seg.sop) - add plane #25 for segment #1
[2022-10-23 16:22:08,347] [INFO] (highdicom.seg.sop) - add plane #26 for segment #1
[2022-10-23 16:22:08,348] [INFO] (highdicom.seg.sop) - add plane #27 for segment #1
[2022-10-23 16:22:08,349] [INFO] (highdicom.seg.sop) - add plane #28 for segment #1
[2022-10-23 16:22:08,351] [INFO] (highdicom.seg.sop) - add plane #29 for segment #1
[2022-10-23 16:22:08,352] [INFO] (highdicom.seg.sop) - add plane #30 for segment #1
[2022-10-23 16:22:08,354] [INFO] (highdicom.seg.sop) - add plane #31 for segment #1
[2022-10-23 16:22:08,355] [INFO] (highdicom.seg.sop) - add plane #32 for segment #1
[2022-10-23 16:22:08,356] [INFO] (highdicom.seg.sop) - add plane #33 for segment #1
[2022-10-23 16:22:08,358] [INFO] (highdicom.seg.sop) - add plane #34 for segment #1
[2022-10-23 16:22:08,359] [INFO] (highdicom.seg.sop) - add plane #35 for segment #1
[2022-10-23 16:22:08,361] [INFO] (highdicom.seg.sop) - add plane #36 for segment #1
[2022-10-23 16:22:08,362] [INFO] (highdicom.seg.sop) - add plane #37 for segment #1
[2022-10-23 16:22:08,364] [INFO] (highdicom.seg.sop) - add plane #38 for segment #1
[2022-10-23 16:22:08,365] [INFO] (highdicom.seg.sop) - add plane #39 for segment #1
[2022-10-23 16:22:08,366] [INFO] (highdicom.seg.sop) - add plane #40 for segment #1
[2022-10-23 16:22:08,368] [INFO] (highdicom.seg.sop) - add plane #41 for segment #1
[2022-10-23 16:22:08,369] [INFO] (highdicom.seg.sop) - add plane #42 for segment #1
[2022-10-23 16:22:08,371] [INFO] (highdicom.seg.sop) - add plane #43 for segment #1
[2022-10-23 16:22:08,372] [INFO] (highdicom.seg.sop) - add plane #44 for segment #1
[2022-10-23 16:22:08,374] [INFO] (highdicom.seg.sop) - add plane #45 for segment #1
[2022-10-23 16:22:08,375] [INFO] (highdicom.seg.sop) - add plane #46 for segment #1
[2022-10-23 16:22:08,376] [INFO] (highdicom.seg.sop) - add plane #47 for segment #1
[2022-10-23 16:22:08,378] [INFO] (highdicom.seg.sop) - add plane #48 for segment #1
[2022-10-23 16:22:08,379] [INFO] (highdicom.seg.sop) - add plane #49 for segment #1
[2022-10-23 16:22:08,381] [INFO] (highdicom.seg.sop) - add plane #50 for segment #1
[2022-10-23 16:22:08,382] [INFO] (highdicom.seg.sop) - add plane #51 for segment #1
[2022-10-23 16:22:08,384] [INFO] (highdicom.seg.sop) - add plane #52 for segment #1
[2022-10-23 16:22:08,385] [INFO] (highdicom.seg.sop) - add plane #53 for segment #1
[2022-10-23 16:22:08,387] [INFO] (highdicom.seg.sop) - add plane #54 for segment #1
[2022-10-23 16:22:08,388] [INFO] (highdicom.seg.sop) - add plane #55 for segment #1
[2022-10-23 16:22:08,390] [INFO] (highdicom.seg.sop) - add plane #56 for segment #1
[2022-10-23 16:22:08,391] [INFO] (highdicom.seg.sop) - add plane #57 for segment #1
[2022-10-23 16:22:08,392] [INFO] (highdicom.seg.sop) - add plane #58 for segment #1
[2022-10-23 16:22:08,394] [INFO] (highdicom.seg.sop) - add plane #59 for segment #1
[2022-10-23 16:22:08,395] [INFO] (highdicom.seg.sop) - add plane #60 for segment #1
[2022-10-23 16:22:08,397] [INFO] (highdicom.seg.sop) - add plane #61 for segment #1
[2022-10-23 16:22:08,399] [INFO] (highdicom.seg.sop) - add plane #62 for segment #1
[2022-10-23 16:22:08,401] [INFO] (highdicom.seg.sop) - add plane #63 for segment #1
[2022-10-23 16:22:08,402] [INFO] (highdicom.seg.sop) - add plane #64 for segment #1
[2022-10-23 16:22:08,404] [INFO] (highdicom.seg.sop) - add plane #65 for segment #1
[2022-10-23 16:22:08,405] [INFO] (highdicom.seg.sop) - add plane #66 for segment #1
[2022-10-23 16:22:08,406] [INFO] (highdicom.seg.sop) - add plane #67 for segment #1
[2022-10-23 16:22:08,435] [INFO] (highdicom.base) - copy Image-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:22:08,435] [INFO] (highdicom.base) - copy attributes of module "Specimen"
[2022-10-23 16:22:08,435] [INFO] (highdicom.base) - copy Patient-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:22:08,435] [INFO] (highdicom.base) - copy attributes of module "Patient"
[2022-10-23 16:22:08,436] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Subject"
[2022-10-23 16:22:08,436] [INFO] (highdicom.base) - copy Study-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 16:22:08,436] [INFO] (highdicom.base) - copy attributes of module "General Study"
[2022-10-23 16:22:08,436] [INFO] (highdicom.base) - copy attributes of module "Patient Study"
[2022-10-23 16:22:08,436] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Study"
Done performing execution of operator DICOMSegmentationWriterOperator

[2022-10-23 16:22:08,552] [INFO] (app.App) - End run
!ls output
1.2.826.0.1.3680043.10.511.3.32702698541528038834448962737039727.dcm
1.2.826.0.1.3680043.10.511.3.35243474063498201272181310164390593.dcm
1.2.826.0.1.3680043.10.511.3.58837783720965139512384663048368908.dcm
1.2.826.0.1.3680043.10.511.3.78470550325986881852478238471324433.dcm
1.2.826.0.1.3680043.10.511.3.92918041342174595727451303717701071.dcm
1.2.826.0.1.3680043.10.511.3.96456581526320710751208157315102845.dcm

Packaging app

Let’s package the app with MONAI Application Packager.

Note that with option -b a specific Nvidia PyTorch base docker image can be specified. Earlier versions of this image, e.g. nvcr.io/nvidia/pytorch:21.11-py3, caused Docker runtime errors in PyTorch, though the error only occurred when run in Jupyter.

!monai-deploy package -b nvcr.io/nvidia/pytorch:22.08-py3 my_app --tag my_app:latest -m multi_models
[2022-10-23 16:22:14,259] [INFO] (root) - Begin compose
[2022-10-23 16:22:14,261] [INFO] (root) - End compose
Building MONAI Application Package... Done
[2022-10-23 16:22:25,260] [INFO] (app_packager) - Successfully built my_app:latest

Note

Building a MONAI Application Package (Docker image) can take time. Use -l DEBUG option if you want to see the progress.

We can see that the Docker image is created.

!docker image ls | grep my_app
my_app                                                                latest                                     944face05f70   4 seconds ago       15.6GB

Executing packaged app locally

The packaged app can be run locally through MONAI Application Runner.

# Copy DICOM files are in 'dcm' folder

# Launch the app
!monai-deploy run my_app:latest dcm output
Checking dependencies...
--> Verifying if "docker" is installed...

--> Verifying if "my_app:latest" is available...

Checking for MAP "my_app:latest" locally
"my_app:latest" found.

Reading MONAI App Package manifest...
--> Verifying if "nvidia-docker" is installed...

/opt/conda/lib/python3.8/site-packages/scipy/__init__.py:138: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.4)
  warnings.warn(f"A NumPy version >={np_minversion} and <{np_maxversion} is required for this version of "
2022-10-23 23:22:41,163 - Begin compose
2022-10-23 23:22:41,166 - End compose
2022-10-23 23:22:41,166 - Begin run
Going to initiate execution of operator DICOMDataLoaderOperator
Executing operator DICOMDataLoaderOperator (Process ID: 1, Operator ID: 668c5a88-f99c-42d9-b204-e7a09de71572)
Done performing execution of operator DICOMDataLoaderOperator

Going to initiate execution of operator DICOMSeriesSelectorOperator
Executing operator DICOMSeriesSelectorOperator (Process ID: 1, Operator ID: 611f5234-1a92-4e40-a108-a99a0cba018a)
[2022-10-23 23:22:41,714] [INFO] (root) - Finding series for Selection named: CT Series
[2022-10-23 23:22:41,714] [INFO] (root) - Searching study, : 1.3.6.1.4.1.14519.5.2.1.7085.2626.822645453932810382886582736291
  # of series: 1
[2022-10-23 23:22:41,714] [INFO] (root) - Working on series, instance UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239
[2022-10-23 23:22:41,714] [INFO] (root) - On attribute: 'StudyDescription' to match value: '(.*?)'
[2022-10-23 23:22:41,714] [INFO] (root) -     Series attribute StudyDescription value: CT ABDOMEN W IV CONTRAST
[2022-10-23 23:22:41,714] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 23:22:41,714] [INFO] (root) - On attribute: 'Modality' to match value: '(?i)CT'
[2022-10-23 23:22:41,714] [INFO] (root) -     Series attribute Modality value: CT
[2022-10-23 23:22:41,714] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 23:22:41,714] [INFO] (root) - On attribute: 'SeriesDescription' to match value: '(.*?)'
[2022-10-23 23:22:41,714] [INFO] (root) -     Series attribute SeriesDescription value: ABD/PANC 3.0 B31f
[2022-10-23 23:22:41,714] [INFO] (root) - Series attribute string value did not match. Try regEx.
[2022-10-23 23:22:41,714] [INFO] (root) - Selected Series, UID: 1.3.6.1.4.1.14519.5.2.1.7085.2626.119403521930927333027265674239
Done performing execution of operator DICOMSeriesSelectorOperator

Going to initiate execution of operator DICOMSeriesToVolumeOperator
Executing operator DICOMSeriesToVolumeOperator (Process ID: 1, Operator ID: 6acc05c6-e023-47de-9323-321855c909f3)
Done performing execution of operator DICOMSeriesToVolumeOperator

Going to initiate execution of operator MonaiBundleInferenceOperator
Executing operator MonaiBundleInferenceOperator (Process ID: 1, Operator ID: 85070cf7-ccee-432f-92a6-ec810ac0a052)
Done performing execution of operator MonaiBundleInferenceOperator

Going to initiate execution of operator MonaiBundleInferenceOperator
Executing operator MonaiBundleInferenceOperator (Process ID: 1, Operator ID: 440a749c-6456-47f0-9913-c553a253bd6f)
Done performing execution of operator MonaiBundleInferenceOperator

Going to initiate execution of operator DICOMSegmentationWriterOperator
Executing operator DICOMSegmentationWriterOperator (Process ID: 1, Operator ID: 0ad2a122-51f4-4ac2-b6c1-87b26ac9cb26)
/root/.local/lib/python3.8/site-packages/highdicom/valuerep.py:54: UserWarning: The string "C3N-00198" is unlikely to represent the intended person name since it contains only a single component. Construct a person name according to the format in described in http://dicom.nema.org/dicom/2013/output/chtml/part05/sect_6.2.html#sect_6.2.1.2, or, in pydicom 2.2.0 or later, use the pydicom.valuerep.PersonName.from_named_components() method to construct the person name correctly. If a single-component name is really intended, add a trailing caret character to disambiguate the name.
  warnings.warn(
[2022-10-23 23:24:33,697] [INFO] (highdicom.seg.sop) - add plane #0 for segment #1
[2022-10-23 23:24:33,699] [INFO] (highdicom.seg.sop) - add plane #1 for segment #1
[2022-10-23 23:24:33,700] [INFO] (highdicom.seg.sop) - add plane #2 for segment #1
[2022-10-23 23:24:33,702] [INFO] (highdicom.seg.sop) - add plane #3 for segment #1
[2022-10-23 23:24:33,703] [INFO] (highdicom.seg.sop) - add plane #4 for segment #1
[2022-10-23 23:24:33,705] [INFO] (highdicom.seg.sop) - add plane #5 for segment #1
[2022-10-23 23:24:33,706] [INFO] (highdicom.seg.sop) - add plane #6 for segment #1
[2022-10-23 23:24:33,708] [INFO] (highdicom.seg.sop) - add plane #7 for segment #1
[2022-10-23 23:24:33,709] [INFO] (highdicom.seg.sop) - add plane #8 for segment #1
[2022-10-23 23:24:33,711] [INFO] (highdicom.seg.sop) - add plane #9 for segment #1
[2022-10-23 23:24:33,712] [INFO] (highdicom.seg.sop) - add plane #10 for segment #1
[2022-10-23 23:24:33,714] [INFO] (highdicom.seg.sop) - add plane #11 for segment #1
[2022-10-23 23:24:33,715] [INFO] (highdicom.seg.sop) - add plane #12 for segment #1
[2022-10-23 23:24:33,717] [INFO] (highdicom.seg.sop) - add plane #13 for segment #1
[2022-10-23 23:24:33,718] [INFO] (highdicom.seg.sop) - add plane #14 for segment #1
[2022-10-23 23:24:33,719] [INFO] (highdicom.seg.sop) - add plane #15 for segment #1
[2022-10-23 23:24:33,721] [INFO] (highdicom.seg.sop) - add plane #16 for segment #1
[2022-10-23 23:24:33,722] [INFO] (highdicom.seg.sop) - add plane #17 for segment #1
[2022-10-23 23:24:33,724] [INFO] (highdicom.seg.sop) - add plane #18 for segment #1
[2022-10-23 23:24:33,725] [INFO] (highdicom.seg.sop) - add plane #19 for segment #1
[2022-10-23 23:24:33,727] [INFO] (highdicom.seg.sop) - add plane #20 for segment #1
[2022-10-23 23:24:33,728] [INFO] (highdicom.seg.sop) - add plane #21 for segment #1
[2022-10-23 23:24:33,730] [INFO] (highdicom.seg.sop) - add plane #22 for segment #1
[2022-10-23 23:24:33,731] [INFO] (highdicom.seg.sop) - add plane #23 for segment #1
[2022-10-23 23:24:33,733] [INFO] (highdicom.seg.sop) - add plane #24 for segment #1
[2022-10-23 23:24:33,734] [INFO] (highdicom.seg.sop) - add plane #25 for segment #1
[2022-10-23 23:24:33,736] [INFO] (highdicom.seg.sop) - add plane #26 for segment #1
[2022-10-23 23:24:33,738] [INFO] (highdicom.seg.sop) - add plane #27 for segment #1
[2022-10-23 23:24:33,740] [INFO] (highdicom.seg.sop) - add plane #28 for segment #1
[2022-10-23 23:24:33,741] [INFO] (highdicom.seg.sop) - add plane #29 for segment #1
[2022-10-23 23:24:33,743] [INFO] (highdicom.seg.sop) - add plane #30 for segment #1
[2022-10-23 23:24:33,744] [INFO] (highdicom.seg.sop) - add plane #31 for segment #1
[2022-10-23 23:24:33,746] [INFO] (highdicom.seg.sop) - add plane #32 for segment #1
[2022-10-23 23:24:33,747] [INFO] (highdicom.seg.sop) - add plane #33 for segment #1
[2022-10-23 23:24:33,749] [INFO] (highdicom.seg.sop) - add plane #34 for segment #1
[2022-10-23 23:24:33,750] [INFO] (highdicom.seg.sop) - add plane #35 for segment #1
[2022-10-23 23:24:33,752] [INFO] (highdicom.seg.sop) - add plane #36 for segment #1
[2022-10-23 23:24:33,753] [INFO] (highdicom.seg.sop) - add plane #37 for segment #1
[2022-10-23 23:24:33,755] [INFO] (highdicom.seg.sop) - add plane #38 for segment #1
[2022-10-23 23:24:33,756] [INFO] (highdicom.seg.sop) - add plane #39 for segment #1
[2022-10-23 23:24:33,758] [INFO] (highdicom.seg.sop) - add plane #40 for segment #1
[2022-10-23 23:24:33,759] [INFO] (highdicom.seg.sop) - add plane #41 for segment #1
[2022-10-23 23:24:33,761] [INFO] (highdicom.seg.sop) - add plane #42 for segment #1
[2022-10-23 23:24:33,762] [INFO] (highdicom.seg.sop) - add plane #43 for segment #1
[2022-10-23 23:24:33,764] [INFO] (highdicom.seg.sop) - add plane #44 for segment #1
[2022-10-23 23:24:33,766] [INFO] (highdicom.seg.sop) - add plane #45 for segment #1
[2022-10-23 23:24:33,767] [INFO] (highdicom.seg.sop) - add plane #46 for segment #1
[2022-10-23 23:24:33,769] [INFO] (highdicom.seg.sop) - add plane #47 for segment #1
[2022-10-23 23:24:33,770] [INFO] (highdicom.seg.sop) - add plane #48 for segment #1
[2022-10-23 23:24:33,772] [INFO] (highdicom.seg.sop) - add plane #49 for segment #1
[2022-10-23 23:24:33,773] [INFO] (highdicom.seg.sop) - add plane #50 for segment #1
[2022-10-23 23:24:33,775] [INFO] (highdicom.seg.sop) - add plane #51 for segment #1
[2022-10-23 23:24:33,777] [INFO] (highdicom.seg.sop) - add plane #52 for segment #1
[2022-10-23 23:24:33,778] [INFO] (highdicom.seg.sop) - add plane #53 for segment #1
[2022-10-23 23:24:33,780] [INFO] (highdicom.seg.sop) - add plane #54 for segment #1
[2022-10-23 23:24:33,782] [INFO] (highdicom.seg.sop) - add plane #55 for segment #1
[2022-10-23 23:24:33,784] [INFO] (highdicom.seg.sop) - add plane #56 for segment #1
[2022-10-23 23:24:33,785] [INFO] (highdicom.seg.sop) - add plane #57 for segment #1
[2022-10-23 23:24:33,787] [INFO] (highdicom.seg.sop) - add plane #58 for segment #1
[2022-10-23 23:24:33,788] [INFO] (highdicom.seg.sop) - add plane #59 for segment #1
[2022-10-23 23:24:33,790] [INFO] (highdicom.seg.sop) - add plane #60 for segment #1
[2022-10-23 23:24:33,792] [INFO] (highdicom.seg.sop) - add plane #61 for segment #1
[2022-10-23 23:24:33,793] [INFO] (highdicom.seg.sop) - add plane #62 for segment #1
[2022-10-23 23:24:33,795] [INFO] (highdicom.seg.sop) - add plane #63 for segment #1
[2022-10-23 23:24:33,796] [INFO] (highdicom.seg.sop) - add plane #64 for segment #1
[2022-10-23 23:24:33,798] [INFO] (highdicom.seg.sop) - add plane #65 for segment #1
[2022-10-23 23:24:33,800] [INFO] (highdicom.seg.sop) - add plane #66 for segment #1
[2022-10-23 23:24:33,801] [INFO] (highdicom.seg.sop) - add plane #67 for segment #1
[2022-10-23 23:24:33,803] [INFO] (highdicom.seg.sop) - add plane #68 for segment #1
[2022-10-23 23:24:33,804] [INFO] (highdicom.seg.sop) - add plane #69 for segment #1
[2022-10-23 23:24:33,806] [INFO] (highdicom.seg.sop) - add plane #70 for segment #1
[2022-10-23 23:24:33,808] [INFO] (highdicom.seg.sop) - add plane #71 for segment #1
[2022-10-23 23:24:33,809] [INFO] (highdicom.seg.sop) - add plane #72 for segment #1
[2022-10-23 23:24:33,811] [INFO] (highdicom.seg.sop) - add plane #73 for segment #1
[2022-10-23 23:24:33,813] [INFO] (highdicom.seg.sop) - add plane #74 for segment #1
[2022-10-23 23:24:33,814] [INFO] (highdicom.seg.sop) - add plane #75 for segment #1
[2022-10-23 23:24:33,816] [INFO] (highdicom.seg.sop) - add plane #76 for segment #1
[2022-10-23 23:24:33,817] [INFO] (highdicom.seg.sop) - add plane #77 for segment #1
[2022-10-23 23:24:33,819] [INFO] (highdicom.seg.sop) - add plane #78 for segment #1
[2022-10-23 23:24:33,821] [INFO] (highdicom.seg.sop) - add plane #79 for segment #1
[2022-10-23 23:24:33,822] [INFO] (highdicom.seg.sop) - add plane #80 for segment #1
[2022-10-23 23:24:33,824] [INFO] (highdicom.seg.sop) - add plane #81 for segment #1
[2022-10-23 23:24:33,826] [INFO] (highdicom.seg.sop) - add plane #82 for segment #1
[2022-10-23 23:24:33,827] [INFO] (highdicom.seg.sop) - add plane #83 for segment #1
[2022-10-23 23:24:33,829] [INFO] (highdicom.seg.sop) - add plane #84 for segment #1
[2022-10-23 23:24:33,831] [INFO] (highdicom.seg.sop) - add plane #85 for segment #1
[2022-10-23 23:24:33,832] [INFO] (highdicom.seg.sop) - add plane #86 for segment #1
[2022-10-23 23:24:33,874] [INFO] (highdicom.base) - copy Image-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 23:24:33,874] [INFO] (highdicom.base) - copy attributes of module "Specimen"
[2022-10-23 23:24:33,875] [INFO] (highdicom.base) - copy Patient-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 23:24:33,875] [INFO] (highdicom.base) - copy attributes of module "Patient"
[2022-10-23 23:24:33,875] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Subject"
[2022-10-23 23:24:33,875] [INFO] (highdicom.base) - copy Study-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 23:24:33,875] [INFO] (highdicom.base) - copy attributes of module "General Study"
[2022-10-23 23:24:33,876] [INFO] (highdicom.base) - copy attributes of module "Patient Study"
[2022-10-23 23:24:33,876] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Study"
Done performing execution of operator DICOMSegmentationWriterOperator

Going to initiate execution of operator DICOMSegmentationWriterOperator
Executing operator DICOMSegmentationWriterOperator (Process ID: 1, Operator ID: ff56e972-1df7-4945-b474-b072cbfc6b57)
[2022-10-23 23:24:35,330] [INFO] (highdicom.seg.sop) - add plane #0 for segment #1
[2022-10-23 23:24:35,332] [INFO] (highdicom.seg.sop) - add plane #1 for segment #1
[2022-10-23 23:24:35,333] [INFO] (highdicom.seg.sop) - add plane #2 for segment #1
[2022-10-23 23:24:35,335] [INFO] (highdicom.seg.sop) - add plane #3 for segment #1
[2022-10-23 23:24:35,336] [INFO] (highdicom.seg.sop) - add plane #4 for segment #1
[2022-10-23 23:24:35,338] [INFO] (highdicom.seg.sop) - add plane #5 for segment #1
[2022-10-23 23:24:35,339] [INFO] (highdicom.seg.sop) - add plane #6 for segment #1
[2022-10-23 23:24:35,340] [INFO] (highdicom.seg.sop) - add plane #7 for segment #1
[2022-10-23 23:24:35,342] [INFO] (highdicom.seg.sop) - add plane #8 for segment #1
[2022-10-23 23:24:35,343] [INFO] (highdicom.seg.sop) - add plane #9 for segment #1
[2022-10-23 23:24:35,345] [INFO] (highdicom.seg.sop) - add plane #10 for segment #1
[2022-10-23 23:24:35,346] [INFO] (highdicom.seg.sop) - add plane #11 for segment #1
[2022-10-23 23:24:35,347] [INFO] (highdicom.seg.sop) - add plane #12 for segment #1
[2022-10-23 23:24:35,349] [INFO] (highdicom.seg.sop) - add plane #13 for segment #1
[2022-10-23 23:24:35,350] [INFO] (highdicom.seg.sop) - add plane #14 for segment #1
[2022-10-23 23:24:35,352] [INFO] (highdicom.seg.sop) - add plane #15 for segment #1
[2022-10-23 23:24:35,353] [INFO] (highdicom.seg.sop) - add plane #16 for segment #1
[2022-10-23 23:24:35,355] [INFO] (highdicom.seg.sop) - add plane #17 for segment #1
[2022-10-23 23:24:35,356] [INFO] (highdicom.seg.sop) - add plane #18 for segment #1
[2022-10-23 23:24:35,357] [INFO] (highdicom.seg.sop) - add plane #19 for segment #1
[2022-10-23 23:24:35,359] [INFO] (highdicom.seg.sop) - add plane #20 for segment #1
[2022-10-23 23:24:35,360] [INFO] (highdicom.seg.sop) - add plane #21 for segment #1
[2022-10-23 23:24:35,362] [INFO] (highdicom.seg.sop) - add plane #22 for segment #1
[2022-10-23 23:24:35,363] [INFO] (highdicom.seg.sop) - add plane #23 for segment #1
[2022-10-23 23:24:35,365] [INFO] (highdicom.seg.sop) - add plane #24 for segment #1
[2022-10-23 23:24:35,366] [INFO] (highdicom.seg.sop) - add plane #25 for segment #1
[2022-10-23 23:24:35,367] [INFO] (highdicom.seg.sop) - add plane #26 for segment #1
[2022-10-23 23:24:35,369] [INFO] (highdicom.seg.sop) - add plane #27 for segment #1
[2022-10-23 23:24:35,370] [INFO] (highdicom.seg.sop) - add plane #28 for segment #1
[2022-10-23 23:24:35,372] [INFO] (highdicom.seg.sop) - add plane #29 for segment #1
[2022-10-23 23:24:35,373] [INFO] (highdicom.seg.sop) - add plane #30 for segment #1
[2022-10-23 23:24:35,375] [INFO] (highdicom.seg.sop) - add plane #31 for segment #1
[2022-10-23 23:24:35,376] [INFO] (highdicom.seg.sop) - add plane #32 for segment #1
[2022-10-23 23:24:35,378] [INFO] (highdicom.seg.sop) - add plane #33 for segment #1
[2022-10-23 23:24:35,379] [INFO] (highdicom.seg.sop) - add plane #34 for segment #1
[2022-10-23 23:24:35,381] [INFO] (highdicom.seg.sop) - add plane #35 for segment #1
[2022-10-23 23:24:35,383] [INFO] (highdicom.seg.sop) - add plane #36 for segment #1
[2022-10-23 23:24:35,384] [INFO] (highdicom.seg.sop) - add plane #37 for segment #1
[2022-10-23 23:24:35,386] [INFO] (highdicom.seg.sop) - add plane #38 for segment #1
[2022-10-23 23:24:35,387] [INFO] (highdicom.seg.sop) - add plane #39 for segment #1
[2022-10-23 23:24:35,389] [INFO] (highdicom.seg.sop) - add plane #40 for segment #1
[2022-10-23 23:24:35,390] [INFO] (highdicom.seg.sop) - add plane #41 for segment #1
[2022-10-23 23:24:35,391] [INFO] (highdicom.seg.sop) - add plane #42 for segment #1
[2022-10-23 23:24:35,393] [INFO] (highdicom.seg.sop) - add plane #43 for segment #1
[2022-10-23 23:24:35,395] [INFO] (highdicom.seg.sop) - add plane #44 for segment #1
[2022-10-23 23:24:35,396] [INFO] (highdicom.seg.sop) - add plane #45 for segment #1
[2022-10-23 23:24:35,397] [INFO] (highdicom.seg.sop) - add plane #46 for segment #1
[2022-10-23 23:24:35,399] [INFO] (highdicom.seg.sop) - add plane #47 for segment #1
[2022-10-23 23:24:35,400] [INFO] (highdicom.seg.sop) - add plane #48 for segment #1
[2022-10-23 23:24:35,402] [INFO] (highdicom.seg.sop) - add plane #49 for segment #1
[2022-10-23 23:24:35,403] [INFO] (highdicom.seg.sop) - add plane #50 for segment #1
[2022-10-23 23:24:35,405] [INFO] (highdicom.seg.sop) - add plane #51 for segment #1
[2022-10-23 23:24:35,406] [INFO] (highdicom.seg.sop) - add plane #52 for segment #1
[2022-10-23 23:24:35,408] [INFO] (highdicom.seg.sop) - add plane #53 for segment #1
[2022-10-23 23:24:35,409] [INFO] (highdicom.seg.sop) - add plane #54 for segment #1
[2022-10-23 23:24:35,411] [INFO] (highdicom.seg.sop) - add plane #55 for segment #1
[2022-10-23 23:24:35,413] [INFO] (highdicom.seg.sop) - add plane #56 for segment #1
[2022-10-23 23:24:35,414] [INFO] (highdicom.seg.sop) - add plane #57 for segment #1
[2022-10-23 23:24:35,416] [INFO] (highdicom.seg.sop) - add plane #58 for segment #1
[2022-10-23 23:24:35,417] [INFO] (highdicom.seg.sop) - add plane #59 for segment #1
[2022-10-23 23:24:35,419] [INFO] (highdicom.seg.sop) - add plane #60 for segment #1
[2022-10-23 23:24:35,420] [INFO] (highdicom.seg.sop) - add plane #61 for segment #1
[2022-10-23 23:24:35,422] [INFO] (highdicom.seg.sop) - add plane #62 for segment #1
[2022-10-23 23:24:35,423] [INFO] (highdicom.seg.sop) - add plane #63 for segment #1
[2022-10-23 23:24:35,425] [INFO] (highdicom.seg.sop) - add plane #64 for segment #1
[2022-10-23 23:24:35,426] [INFO] (highdicom.seg.sop) - add plane #65 for segment #1
[2022-10-23 23:24:35,428] [INFO] (highdicom.seg.sop) - add plane #66 for segment #1
[2022-10-23 23:24:35,429] [INFO] (highdicom.seg.sop) - add plane #67 for segment #1
[2022-10-23 23:24:35,465] [INFO] (highdicom.base) - copy Image-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 23:24:35,465] [INFO] (highdicom.base) - copy attributes of module "Specimen"
[2022-10-23 23:24:35,465] [INFO] (highdicom.base) - copy Patient-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 23:24:35,465] [INFO] (highdicom.base) - copy attributes of module "Patient"
[2022-10-23 23:24:35,466] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Subject"
[2022-10-23 23:24:35,466] [INFO] (highdicom.base) - copy Study-related attributes from dataset "1.3.6.1.4.1.14519.5.2.1.7085.2626.936983343951485811186213470191"
[2022-10-23 23:24:35,466] [INFO] (highdicom.base) - copy attributes of module "General Study"
[2022-10-23 23:24:35,466] [INFO] (highdicom.base) - copy attributes of module "Patient Study"
[2022-10-23 23:24:35,466] [INFO] (highdicom.base) - copy attributes of module "Clinical Trial Study"
Done performing execution of operator DICOMSegmentationWriterOperator

[2022-10-23 23:24:35,584] [INFO] (__main__.App) - End run
!ls output
1.2.826.0.1.3680043.10.511.3.12552687019247779801993647988962741.dcm
1.2.826.0.1.3680043.10.511.3.32702698541528038834448962737039727.dcm
1.2.826.0.1.3680043.10.511.3.35243474063498201272181310164390593.dcm
1.2.826.0.1.3680043.10.511.3.58837783720965139512384663048368908.dcm
1.2.826.0.1.3680043.10.511.3.78470550325986881852478238471324433.dcm
1.2.826.0.1.3680043.10.511.3.79550200308831900854298455254044232.dcm
1.2.826.0.1.3680043.10.511.3.92918041342174595727451303717701071.dcm
1.2.826.0.1.3680043.10.511.3.96456581526320710751208157315102845.dcm