Deploying Segmentation App with MONAI Inference Service (MIS)

This tutorial discusses how to deploy the segmentation application with the RESTful MONAI Inference Service.

Please refer back to the previous tutorial for creating the Segmentation App using MONAI App SDK

In the following sections, we will demonstrate how to deploy a packaged MONAI Application with the MONAI Inference Service. Along the way we will provide verification steps to confirm that our application produces the desired output both locally (for verification) and as a service output.

Exporting Application and Package Manifest Files

Given a succesfully built MAP image (ex. my_app:latest from previous tutorial), its manifest files can be extracted with all configured paramters. This can be done by running docker run with the image and making sure to map a local volume (ex. ./output) to "/var/run/monai/export/config/" within the contianer

!mkdir ./export
!docker run -it -v "$(pwd)/export/":"/var/run/monai/export/config/" my_app:latest
[?1h= > export '/var/run/monai/export/' detected

After running, two .json files (application and package manifests) can be found inside of the local directory volume mount

!ls ./export/
app.json  pkg.json
!cat ./export/app.json
{
    "api-version": "0.1.0",
    "command": "python3 -u /opt/monai/app/app.py",
    "environment": {},
    "input": {
        "formats": [],
        "path": "input"
    },
    "output": {
        "format": {},
        "path": "output"
    },
    "sdk-version": "0.2.0",
    "timeout": 0,
    "version": "0.0.0",
    "working-directory": "/var/monai/"
}
!cat ./export/pkg.json
{
    "api-version": "0.1.0",
    "application-root": "/var/monai/",
    "models": [
        {
            "name": "model-54dd6cdaac290a0e800c0fa627cd60410bb2cea173ac8bb2f4816cc54ea88c90",
            "path": "/opt/monai/models/model/model.pt"
        }
    ],
    "resources": {
        "cpu": 1,
        "gpu": 1,
        "memory": "7168Mi"
    },
    "sdk-version": "0.2.0",
    "version": "0.0.0"
}

Deploying MONAI Inference Service (MIS)

With the MONAI application package image we built, we can now deploy it with the MONAI Inference Service.

This is a RESTful service which will allow other users to make inference requests with our MAP using HTTP.

We first need to acquire the MIS helm charts and provide them with information of our MAP, as well as the name and tag of the MIS image we wish to use (pritishnahar/monai-deploy:inference-service-0.1)

!pip install gdown
!gdown https://drive.google.com/uc?id=12uNO1tyqZh1oFkZH41Osliey7TRm-BBG
!unzip -o charts.zip
Collecting gdown
  Using cached gdown-4.2.0-py3-none-any.whl
Collecting tqdm
  Using cached tqdm-4.62.3-py2.py3-none-any.whl (76 kB)
Requirement already satisfied: six in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from gdown) (1.16.0)
Requirement already satisfied: requests[socks] in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from gdown) (2.12.5)
Collecting filelock
  Downloading filelock-3.4.0-py3-none-any.whl (9.8 kB)
Collecting beautifulsoup4
  Downloading beautifulsoup4-4.10.0-py3-none-any.whl (97 kB)
     |████████████████████████████████| 97 kB 1.2 MB/s eta 0:00:011
?25hCollecting soupsieve>1.2
  Downloading soupsieve-2.3.1-py3-none-any.whl (37 kB)
Collecting PySocks!=1.5.7,>=1.5.6
  Using cached PySocks-1.7.1-py3-none-any.whl (16 kB)
Installing collected packages: soupsieve, PySocks, tqdm, filelock, beautifulsoup4, gdown
Successfully installed PySocks-1.7.1 beautifulsoup4-4.10.0 filelock-3.4.0 gdown-4.2.0 soupsieve-2.3.1 tqdm-4.62.3
Downloading...
From: https://drive.google.com/uc?id=12uNO1tyqZh1oFkZH41Osliey7TRm-BBG
To: /data/Vikash/Tools/RSNA/monai-deploy-app-sdk/notebooks/tutorials/charts.zip
100%|███████████████████████████████████████| 9.18k/9.18k [00:00<00:00, 284kB/s]
Archive:  charts.zip
   creating: charts/
   creating: charts/templates/
  inflating: charts/templates/monaiinferenceservice-deployment.yaml  
  inflating: charts/templates/monaiinferenceservice-service.yaml  
  inflating: charts/templates/monaiinferenceservice-clusterrole.yaml  
  inflating: charts/templates/monaiinferenceservice-payload-volume.yaml  
  inflating: charts/templates/monaiinferenceservice-serviceaccount.yaml  
  inflating: charts/templates/monaiinferenceservice-clusterrolebinding.yaml  
  inflating: charts/templates/monaiinferenceservice-payload-volume-claim.yaml  
  inflating: charts/templates/_helpers.tpl  
  inflating: charts/Chart.yaml       
  inflating: charts/values.yaml      

Before starting MONAI Inference Service, a set of values must be specified within ./charts/values.yaml to configure the MIS instance with a MAP:

Parameter

Value Description

images.monaiInferenceServiceTag

MONAI Inference Service image name (pritishnahar/monai-deploy)

images.monaiInferenceService

MONAI Inference Service image tag (inference-service-0.1)

payloadService.hostVolumePath

Path to a local directory which will serve as a shared volume for payloads between MIS and its pods

map.urn

Name:Tag of MAP image built with MONAI application packager

map.entrypoint

Application entrypoint which can obtained from app.json

map.cpu

Number of CPUs requested by application which can be obtained either from pkg.json OR from when we created app.py (check @resource decorator)

map.memory

Memory requested by application which can be obtained either from pkg.json OR from when we created app.py (check @resource decorator)

map.gpu

Number of GPUs requested by application which can be obtained either from pkg.json OR from when we created app.py (check @resource decorator)

map.inputPath

Input volume path within MAP container, can be derived by appending the input.path with the working-directory in app.json

map.outputPath

Output volume path within MAP container, can be derived by appending the output.path with the working-directory in app.json

map.modelPath

Model volume path within MAP container, can be derived using a path of an entry under models in pkg.json, and taking the sub-path where the /model folder resides (ex: path: "/opt/monai/models/model/model.pt" -> "/opt/monai/models")

%%writefile charts/values.yaml
# Default values for MONAI Inference Service.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
images:
  monaiInferenceService: pritishnahar/monai-deploy
  monaiInferenceServiceTag: inference-service-0.1

########################################################
#   Configuration Values for MONAI Inference Service   #
########################################################

server:
  names:
    clusterRole: monai-inference-service-cluster-role
    clusterRoleBinding: monai-inference-service-binding
    deployment: monai-inference-service
    service: monai-inference-service
    serviceAccount: monai-inference-service-service-account
    storageClass: monai-inference-service-storage-class
    volume: monai-inference-service-payload-volume
    volumeClaim: monai-inference-service-payload-volume-claim

  serviceType: NodePort # Alternatively: ClusterIp if only in cluster clients will exist
  nodePort: 32000
  pullSecrets: []
  targetPort: 8000

  # Configuration for the payload service in the MONAI Inference Service.
  payloadService:
    # The path on the node running MONAI Inference Service where a payload will be stored.
    # The input directory and output directory that are created by MONAI Inference Service
    # will exist as a directory inside this path. 
    # (e.g. "/monai/payload/input").
    # Please make sure that this directory has read, write, and execute permissions for the user,
    # group, and all other users `rwxrwxrwx`. Running `chmod 777 <hostVolumePath>` will achomplish this.
    hostVolumePath: "/monai/payload"

  # MAP configuration.
  map:
    # MAP Container <image>:<tag> to de deployed by MONAI Inference Service.
    # For example, urn: "ubuntu:latest"
    urn: "my_app:latest"

    # String value which defines entry point command for MAP Container.
    # For example, entrypoint: "/bin/echo Hello"
    entrypoint: "python3 -u /opt/monai/app/app.py"

    # Integer value which defines the CPU limit assigned to the MAP container.
    # This value can not be less than 1.
    cpu: 1

    # Integer value in Megabytes which defines the Memory limit assigned to the MAP container.
    # This value can not be less than 256.
    memory: 7168

    # Integer value which defines the number of GPUs assigned to the MAP container.
    # This value can not be less than 0.
    gpu: 1

    # Input directory path of MAP Container.
    # An environment variable `MONAI_INPUTPATH` is mounted in the MAP container
    # with it's value equal to the one provided for this field.
    inputPath: "/var/monai/input"

    # Output directory path of MAP Container.
    # An environment variable `MONAI_OUTPUTPATH` is mounted in the MAP container
    # with it's value equal to the one provided for this field.
    outputPath: "/var/monai/output"

    # Model directory path of MAP Container.
    # For example, modelPath: /opt/monai/models.
    # An environment variable `MONAI_MODELPATH` is mounted in the MAP container
    # with it's value equal to the one provided for this field.
    modelPath: "/opt/monai/models"
Overwriting charts/values.yaml

Now we are ready to deploy our MIS instance:

!helm install monai-inference-service ./charts/
NAME: monai-inference-service
LAST DEPLOYED: Wed Nov 24 16:06:57 2021
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
!kubectl get po
NAME                                             READY   STATUS              RESTARTS   AGE
clara-clara-platformapiserver-75bc9b4867-q4jvz   1/1     Running             7          68d
clara-console-6d944c97d5-zsxn2                   2/2     Running             10         68d
clara-dicom-adapter-7fb4cc587b-6fn6h             1/1     Running             5          68d
clara-node-monitor-rjb5z                         1/1     Running             5          68d
clara-resultsservice-f758699b-lv56q              1/1     Running             5          68d
clara-ui-758d9645b7-zf9mn                        1/1     Running             5          68d
clara-workflow-controller-7c66d77f55-557js       1/1     Running             7          68d
fluentd-ffrtf                                    1/1     Running             7          68d
monai-inference-service-6bd7d8f5df-ngcfz         0/1     ContainerCreating   0          3s

Inferencing Segmentation AI with MIS

With our MIS instance running as a kubernetes pod, we can now submit REST inferencing requests to it

In the previous chapter, we downloaded our input data for our spleen segmentation application. We just need to compress the dicom files under /dcm into a compressed .zip as MIS accepts that format.

If you have not downloaded the data already, the neccessary gdown command is provided below

# Download ai_spleen_seg_data.zip if not done so already
!pip install gdown 
!gdown https://drive.google.com/uc?id=1uTQsm8omwimBcp_kRXlduWBP2M6cspr1
!unzip -o "ai_spleen_seg_data.zip"

!cd dcm; zip -rq ../input.zip *
!ls input.zip
Requirement already satisfied: gdown in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (4.2.0)
Requirement already satisfied: six in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from gdown) (1.16.0)
Requirement already satisfied: beautifulsoup4 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from gdown) (4.10.0)
Requirement already satisfied: filelock in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from gdown) (3.4.0)
Requirement already satisfied: tqdm in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from gdown) (4.62.3)
Requirement already satisfied: requests[socks] in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from gdown) (2.12.5)
Requirement already satisfied: soupsieve>1.2 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from beautifulsoup4->gdown) (2.3.1)
Requirement already satisfied: PySocks!=1.5.7,>=1.5.6 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from requests[socks]->gdown) (1.7.1)
Downloading...
From: https://drive.google.com/uc?id=1uTQsm8omwimBcp_kRXlduWBP2M6cspr1
To: /data/Vikash/Tools/RSNA/monai-deploy-app-sdk/notebooks/tutorials/ai_spleen_seg_data.zip
100%|████████████████████████████████████████| 104M/104M [00:20<00:00, 4.97MB/s]
Archive:  ai_spleen_seg_data.zip
  inflating: dcm/IMG0001.dcm         
  inflating: dcm/IMG0002.dcm         
  inflating: dcm/IMG0003.dcm         
  inflating: dcm/IMG0004.dcm         
  inflating: dcm/IMG0005.dcm         
  inflating: dcm/IMG0006.dcm         
  inflating: dcm/IMG0007.dcm         
  inflating: dcm/IMG0008.dcm         
  inflating: dcm/IMG0009.dcm         
  inflating: dcm/IMG0010.dcm         
  inflating: dcm/IMG0011.dcm         
  inflating: dcm/IMG0012.dcm         
  inflating: dcm/IMG0013.dcm         
  inflating: dcm/IMG0014.dcm         
  inflating: dcm/IMG0015.dcm         
  inflating: dcm/IMG0016.dcm         
  inflating: dcm/IMG0017.dcm         
  inflating: dcm/IMG0018.dcm         
  inflating: dcm/IMG0019.dcm         
  inflating: dcm/IMG0020.dcm         
  inflating: dcm/IMG0021.dcm         
  inflating: dcm/IMG0022.dcm         
  inflating: dcm/IMG0023.dcm         
  inflating: dcm/IMG0024.dcm         
  inflating: dcm/IMG0025.dcm         
  inflating: dcm/IMG0026.dcm         
  inflating: dcm/IMG0027.dcm         
  inflating: dcm/IMG0028.dcm         
  inflating: dcm/IMG0029.dcm         
  inflating: dcm/IMG0030.dcm         
  inflating: dcm/IMG0031.dcm         
  inflating: dcm/IMG0032.dcm         
  inflating: dcm/IMG0033.dcm         
  inflating: dcm/IMG0034.dcm         
  inflating: dcm/IMG0035.dcm         
  inflating: dcm/IMG0036.dcm         
  inflating: dcm/IMG0037.dcm         
  inflating: dcm/IMG0038.dcm         
  inflating: dcm/IMG0039.dcm         
  inflating: dcm/IMG0040.dcm         
  inflating: dcm/IMG0041.dcm         
  inflating: dcm/IMG0042.dcm         
  inflating: dcm/IMG0043.dcm         
  inflating: dcm/IMG0044.dcm         
  inflating: dcm/IMG0045.dcm         
  inflating: dcm/IMG0046.dcm         
  inflating: dcm/IMG0047.dcm         
  inflating: dcm/IMG0048.dcm         
  inflating: dcm/IMG0049.dcm         
  inflating: dcm/IMG0050.dcm         
  inflating: dcm/IMG0051.dcm         
  inflating: dcm/IMG0052.dcm         
  inflating: dcm/IMG0053.dcm         
  inflating: dcm/IMG0054.dcm         
  inflating: dcm/IMG0055.dcm         
  inflating: dcm/IMG0056.dcm         
  inflating: dcm/IMG0057.dcm         
  inflating: dcm/IMG0058.dcm         
  inflating: dcm/IMG0059.dcm         
  inflating: dcm/IMG0060.dcm         
  inflating: dcm/IMG0061.dcm         
  inflating: dcm/IMG0062.dcm         
  inflating: dcm/IMG0063.dcm         
  inflating: dcm/IMG0064.dcm         
  inflating: dcm/IMG0065.dcm         
  inflating: dcm/IMG0066.dcm         
  inflating: dcm/IMG0067.dcm         
  inflating: dcm/IMG0068.dcm         
  inflating: dcm/IMG0069.dcm         
  inflating: dcm/IMG0070.dcm         
  inflating: dcm/IMG0071.dcm         
  inflating: dcm/IMG0072.dcm         
  inflating: dcm/IMG0073.dcm         
  inflating: dcm/IMG0074.dcm         
  inflating: dcm/IMG0075.dcm         
  inflating: dcm/IMG0076.dcm         
  inflating: dcm/IMG0077.dcm         
  inflating: dcm/IMG0078.dcm         
  inflating: dcm/IMG0079.dcm         
  inflating: dcm/IMG0080.dcm         
  inflating: dcm/IMG0081.dcm         
  inflating: dcm/IMG0082.dcm         
  inflating: dcm/IMG0083.dcm         
  inflating: dcm/IMG0084.dcm         
  inflating: dcm/IMG0085.dcm         
  inflating: dcm/IMG0086.dcm         
  inflating: dcm/IMG0087.dcm         
  inflating: dcm/IMG0088.dcm         
  inflating: dcm/IMG0089.dcm         
  inflating: dcm/IMG0090.dcm         
  inflating: dcm/IMG0091.dcm         
  inflating: dcm/IMG0092.dcm         
  inflating: dcm/IMG0093.dcm         
  inflating: dcm/IMG0094.dcm         
  inflating: dcm/IMG0095.dcm         
  inflating: dcm/IMG0096.dcm         
  inflating: dcm/IMG0097.dcm         
  inflating: dcm/IMG0098.dcm         
  inflating: dcm/IMG0099.dcm         
  inflating: dcm/IMG0100.dcm         
  inflating: dcm/IMG0101.dcm         
  inflating: dcm/IMG0102.dcm         
  inflating: dcm/IMG0103.dcm         
  inflating: dcm/IMG0104.dcm         
  inflating: dcm/IMG0105.dcm         
  inflating: dcm/IMG0106.dcm         
  inflating: dcm/IMG0107.dcm         
  inflating: dcm/IMG0108.dcm         
  inflating: dcm/IMG0109.dcm         
  inflating: dcm/IMG0110.dcm         
  inflating: dcm/IMG0111.dcm         
  inflating: dcm/IMG0112.dcm         
  inflating: dcm/IMG0113.dcm         
  inflating: dcm/IMG0114.dcm         
  inflating: dcm/IMG0115.dcm         
  inflating: dcm/IMG0116.dcm         
  inflating: dcm/IMG0117.dcm         
  inflating: dcm/IMG0118.dcm         
  inflating: dcm/IMG0119.dcm         
  inflating: dcm/IMG0120.dcm         
  inflating: dcm/IMG0121.dcm         
  inflating: dcm/IMG0122.dcm         
  inflating: dcm/IMG0123.dcm         
  inflating: dcm/IMG0124.dcm         
  inflating: dcm/IMG0125.dcm         
  inflating: dcm/IMG0126.dcm         
  inflating: dcm/IMG0127.dcm         
  inflating: dcm/IMG0128.dcm         
  inflating: dcm/IMG0129.dcm         
  inflating: dcm/IMG0130.dcm         
  inflating: dcm/IMG0131.dcm         
  inflating: dcm/IMG0132.dcm         
  inflating: dcm/IMG0133.dcm         
  inflating: dcm/IMG0134.dcm         
  inflating: dcm/IMG0135.dcm         
  inflating: dcm/IMG0136.dcm         
  inflating: dcm/IMG0137.dcm         
  inflating: dcm/IMG0138.dcm         
  inflating: dcm/IMG0139.dcm         
  inflating: dcm/IMG0140.dcm         
  inflating: dcm/IMG0141.dcm         
  inflating: dcm/IMG0142.dcm         
  inflating: dcm/IMG0143.dcm         
  inflating: dcm/IMG0144.dcm         
  inflating: dcm/IMG0145.dcm         
  inflating: dcm/IMG0146.dcm         
  inflating: dcm/IMG0147.dcm         
  inflating: dcm/IMG0148.dcm         
  inflating: dcm/IMG0149.dcm         
  inflating: dcm/IMG0150.dcm         
  inflating: dcm/IMG0151.dcm         
  inflating: dcm/IMG0152.dcm         
  inflating: dcm/IMG0153.dcm         
  inflating: dcm/IMG0154.dcm         
  inflating: dcm/IMG0155.dcm         
  inflating: dcm/IMG0156.dcm         
  inflating: dcm/IMG0157.dcm         
  inflating: dcm/IMG0158.dcm         
  inflating: dcm/IMG0159.dcm         
  inflating: dcm/IMG0160.dcm         
  inflating: dcm/IMG0161.dcm         
  inflating: dcm/IMG0162.dcm         
  inflating: dcm/IMG0163.dcm         
  inflating: dcm/IMG0164.dcm         
  inflating: dcm/IMG0165.dcm         
  inflating: dcm/IMG0166.dcm         
  inflating: dcm/IMG0167.dcm         
  inflating: dcm/IMG0168.dcm         
  inflating: dcm/IMG0169.dcm         
  inflating: dcm/IMG0170.dcm         
  inflating: dcm/IMG0171.dcm         
  inflating: dcm/IMG0172.dcm         
  inflating: dcm/IMG0173.dcm         
  inflating: dcm/IMG0174.dcm         
  inflating: dcm/IMG0175.dcm         
  inflating: dcm/IMG0176.dcm         
  inflating: dcm/IMG0177.dcm         
  inflating: dcm/IMG0178.dcm         
  inflating: dcm/IMG0179.dcm         
  inflating: dcm/IMG0180.dcm         
  inflating: dcm/IMG0181.dcm         
  inflating: dcm/IMG0182.dcm         
  inflating: dcm/IMG0183.dcm         
  inflating: dcm/IMG0184.dcm         
  inflating: dcm/IMG0185.dcm         
  inflating: dcm/IMG0186.dcm         
  inflating: dcm/IMG0187.dcm         
  inflating: dcm/IMG0188.dcm         
  inflating: dcm/IMG0189.dcm         
  inflating: dcm/IMG0190.dcm         
  inflating: dcm/IMG0191.dcm         
  inflating: dcm/IMG0192.dcm         
  inflating: dcm/IMG0193.dcm         
  inflating: dcm/IMG0194.dcm         
  inflating: dcm/IMG0195.dcm         
  inflating: dcm/IMG0196.dcm         
  inflating: dcm/IMG0197.dcm         
  inflating: dcm/IMG0198.dcm         
  inflating: dcm/IMG0199.dcm         
  inflating: dcm/IMG0200.dcm         
  inflating: dcm/IMG0201.dcm         
  inflating: dcm/IMG0202.dcm         
  inflating: dcm/IMG0203.dcm         
  inflating: dcm/IMG0204.dcm         
  inflating: dcm/IMG0205.dcm         
  inflating: dcm/IMG0206.dcm         
  inflating: dcm/IMG0207.dcm         
  inflating: dcm/IMG0208.dcm         
  inflating: dcm/IMG0209.dcm         
  inflating: dcm/IMG0210.dcm         
  inflating: dcm/IMG0211.dcm         
  inflating: dcm/IMG0212.dcm         
  inflating: dcm/IMG0213.dcm         
  inflating: dcm/IMG0214.dcm         
  inflating: dcm/IMG0215.dcm         
  inflating: dcm/IMG0216.dcm         
  inflating: dcm/IMG0217.dcm         
  inflating: dcm/IMG0218.dcm         
  inflating: dcm/IMG0219.dcm         
  inflating: dcm/IMG0220.dcm         
  inflating: dcm/IMG0221.dcm         
  inflating: dcm/IMG0222.dcm         
  inflating: dcm/IMG0223.dcm         
  inflating: dcm/IMG0224.dcm         
  inflating: dcm/IMG0225.dcm         
  inflating: dcm/IMG0226.dcm         
  inflating: dcm/IMG0227.dcm         
  inflating: dcm/IMG0228.dcm         
  inflating: dcm/IMG0229.dcm         
  inflating: dcm/IMG0230.dcm         
  inflating: dcm/IMG0231.dcm         
  inflating: dcm/IMG0232.dcm         
  inflating: dcm/IMG0233.dcm         
  inflating: dcm/IMG0234.dcm         
  inflating: dcm/IMG0235.dcm         
  inflating: dcm/IMG0236.dcm         
  inflating: dcm/IMG0237.dcm         
  inflating: dcm/IMG0238.dcm         
  inflating: dcm/IMG0239.dcm         
  inflating: dcm/IMG0240.dcm         
  inflating: dcm/IMG0241.dcm         
  inflating: dcm/IMG0242.dcm         
  inflating: dcm/IMG0243.dcm         
  inflating: dcm/IMG0244.dcm         
  inflating: dcm/IMG0245.dcm         
  inflating: dcm/IMG0246.dcm         
  inflating: dcm/IMG0247.dcm         
  inflating: dcm/IMG0248.dcm         
  inflating: dcm/IMG0249.dcm         
  inflating: dcm/IMG0250.dcm         
  inflating: dcm/IMG0251.dcm         
  inflating: dcm/IMG0252.dcm         
  inflating: dcm/IMG0253.dcm         
  inflating: dcm/IMG0254.dcm         
  inflating: dcm/IMG0255.dcm         
  inflating: dcm/IMG0256.dcm         
  inflating: dcm/IMG0257.dcm         
  inflating: dcm/IMG0258.dcm         
  inflating: dcm/IMG0259.dcm         
  inflating: dcm/IMG0260.dcm         
  inflating: dcm/IMG0261.dcm         
  inflating: dcm/IMG0262.dcm         
  inflating: dcm/IMG0263.dcm         
  inflating: dcm/IMG0264.dcm         
  inflating: dcm/IMG0265.dcm         
  inflating: dcm/IMG0266.dcm         
  inflating: dcm/IMG0267.dcm         
  inflating: dcm/IMG0268.dcm         
  inflating: dcm/IMG0269.dcm         
  inflating: dcm/IMG0270.dcm         
  inflating: dcm/IMG0271.dcm         
  inflating: dcm/IMG0272.dcm         
  inflating: dcm/IMG0273.dcm         
  inflating: dcm/IMG0274.dcm         
  inflating: dcm/IMG0275.dcm         
  inflating: dcm/IMG0276.dcm         
  inflating: dcm/IMG0277.dcm         
  inflating: dcm/IMG0278.dcm         
  inflating: dcm/IMG0279.dcm         
  inflating: dcm/IMG0280.dcm         
  inflating: dcm/IMG0281.dcm         
  inflating: dcm/IMG0282.dcm         
  inflating: dcm/IMG0283.dcm         
  inflating: dcm/IMG0284.dcm         
  inflating: dcm/IMG0285.dcm         
  inflating: dcm/IMG0286.dcm         
  inflating: dcm/IMG0287.dcm         
  inflating: dcm/IMG0288.dcm         
  inflating: dcm/IMG0289.dcm         
  inflating: dcm/IMG0290.dcm         
  inflating: dcm/IMG0291.dcm         
  inflating: dcm/IMG0292.dcm         
  inflating: dcm/IMG0293.dcm         
  inflating: dcm/IMG0294.dcm         
  inflating: dcm/IMG0295.dcm         
  inflating: dcm/IMG0296.dcm         
  inflating: dcm/IMG0297.dcm         
  inflating: dcm/IMG0298.dcm         
  inflating: dcm/IMG0299.dcm         
  inflating: dcm/IMG0300.dcm         
  inflating: dcm/IMG0301.dcm         
  inflating: dcm/IMG0302.dcm         
  inflating: dcm/IMG0303.dcm         
  inflating: dcm/IMG0304.dcm         
  inflating: dcm/IMG0305.dcm         
  inflating: dcm/IMG0306.dcm         
  inflating: dcm/IMG0307.dcm         
  inflating: dcm/IMG0308.dcm         
  inflating: dcm/IMG0309.dcm         
  inflating: dcm/IMG0310.dcm         
  inflating: dcm/IMG0311.dcm         
  inflating: dcm/IMG0312.dcm         
  inflating: dcm/IMG0313.dcm         
  inflating: dcm/IMG0314.dcm         
  inflating: dcm/IMG0315.dcm         
  inflating: dcm/IMG0316.dcm         
  inflating: dcm/IMG0317.dcm         
  inflating: dcm/IMG0318.dcm         
  inflating: dcm/IMG0319.dcm         
  inflating: dcm/IMG0320.dcm         
  inflating: dcm/IMG0321.dcm         
  inflating: dcm/IMG0322.dcm         
  inflating: dcm/IMG0323.dcm         
  inflating: dcm/IMG0324.dcm         
  inflating: dcm/IMG0325.dcm         
  inflating: dcm/IMG0326.dcm         
  inflating: dcm/IMG0327.dcm         
  inflating: dcm/IMG0328.dcm         
  inflating: dcm/IMG0329.dcm         
  inflating: dcm/IMG0330.dcm         
  inflating: dcm/IMG0331.dcm         
  inflating: dcm/IMG0332.dcm         
  inflating: dcm/IMG0333.dcm         
  inflating: dcm/IMG0334.dcm         
  inflating: dcm/IMG0335.dcm         
  inflating: dcm/IMG0336.dcm         
  inflating: dcm/IMG0337.dcm         
  inflating: dcm/IMG0338.dcm         
  inflating: dcm/IMG0339.dcm         
  inflating: dcm/IMG0340.dcm         
  inflating: dcm/IMG0341.dcm         
  inflating: dcm/IMG0342.dcm         
  inflating: dcm/IMG0343.dcm         
  inflating: dcm/IMG0344.dcm         
  inflating: dcm/IMG0345.dcm         
  inflating: dcm/IMG0346.dcm         
  inflating: dcm/IMG0347.dcm         
  inflating: dcm/IMG0348.dcm         
  inflating: dcm/IMG0349.dcm         
  inflating: dcm/IMG0350.dcm         
  inflating: dcm/IMG0351.dcm         
  inflating: dcm/IMG0352.dcm         
  inflating: dcm/IMG0353.dcm         
  inflating: dcm/IMG0354.dcm         
  inflating: dcm/IMG0355.dcm         
  inflating: dcm/IMG0356.dcm         
  inflating: dcm/IMG0357.dcm         
  inflating: dcm/IMG0358.dcm         
  inflating: dcm/IMG0359.dcm         
  inflating: dcm/IMG0360.dcm         
  inflating: dcm/IMG0361.dcm         
  inflating: dcm/IMG0362.dcm         
  inflating: dcm/IMG0363.dcm         
  inflating: dcm/IMG0364.dcm         
  inflating: dcm/IMG0365.dcm         
  inflating: dcm/IMG0366.dcm         
  inflating: dcm/IMG0367.dcm         
  inflating: dcm/IMG0368.dcm         
  inflating: dcm/IMG0369.dcm         
  inflating: dcm/IMG0370.dcm         
  inflating: dcm/IMG0371.dcm         
  inflating: dcm/IMG0372.dcm         
  inflating: dcm/IMG0373.dcm         
  inflating: dcm/IMG0374.dcm         
  inflating: dcm/IMG0375.dcm         
  inflating: dcm/IMG0376.dcm         
  inflating: dcm/IMG0377.dcm         
  inflating: dcm/IMG0378.dcm         
  inflating: dcm/IMG0379.dcm         
  inflating: dcm/IMG0380.dcm         
  inflating: dcm/IMG0381.dcm         
  inflating: dcm/IMG0382.dcm         
  inflating: dcm/IMG0383.dcm         
  inflating: dcm/IMG0384.dcm         
  inflating: dcm/IMG0385.dcm         
  inflating: dcm/IMG0386.dcm         
  inflating: dcm/IMG0387.dcm         
  inflating: dcm/IMG0388.dcm         
  inflating: dcm/IMG0389.dcm         
  inflating: dcm/IMG0390.dcm         
  inflating: dcm/IMG0391.dcm         
  inflating: dcm/IMG0392.dcm         
  inflating: dcm/IMG0393.dcm         
  inflating: dcm/IMG0394.dcm         
  inflating: dcm/IMG0395.dcm         
  inflating: dcm/IMG0396.dcm         
  inflating: dcm/IMG0397.dcm         
  inflating: dcm/IMG0398.dcm         
  inflating: dcm/IMG0399.dcm         
  inflating: dcm/IMG0400.dcm         
  inflating: dcm/IMG0401.dcm         
  inflating: dcm/IMG0402.dcm         
  inflating: dcm/IMG0403.dcm         
  inflating: dcm/IMG0404.dcm         
  inflating: dcm/IMG0405.dcm         
  inflating: dcm/IMG0406.dcm         
  inflating: dcm/IMG0407.dcm         
  inflating: dcm/IMG0408.dcm         
  inflating: dcm/IMG0409.dcm         
  inflating: dcm/IMG0410.dcm         
  inflating: dcm/IMG0411.dcm         
  inflating: dcm/IMG0412.dcm         
  inflating: dcm/IMG0413.dcm         
  inflating: dcm/IMG0414.dcm         
  inflating: dcm/IMG0415.dcm         
  inflating: dcm/IMG0416.dcm         
  inflating: dcm/IMG0417.dcm         
  inflating: dcm/IMG0418.dcm         
  inflating: dcm/IMG0419.dcm         
  inflating: dcm/IMG0420.dcm         
  inflating: dcm/IMG0421.dcm         
  inflating: dcm/IMG0422.dcm         
  inflating: dcm/IMG0423.dcm         
  inflating: dcm/IMG0424.dcm         
  inflating: dcm/IMG0425.dcm         
  inflating: dcm/IMG0426.dcm         
  inflating: dcm/IMG0427.dcm         
  inflating: dcm/IMG0428.dcm         
  inflating: dcm/IMG0429.dcm         
  inflating: dcm/IMG0430.dcm         
  inflating: dcm/IMG0431.dcm         
  inflating: dcm/IMG0432.dcm         
  inflating: dcm/IMG0433.dcm         
  inflating: dcm/IMG0434.dcm         
  inflating: dcm/IMG0435.dcm         
  inflating: dcm/IMG0436.dcm         
  inflating: dcm/IMG0437.dcm         
  inflating: dcm/IMG0438.dcm         
  inflating: dcm/IMG0439.dcm         
  inflating: dcm/IMG0440.dcm         
  inflating: dcm/IMG0441.dcm         
  inflating: dcm/IMG0442.dcm         
  inflating: dcm/IMG0443.dcm         
  inflating: dcm/IMG0444.dcm         
  inflating: dcm/IMG0445.dcm         
  inflating: dcm/IMG0446.dcm         
  inflating: dcm/IMG0447.dcm         
  inflating: dcm/IMG0448.dcm         
  inflating: dcm/IMG0449.dcm         
  inflating: dcm/IMG0450.dcm         
  inflating: dcm/IMG0451.dcm         
  inflating: dcm/IMG0452.dcm         
  inflating: dcm/IMG0453.dcm         
  inflating: dcm/IMG0454.dcm         
  inflating: dcm/IMG0455.dcm         
  inflating: dcm/IMG0456.dcm         
  inflating: dcm/IMG0457.dcm         
  inflating: dcm/IMG0458.dcm         
  inflating: dcm/IMG0459.dcm         
  inflating: dcm/IMG0460.dcm         
  inflating: dcm/IMG0461.dcm         
  inflating: dcm/IMG0462.dcm         
  inflating: dcm/IMG0463.dcm         
  inflating: dcm/IMG0464.dcm         
  inflating: dcm/IMG0465.dcm         
  inflating: dcm/IMG0466.dcm         
  inflating: dcm/IMG0467.dcm         
  inflating: dcm/IMG0468.dcm         
  inflating: dcm/IMG0469.dcm         
  inflating: dcm/IMG0470.dcm         
  inflating: dcm/IMG0471.dcm         
  inflating: dcm/IMG0472.dcm         
  inflating: dcm/IMG0473.dcm         
  inflating: dcm/IMG0474.dcm         
  inflating: dcm/IMG0475.dcm         
  inflating: dcm/IMG0476.dcm         
  inflating: dcm/IMG0477.dcm         
  inflating: dcm/IMG0478.dcm         
  inflating: dcm/IMG0479.dcm         
  inflating: dcm/IMG0480.dcm         
  inflating: dcm/IMG0481.dcm         
  inflating: dcm/IMG0482.dcm         
  inflating: dcm/IMG0483.dcm         
  inflating: dcm/IMG0484.dcm         
  inflating: dcm/IMG0485.dcm         
  inflating: dcm/IMG0486.dcm         
  inflating: dcm/IMG0487.dcm         
  inflating: dcm/IMG0488.dcm         
  inflating: dcm/IMG0489.dcm         
  inflating: dcm/IMG0490.dcm         
  inflating: dcm/IMG0491.dcm         
  inflating: dcm/IMG0492.dcm         
  inflating: dcm/IMG0493.dcm         
  inflating: dcm/IMG0494.dcm         
  inflating: dcm/IMG0495.dcm         
  inflating: dcm/IMG0496.dcm         
  inflating: dcm/IMG0497.dcm         
  inflating: dcm/IMG0498.dcm         
  inflating: dcm/IMG0499.dcm         
  inflating: dcm/IMG0500.dcm         
  inflating: dcm/IMG0501.dcm         
  inflating: dcm/IMG0502.dcm         
  inflating: dcm/IMG0503.dcm         
  inflating: dcm/IMG0504.dcm         
  inflating: dcm/IMG0505.dcm         
  inflating: dcm/IMG0506.dcm         
  inflating: dcm/IMG0507.dcm         
  inflating: dcm/IMG0508.dcm         
  inflating: dcm/IMG0509.dcm         
  inflating: dcm/IMG0510.dcm         
  inflating: dcm/IMG0511.dcm         
  inflating: dcm/IMG0512.dcm         
  inflating: dcm/IMG0513.dcm         
  inflating: dcm/IMG0514.dcm         
  inflating: dcm/IMG0515.dcm         
  inflating: model.pt                
input.zip

Now that we have our compressed .zip, we can now making an inferencing request to our MIS instance using curl

Usage:

curl -X 'POST' 'http://[CLUSTER-IP:8000 OR HOST-IP:32000]/upload/' \
    -H 'accept: application/json' \
    -H 'Content-Type: multipart/form-data' \
    -F 'file=@[PATH TO INPUT PAYLOAD ZIP];type=application/x-zip-compressed' \
    -o output.zip

You can obtain the cluster IP of the MIS Kubernetes service by doing a kubectl get svc.

For example,

user@hostname:~$ kubectl get svc
NAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
kubernetes                ClusterIP   10.96.0.1      <none>        443/TCP          8d
monai-inference-service   NodePort    10.97.138.32   <none>        8000:32000/TCP   4s

Under the entry monai-inference-service, note the IP registered under the CLUSTER-IP section. This is the Cluster IP of the MIS.

!curl -X 'POST' 'http://localhost:8000/upload/' \
    -H 'accept: application/json' \
    -H 'Content-Type: multipart/form-data' \
    -F 'file=@input.zip;type=application/x-zip-compressed' \
    -o output.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 86.5M  100  1018  100 86.5M   7953   675M --:--:-- --:--:-- --:--:--  675M
!unzip -o output.zip
Archive:  output.zip
  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
unzip:  cannot find zipfile directory in one of output.zip or
        output.zip.zip, and cannot find output.zip.ZIP, period.
!pip install nilearn matplotlib
def visualize_output(predicted_output: str):
    import SimpleITK as sitk
    reader = sitk.ImageSeriesReader()
    dicom_names = reader.GetGDCMSeriesFileNames('./dcm')
    reader.SetFileNames(dicom_names)
    input_image = reader.Execute()

    writer = sitk.ImageFileWriter()
    writer.SetFileName('input.nii.gz')
    writer.Execute(input_image)

    import nibabel as nib
    input_image_nib = nib.load('input.nii.gz')

    image_itk = nib.load(predicted_output)

    from nilearn import plotting, image
    display = plotting.plot_anat(input_image_nib, cut_coords=(123, 162, 387), colorbar=False)
    display.add_overlay(image_itk)

visualize_output("./output/prediction_output/1.2.826.0.1.3680043.2.1125.1/1.2.826.0.1.3680043.2.1125.1_seg.nii.gz")
Requirement already satisfied: nilearn in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (0.8.1)
Requirement already satisfied: matplotlib in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (3.3.4)
Requirement already satisfied: pandas>=0.24.0 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from nilearn) (1.1.5)
Requirement already satisfied: numpy>=1.16 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from nilearn) (1.19.2)
Requirement already satisfied: scikit-learn>=0.21 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from nilearn) (0.24.2)
Requirement already satisfied: nibabel>=2.5 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from nilearn) (3.2.1)
Requirement already satisfied: requests>=2 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from nilearn) (2.12.5)
Requirement already satisfied: joblib>=0.12 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from nilearn) (1.1.0)
Requirement already satisfied: scipy>=1.2 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from nilearn) (1.5.4)
Requirement already satisfied: cycler>=0.10 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from matplotlib) (0.11.0)
Requirement already satisfied: python-dateutil>=2.1 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from matplotlib) (2.8.2)
Requirement already satisfied: kiwisolver>=1.0.1 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from matplotlib) (1.3.1)
Requirement already satisfied: pillow>=6.2.0 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from matplotlib) (8.3.1)
Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.3 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from matplotlib) (3.0.4)
Requirement already satisfied: packaging>=14.3 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from nibabel>=2.5->nilearn) (21.3)
Requirement already satisfied: pytz>=2017.2 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from pandas>=0.24.0->nilearn) (2021.3)
Requirement already satisfied: six>=1.5 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from python-dateutil>=2.1->matplotlib) (1.16.0)
Requirement already satisfied: threadpoolctl>=2.0.0 in /home/gupta/miniconda3/envs/monairsna/lib/python3.6/site-packages (from scikit-learn>=0.21->nilearn) (3.0.0)
../../_images/04_mis_tutorial_19_1.png

Uninstalling MONAI Inference Service

!helm uninstall monai-inference-service
release "monai-inference-service" uninstalled